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修饰符的方法。
相关文章推荐
- Java Persistence with MyBatis 3(中国版)
- Eclipse新版 syso无法自动补全的解决方法
- eclipse+maven+git+mysql
- Java-2-学习历程2:基础知识1,2,3文档、完整版视频资源、电子书籍下载
- AndroidAnnotations开发框架在Eclipse中的搭建和使用以及框架实现的原理
- AndroidAnnotations开发框架在Eclipse中的搭建和使用以及框架实现的原理
- java中保留固定小数位数
- 【Error opening registry key 'Software\JavaSoft\Java Runtime Environment】解决方案
- Struts2 注解零配置方法(convention插件使用)
- 对Spring 及SpringMVC的理解
- Eclipse在线安装SVN
- JavaSE笔记之<正则表达式>
- springmvc、mybatis整合数据库语句输出问题解决
- Java基础知识整理---环境变量配置
- JSP 和 JavaBean连接sql server验证登录
- Android开发中遇到的问题(五)——Eclipse导入Android项目出现"Invalid project description overlaps the location of another project"错误的解决办法
- 五、Spring源码分析——Spring Aop
- Android开发中遇到的问题(三)——eclipse创建android项目无法正常预览布局文件
- 1005--Java集合--Map接口
- Android开发中遇到的问题(二)——新建android工程的时候eclipse没有生成MainActivity和layout布局