Spring的AOP实现原理,动态代理。

血红的双手。 提交于 2019-11-28 03:28:43

AOP面向切片编程,实现原理就是动态代理,动态代理又分为JDK动态代理和CGLIB动态代理。

1,JDK动态代理智能实现对接口的代理

    1. public class UserManagerImpl implements UserManager {  
    2.   
    3.     @Override  
    4.     public void addString userId, String userName) {  
    5.         System.out.println("UserManagerImpl.addUser");  
    6.     }  
    7.   
    8.     @Override  
    9.     public void dellet(String userId) {  
    10.         System.out.println("UserManagerImpl.delUser");  
    11.     }  

//动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类  

    1. public class LogHandler implements InvocationHandler {  
    2. private Object targetObject;  
    3. //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。              
    4. public Object newProxyInstance(Object targetObject){  
    5. this.targetObject=targetObject;  
    6. //该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例    
    7. //第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器  
    8. //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口  
    9. //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法  
    10. //根据传入的目标返回一个代理对象  
    11. return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
    12.                 targetObject.getClass().getInterfaces(),this);  
    13.     }  
    14. @Override  
    15. //关联的这个实现类的方法被调用时将被执行  
    16. /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/  
    17. public Object invoke(Object proxy, Method method, Object[] args)  
    18. throws Throwable {  
    19.         System.out.println("start-->>");  
    20. for(int i=0;i<args.length;i++){  
    21.             System.out.println(args[i]);  
    22.         }  
    23.         Object ret=null;  
    24. try{  
    25. /*原对象方法调用前处理日志信息*/  
    26.             System.out.println("satrt-->>");  
    27. //调用目标方法  
    28.             ret=method.invoke(targetObject, args);  
    29. /*原对象方法调用后处理日志信息*/  
    30.             System.out.println("success-->>");  
    31.         }catch(Exception e){  
    32.             e.printStackTrace();  
    33.             System.out.println("error-->>");  
    34. throw e;  
    35.         }  
  •         return ret;  
  1.     }  
  2. 被代理对象targetObject通过参数传递进来,我们通过targetObject.getClass().getClassLoader()获取ClassLoader对象,然后通过targetObject.getClass().getInterfaces()获取它实现的所有接口,然后将targetObject包装到实现了InvocationHandler接口的LogHandler对象中。通过newProxyInstance函数我们就获得了一个动态代理对象。

    1. public class Client {  
    2. public static void main(String[] args){  
    3.         LogHandler logHandler=new LogHandler();  
    4.         UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());  
    5. //UserManager userManager=new UserManagerImpl();  
    6.         userManager.addUser("1111", "张三");  
    7.     }  
    8. }
  3. CGLIB可以接口可以类
    cglib的代理方式不需要传入被代理对象实例即可完成动态代理。cglib和jdk代理有什么区别呢?jdk的代理对象与被代理对象实现了同一接口,底层通过clone()方法,将实现类的方法复制过来在按照invoke中的配置对方法进行增强。而cglib代理则是代理对象继承了被代理对象的方法,然后自身进行增强。这两种代理思想在外来的自动生成代码方向会经常被使用,实现完全体代码的复用性。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!