Spring AOP 大家在使用Spring 框架 一定非常的熟悉
Spring AOP 的本质其实就是实现了动态代理,这个和Aspectj不一样,AspectJ 是直接修改你的字节码 完成的
代理模式其实很简单 主要包括 接口+真实的实现类+代理类 在真实类的实例化的时候 使用代理类,所以需要 Spring AOP 做的是生成一个代理类,然后替换真实的类 去对外提供服务
那怎么去替换呢?
就是Spring IOC 容器中获取Bean–getBean()的是时候IOC容器返回的时候 代理类的实例 而非真实类的实例,这个代理类 我们没有写任何的代码去实现,是通过java的动态代理或者CGLIB的代理去实现的
2种代理技术的对比那为什有2中动态代理技术呢?是因为java的动态代理需要真实类实现一个接口,这就限制了我们的使用,而CGLIB 则不需要,一个普通的类和实现接口的类都是可以被代理的,Spring AOP中默认是用的Java的动态代理。
那Java的动态代理为什么有这个限制呢?是因为生成的代理类的父类是Proxy类 而Java中普通的类默认都是父类都是Object类的,但是Java 不允许多继承 所以只能代理实现接口的类
二者的比较
Java原生的API进行操作,在生成类上比较高效,CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效
Java 动态代理/**
* @ClassName OrderService
* @Auther burgxun
* @Description: 订单服务接口
* @Date 2020/4/22 1:33
**/
public interface OrderService {
void subOrder(User user);
}
/**
* @ClassName OrderServiceImpl
* @Auther burgxun
* @Description: 订单服务接口的实现类
* @Date 2020/4/23 0:47
**/
public class OrderServiceImpl implements OrderService {
@Override
public void subOrder(User user) {
System.out.println("执行下单逻辑,user:" + user.toString());
}
}
/**
* @ClassName OrderServiceInvocationHandler
* @Auther burgxun
* @Description: JDK 实现的动态代理
* @Date 2020/4/23 0:49
**/
public class OrderServiceInvocationHandler implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("===============方法调用前处理==========");
result = method.invoke(target, args);
//System.out.println(proxy);
System.out.println("===============方法调用后处理==========");
return result;
}
}
CGLIB 动态代理
/**
* @ClassName OrderServiceMethodIntercepter
* @Auther burgxun
* @Description: CGLIB 实现的动态代理
* @Date 2020/4/27 16:21
**/
public class OrderServiceMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("=====调用前处理=====" + method.getName());
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("=====调用后处理=====");
return object;
}
}
二者的使用
/**
* @ClassName SpringProxyTest
* @Auther burgxun
* @Description:
* @Date 2020/4/23 1:04
**/
public class SpringProxyTest {
public static void main(String[] args) {
/*JDK 实现动态代理*/
OrderServiceImpl serviceImpl = new OrderServiceImpl();
OrderServiceInvocationHandler invocationHandler = new OrderServiceInvocationHandler();
OrderService service = (OrderService) invocationHandler.bind(serviceImpl);
service.subOrder(new User("fei", "yang"));
/*CGLIB 实现的代理*/
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderServiceImpl.class);
enhancer.setCallback(new OrderServiceMethodInterceptor());
OrderServiceImpl serviceImplForCGLIB = (OrderServiceImpl) enhancer.create();
serviceImplForCGLIB.subOrder(new User("burg", "xun"));
}
}
执行的结果:
Java动态代理---方法调用前处理==========
执行下单逻辑,user:fei:yang-0
Java动态代理---方法调用后处理==========
CGLIB动态代理---调用前处理=====subOrder
执行下单逻辑,user:burg:xun-0
CGLIB动态代理---调用后处理=====
Spring 源码
/**
* ProxyFactory 类中
*/
public class ProxyFactory extends ProxyCreatorSupport {
/**
* 返回代理一个代理
*/
public Object getProxy() {
return createAopProxy().getProxy();
}
}
createAopProxy()方式是在ProxyCreatorSupport的父类方法中,进入ProxyCreatorSupport中去看
/**
* ProxyCreatorSupport 类中
*/
public class ProxyCreatorSupport extends AdvisedSupport {
private AopProxyFactory aopProxyFactory;
/**
* 默认的构造函数 aopProxyFactory 默认实现是DefaultAopProxyFactory
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
/**
* 子类调用此方法 得到一个AopProxy的对象
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
}
aopProxyFactory的默认实现是DefaultAopProxyFactory 所以createAopProxy也是调用此类的方法
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);//CGLIB的动态代理
}
else {
return new JdkDynamicAopProxy(config);//JDK的动态代理
}
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
上面就是AOP 在处理动态代理 代码 后面的源码 后面有时间在跟进去 分析一遍 ,时间限制 写的比较简单 后面会深入分析一下
burgxun 原创文章 13获赞 22访问量 1133 关注 私信 展开阅读全文