您的位置:首页 > 编程语言 > Java开发

spring 动态代理

2015-07-04 15:46 405 查看

依赖注入(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动态代理

public class JDKProxy
implements InvocationHandler
{

private Object targetObject;//代理的目标对象

public Object createProxyInstance(Object targetObject){

this.targetObject
= targetObject;

/*

* 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器

* 第二个参数设置代理类实现的接口

* 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法

*/

return
Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),

this.targetObject.getClass().getInterfaces(),
this);

}

public Object
invoke(Object
proxy,
Method method,
Object[] args)

throws
Throwable {

return
method.invoke(this.targetObject, args);//把方法调用委派给目标对象

}

}

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

使用CGLIB生成代理

public class CGLIBProxy
implements MethodInterceptor
{

private Object targetObject;//代理的目标对象

public Object createProxyInstance(Object targetObject){

this.targetObject
= targetObject;

Enhancer enhancer =
new Enhancer();//该类用于生成代理对象

enhancer.setSuperclass(this.targetObject.getClass());//设置父类

enhancer.setCallback(this);//设置回调用对象为本身

return enhancer.create();

}

public Object intercept(Object
proxy,
Method method,
Object[] args,

MethodProxy methodProxy)
throws Throwable
{

return methodProxy.invoke(this.targetObject,
args);

}

}

CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: