spring 动态代理

依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中
创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者
因此也称为依赖注入。

spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。
设置注入的优点:直观,自然
构造注入的优点:可以在构造器中决定依赖关系的顺序。


 

IOC:控制反转,是一种设计模式。一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制;

          第二层是依赖注入:将相互依赖的对象分离,在spring配置文件中描述他们的依赖关系。他们的依赖关系只在使用的时候才建立。 

 

 

      AOP:面向切面,是一种编程思想,OOP的延续。将系统中非核心的业务提取出来,进行单独处理。比如事务、日志和安全等。

 

  Spring的AOP和IOC都是为了解决系统代码耦合度过高的问题。使代码重用度高、易于维护。 

        不过AOP和IOC并不是spring中特有的,只是spring把他们应用的更灵活方便 。


原理区别:

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

 


如何强制使用CGLIB实现AOP?
* 添加CGLIB库,SPRING_HOME/cglib/*.jar
* 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLIB字节码生成的区别?
* JDK动态代理只能对实现了接口的类生成代理,而不能针对类
* CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
  因为是继承,所以该类或方法最好不要声明成final



Spring Aop 要拦截某些类的话,那会判断这个类是否实现了接口,如果实现了接口就会用jdk 动态代理来创建代理对象;如果没有这个类没有实现接口情况下,则用CGLIB来创建代理对象;

 JDK动态代理

  1. public class JDKProxy implements InvocationHandler {
  2.     private Object targetObject;//代理的目标对象
  3.     public Object createProxyInstance(Object targetObject){
  4.         this.targetObject = targetObject;
  5. /*
  6. * 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
  7. * 第二个参数设置代理类实现的接口
  8. * 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法
  9. */
  10.         return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
  11.                 this.targetObject.getClass().getInterfaces(), this);
  12.     }
  13.     public Object invoke(Object proxy, Method method, Object[] args)
  14.             throws Throwable {
  15.         return method.invoke(this.targetObject, args);//把方法调用委派给目标对象
  16.     }
  17. }


    当目标类实现了接口,我们可以使用jdk的Proxy来生成代理对象。

使用CGLIB生成代理

  1. public class CGLIBProxy implements MethodInterceptor {
  2.     private Object targetObject;//代理的目标对象    
  3.     public Object createProxyInstance(Object targetObject){
  4.         this.targetObject = targetObject;
  5.         Enhancer enhancer = new Enhancer();//该类用于生成代理对象
  6.         enhancer.setSuperclass(this.targetObject.getClass());//设置父类
  7.         enhancer.setCallback(this);//设置回调用对象为本身
  8.         return enhancer.create();
  9.     }
  10.     public Object intercept(Object proxy, Method method, Object[] args,
  11.             MethodProxy methodProxy) throws Throwable {
  12.         return methodProxy.invoke(this.targetObject, args);
  13.     }
  14. }

  15. CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值