zoukankan      html  css  js  c++  java
  • Spring AOP 动态代理(二)

    简介

    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 {
        	    <!--
        	    isOptimize和isProxyTargetClass默认是false 
        	    hasNoUserSuppliedProxyInterfaces的判断当前类是否有接口的实现
        	    -->
        		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 在处理动态代理 代码 后面的源码 后面有时间在跟进去 分析一遍 ,时间限制 写的比较简单 后面会深入分析一下

  • 相关阅读:
    企业云盘安全性如何 怎样部署
    Sentinel 控制台部署
    nginx代理静态页面添加二级目录
    java socket
    IDEA
    golang代码生成器
    es 单节点问题
    代码模板
    错误摘要 HTTP 错误 403.14
    安装.Net Framework 4.6.2无法安装的2种情况
  • 原文地址:https://www.cnblogs.com/burg-xun/p/12865269.html
Copyright © 2011-2022 走看看