Spring AOP 动态代理(二)

Fiona ·
更新时间:2024-11-13
· 621 次阅读

简介

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 关注 私信 展开阅读全文
作者:burgxun



spring 代理 动态代理 aop 动态

需要 登录 后方可回复, 如果你还没有账号请 注册新账号