深入探索spring技术内幕(六): JDK动态代理和cglib生成代理

[ JDK生成代理 ]

JDK中给我们提供了一个Proxy类可以动态的给我们生成代理.

假定我们要做一个权限管理系统, 需要控制用户对某一个方法的访问. 如果user为null, 那么不让用户访问save方法.


① 接口类: PersonService

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public interface PersonService {  
  2.     public void save();  
  3. }  

② 实现类: PersonServiceImpl

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class PersonServiceImpl implements PersonService {  
  2.     private String user;  
  3.       
  4.     public PersonServiceImpl(){  
  5.     }  
  6.       
  7.     public PersonServiceImpl(String user) {  
  8.         this.user = user;  
  9.     }  
  10.   
  11.     public void save() {  
  12.         System.out.println("执行了save()方法");  
  13.     }  
  14.   
  15.     public String getUser() {  
  16.         return user;  
  17.     }  
  18. }  

③ 生成代理类工厂: JDKProxyFactory

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class JDKProxyFactory implements InvocationHandler {  
  2.     private Object targetObject; //代理的目标对象  
  3.   
  4.     public Object createProxyIntance(Object targetObject) {  
  5.         this.targetObject = targetObject;  
  6.         /** 
  7.          * 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器 
  8.          * 第二个参数设置代理类实现的接口 
  9.          * 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法 
  10.          */  
  11.         return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),   
  12.                                       this.targetObject.getClass().getInterfaces(),   
  13.                                       this);  
  14.     }  
  15.   
  16.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  17.         PersonServiceImpl ps = (PersonServiceImpl) this.targetObject;  
  18.         Object result = null;  
  19.         if (ps.getUser() != null) { // 如果user为null, 则无法调用目标方法  
  20.             result = method.invoke(targetObject, args); // 把方法调用委派给目标对象  
  21.         }  
  22.         return result;  
  23.     }  
  24. }  

④ 测试一把:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class PersonServiceImplTest {  
  2.     @Test  
  3.     public void testJDKProxy() {  
  4.         JDKProxyFactory factory = new JDKProxyFactory();  
  5.         PersonService personService = (PersonService) factory.createProxyIntance(new PersonServiceImpl("zhangsan"));  
  6.         personService.save();  
  7.     }  
  8. }  

[ CGLIB生成代理 ]

Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类。

使用CGLIB生成代理需要引入cglib-nodep-2.1_3.jar

① CBLIG生成代理工厂: CGlibProxyFactory

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class CGlibProxyFactory implements MethodInterceptor {  
  2.     private Object targetObject;  
  3.   
  4.     public Object createProxyIntance(Object targetObject) {  
  5.         this.targetObject = targetObject;  
  6.         Enhancer enhancer = new Enhancer();  
  7.         enhancer.setSuperclass(this.targetObject.getClass()); // 设置代理类的父类  
  8.         enhancer.setCallback(this); // 设置回调函数  
  9.         return enhancer.create();  
  10.     }  
  11.   
  12.     public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
  13.         PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;  
  14.         Object result = null;  
  15.         if (bean.getUser() != null) { // 如果user为null, 则无法调用目标方法  
  16.             result = methodProxy.invoke(targetObject, args);  
  17.         }  
  18.         return result;  
  19.     }  
  20. }  

② 测试一把

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class PersonServiceImplTest {  
  2.     @Test  
  3.     public void testCGLIBProxy() {  
  4.         CGlibProxyFactory factory = new CGlibProxyFactory();  
  5.         PersonService personService = (PersonServiceImpl) factory.createProxyIntance(new PersonServiceImpl("lisi"));  
  6.         personService.save();  
  7.     }  
  8. }  


[ 比较两种代理 ]

1. 使用JDK的动态代理, 被代理类一定要实现了某个接口, 而使用CGLIB, 被代理类没有实现任何接口也可以实现动态代理功能, 

2. 因为采用的是继承, 所以cglib无法对使用final修饰的类使用代理.

3. CGLIB的速度要远远快于JDK Proxy动态代理.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值