spring AOP 两种底层实现( JDK动态代理 和 CGLIB代理)
2016-03-22 21:17
846 查看
AOP的底层实现:
1.底层实现就是代理机制:
JDK动态代理和CGLIB代理.2.JDK动态代理:
原理:并没有使用多余的技术,纯粹的原java方式,类运用,即生成了一个接口的实现类.JDK动态代理的使用:添加Proxy类,一般会继承:InvocationHandler接口生成invoke方法。staticObjectInvocationHandler接口 | newProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh)ClassLoader:类的加载器.Class[]:实现的所有接口.InvocationHandler:处理接口.Objectinvoke(Objectproxy,Methodmethod,Object[]args);Object:代理对象.Method:执行的方法.Object[]:执行这个方法的参数列表. |
2.1.调用真实对象的方法的时候;
*UserDao(接口)---->UserDaoImpl(实现类)*对UserDaoImpl生成一个代理类.*UserDaouserDao=Proxy.newProxyInstance(..);*userDao.add();*userDao.update();*****都相当于调用了InvocationHandler中的invoke()方法.2.2.JDK动态代理的代码实现:
生成代理类==>
publicclassJdkProxyimplementsInvocationHandler{
privateUserDaouserDao;
publicJdkProxy(UserDaouserDao){
this.userDao=userDao;
}
publicUserDaocreateProxy(){
Objectproxy=Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this);
return(UserDao)proxy;
}
@Override
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
throwsThrowable{
//判断执行的方法
//对add方法进行增强
if("add".equals(method.getName())){
//增强
System.out.println("增强的代码...");
returnmethod.invoke(userDao,args);
}else{
//不增强
returnmethod.invoke(userDao,args);
}
}
}[/code]
测试主体==>
packagecn.green.demo;
importorg.junit.Test;
publicclassTestCase{
@Test
publicvoiddemo01(){
UserDaouserDao=newUserDaoImpl();
UserDaouserProxy=newJdkProxy(userDao).createProxy();
userProxy.add();
userProxy.delete();
}
}[/code]
applicationContext.xml==>
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/aop'target='_blank'>http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><aop:aspectj-autoproxy/><beanid="userDao"class="cn.green.demo.UserDaoImpl"></bean><beanid="jdkProxy"class="cn.green.demo.JdkProxy"></bean></beans>[/code]3.CGLIB的代理:
JDK的动态代理有局限性:类必须实现接口,才能生成代理.(一个类没有实现接口,JDK无法生成代理对象.)CGLIB代理:可以对没有实现接口的类生成代理.CGLIB(CodeGenerationLibrary)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate支持它来实现PO(PersistentObject持久化对象)字节码的动态生成。*Hibernate:javassist原理:*通过字节码技术,对这个类生成了一个子类对象. packagecn.itcast.spring3.demo2;publicclassProductDao{publicvoidadd(){System.out.println("添加商品...");}publicvoidupdate(){System.out.println("修改商品...");}publicvoiddelete(){System.out.println("删除商品...");}publicvoidfind(){System.out.println("查询商品...");}}[/code]packagecn.green.demo1;importjava.lang.reflect.Method;importorg.springframework.cglib.proxy.Enhancer;importorg.springframework.cglib.proxy.MethodInterceptor;importorg.springframework.cglib.proxy.MethodProxy;publicclassCglibProxyimplementsMethodInterceptor{privateOrderDaoorderDao;publicCglibProxy(OrderDaoorderDao){this.orderDao=orderDao;}//生成代理的方法publicOrderDaocreateProxy(){//CGLIB核心对象Enhancerenhancer=newEnhancer();//原理:对这个类生成一个子类对象//设置父类enhancer.setSuperclass(orderDao.getClass());//设置回调enhancer.setCallback(this);//创建代理对象return(OrderDao)enhancer.create();}publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{if("add".equals(method.getName())){System.out.println("方法前增强代码===============");Objectobj=methodProxy.invokeSuper(proxy,args);System.out.println("方法后增强代码===============");returnobj;}else{returnmethodProxy.invokeSuper(proxy,args);}}}[/code]packagecn.green.demo1;importorg.junit.Test;publicclassTestDemo{@Testpublicvoidtest01(){OrderDaoorderDao=newOrderDao();OrderDaoproxy=newCglibProxy(orderDao).createProxy();proxy.add();proxy.delete();proxy.update();proxy.find();}}[/code]<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/aop'target='_blank'>http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><beanid="orderDao"class="cn.green.demo1.OrderDao"></bean><beanid="cglibProxy"class="cn.green.demo1.CglibProxy"></bean></beans>[/code]效果如下:方法前增强代码===============addrun....方法后增强代码===============deleterun....updaterun....findrun....[/code]4.Spring中使用这两种技术完成代理(AOP):
*如果类实现了接口,使用JDK动态代理,为你生成代理对象.*如果类没有实现接口,使用CGLIB动态代理,生成代理对象.总结:Spring在运行期,生成动态代理对象,不需要特殊的编译器SpringAOP的底层就是通过JDK动态代理或CGLib动态代理技术为目标Bean执行横向织入1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。*程序中应优先对接口创建代理,便于程序解耦维护3.标记为final的方法,不能被代理,因为无法进行覆盖JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰CGLib是针对目标类生产子类,因此类或方法不能使final的4.Spring只支持方法连接点,不提供属性连接.
相关文章推荐
- Java --- 异常处理和设计
- java中>,>>,>>> 的区别
- Spring中自动装配的三种方式
- Java中对象的内存分配问题
- java基础---->Zip压缩的使用(转)
- insertionSort()插入排序
- The connection to adb is down, and a severe error has occured. You must restart adb and Eclipse.Ple
- 链表题 java
- eclipse中查看项目有多少行代码
- JAVA hashcode和equals为何要同时重写
- Java输入输出流
- 如何创建struts2第一个程序及其原理解释
- 关于java中的对象交互问题(模拟时钟)
- myeclipse快捷键总结
- foreach语句
- Java基础学习第二十一天——递归与字节流
- java产生4位随机数
- java 对xml文件进行 增删改查
- java指导
- 91. Decode Ways | Java最短代码实现