AOP底层原理
-
静态代理
-
动态代理——Proxy
-
动态代理——CGLIB
-
织入形式
1)静态代理**
装饰者模式(Decorator Pattern):在不惊动原始设计的基础上,为其添加功能
public class UserServiceDecorator implements UserService{
private UserService userService;
public UserServiceDecorator(UserService userService) {
this.userService = userService;
}
public void save() {
//原始调用
userService.save();
//增强功能(后置)
System.out.println("刮大白");
}
}
测试
public class App {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService userService1 = new UserServiceImplDecorator(userService);
userService1.save();
}
}
运行结果
2)动态代理——JDK Proxy
JDKProxy动态代理是针对对象做代理,要求原始对象具有接口实现,并对接口方法进行增强
public class UserServiceJDKProxy {
public UserService createUserServiceJDKProxy(final UserService userService){
//获取被代理对象的类加载器
ClassLoader classLoader = userService.getClass().getClassLoader();
//获取被代理对象实现的接口
Class[] classes = userService.getClass().getInterfaces();
//对原始方法执行进行拦截并增强
InvocationHandler ih = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置增强内容
Object ret = method.invoke(userService, args);
//后置增强内容
System.out.println("刮大白2");
return ret;
}
};
//使用原始被代理对象创建新的代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(classLoader,classes,ih);
return proxy;
}
}
测试
public class App {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService userService1 = UserServiceJDKProxy.createUserServiceJDKProxy(userService);
userService1.save();
}
}
运行结果
3)动态代理——CGLIB
-
CGLIB(Code Generation Library),Code生成类库
-
CGLIB动态代理不限定是否具有接口,可以对任意操作进行增强
-
CGLIB动态代理无需要原始被代理对象,动态创建出新的代理对象
代码实现
public class UserServiceImplCglibProxy {
public static UserServiceImpl createUserServiceCglibProxy(Class clazz){
//创建Enhancer对象(可以理解为内存中动态创建了一个类的字节码)
Enhancer enhancer = new Enhancer();
//设置Enhancer对象的父类是指定类型UserServerImpl
enhancer.setSuperclass(clazz);
Callback cb = new MethodInterceptor() {
public Object intercept(Object o, Method m, Object[] a, MethodProxy mp) throws Throwable {
Object ret = mp.invokeSuper(o, a);
if(m.getName().equals("save")) {
System.out.println("刮大白");
}
return ret;
}
};
//设置回调方法
enhancer.setCallback(cb);
//使用Enhancer对象创建对应的对象
return (UserServiceImpl)enhancer.create();
}
}
测试App
public class App {
public static void main(String[] args) {
UserService userService = UserServiceCglibProxy.createUserServiceCglibProxy(UserServiceImpl.class);
userService.save();
}
}
运行结果
4)代理模式的选择
Spirng可以通过配置的形式控制使用的代理形式,默认使用jdkproxy,通过配置可以修改为使用cglib
-
XML配置
<!--XMP配置AOP--> <aop:config proxy-target-class="false"></aop:config>
-
XML注解支持
<!--注解配置AOP--> <aop:aspectj-autoproxy proxy-target-class="false"/>
-
注解驱动
//注解驱动 @EnableAspectJAutoProxy(proxyTargetClass = true)