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

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.xsd
http://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{
@Test
publicvoidtest01(){
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.xsd
http://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只支持方法连接点,不提供属性连接.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: