(8) 使用JDK中的Proxy技术实现AOP功能 以及 CGLIB生成代理

第一种:使用JDK中的Proxy技术实现AOP功能


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来生成代理对象。


  1. package cn.itm.service; 
  2.  
  3. public interface PersonService { 
  4.  
  5.     public void save(String name); 
  6.      
  7.     public void update(String name,Integer personid); 
  8.      
  9.     public String getPersonName(Integer personid); 

  1. package cn.itm.service.impl; 
  2.  
  3. import cn.itm.service.PersonService; 
  4.  
  5. /**
  6. * 对这里面的所有方法 实施拦截,拦截到这个方式之后,我们判断,用户是否为 null,如果为null,就没有权限去调用这里面的方法。
  7. * @author Administrator
  8. *
  9. */ 
  10. public class PersonServiceBean implements PersonService { 
  11.      
  12.      
  13.     private String user = null
  14.      
  15.     public String getUser() { 
  16.         return user; 
  17.     } 
  18.  
  19.      
  20.     public PersonServiceBean(){} 
  21.      
  22.     public PersonServiceBean(String user){ 
  23.         this.user = user; 
  24.     } 
  25.  
  26.     @Override 
  27.     public String getPersonName(Integer personid) { 
  28.         System.out.println("我是  getPersonName()方法 "); 
  29.         return "xxx"
  30.     } 
  31.  
  32.     @Override 
  33.     public void save(String name) { 
  34.         System.out.println("我是 save() 方法"); 
  35.     } 
  36.  
  37.     @Override 
  38.     public void update(String name, Integer personid) { 
  39.         System.out.println("我是 update() 方法"); 
  40.     } 
  41.  

  1. package cn.itm.aop; 
  2.  
  3. import java.lang.reflect.InvocationHandler; 
  4. import java.lang.reflect.Method; 
  5. import java.lang.reflect.Proxy; 
  6.  
  7. import cn.itm.service.impl.PersonServiceBean; 
  8.  
  9. public class JDKProxyFactory implements InvocationHandler{ 
  10.  
  11.     private Object targetObject; 
  12.      
  13.     /**
  14.      * 调用对象 会 被this 拦截到。拦截到后,他会执行invoke() 方法    也就是说:客户端调用代理对象业务方法的时候,代理对象就会执行 InvocationHandler 找   invoke()方法
  15.      *
  16.      * invoke方法就会   把 method的调用 委派给目标对象。
  17.      *
  18.      * @param targetObject
  19.      * @return
  20.      */ 
  21.     public Object createProxyInstance(Object targetObject){ 
  22.         this.targetObject = targetObject; 
  23.         return Proxy.newProxyInstance( 
  24.                 this.targetObject.getClass().getClassLoader(),  
  25.                 this.targetObject.getClass().getInterfaces(),  
  26.                 this 
  27.         );   
  28.     } 
  29.  
  30.     /**
  31.      *
  32.      * @param proxy
  33.      * @param method : 代表被拦截到的方法,
  34.      * @param args   : 代表方法的输入参数。
  35.      * @return
  36.      * @throws Throwable
  37.      */ 
  38.     public Object invoke(Object proxy, Method method, Object[] args) 
  39.             throws Throwable { 
  40.         PersonServiceBean bean = (PersonServiceBean)this.targetObject; 
  41.         Object result = null
  42.         if(bean.getUser() != null){ // 代表如果有权限。 
  43.             // 委派给目标对象。 
  44.             result = method.invoke(targetObject, args); 
  45.         } 
  46.          
  47.         return result; 
  48.     } 

  1. package junit.test; 
  2.  
  3.  
  4. import org.junit.BeforeClass; 
  5. import org.junit.Test; 
  6.  
  7. import cn.itm.aop.JDKProxyFactory; 
  8. import cn.itm.service.PersonService; 
  9. import cn.itm.service.impl.PersonServiceBean; 
  10.  
  11. public class AOPTest { 
  12.  
  13.     @BeforeClass 
  14.     public static void setUpBeforeClass() throws Exception { 
  15.     } 
  16.      
  17.     @Test public void proxyTest(){ 
  18.         JDKProxyFactory factory = new JDKProxyFactory(); 
  19.         // 注意要使用接口 来饮用代理对象。 
  20.         PersonService personService = (PersonService)factory.createProxyInstance(new PersonServiceBean("XXX")); 
  21.         personService.save("999"); 
  22.     } 
  23.  

ok,成功。


第二种:使用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修饰符的方法。


代码示例:


不用实现接口

  1. package cn.itm.service.impl; 
  2.  
  3.  
  4. /**
  5. * 对这里面的所有方法 实施拦截,拦截到这个方式之后,我们判断,用户是否为 null,如果为null,就没有权限去调用这里面的方法。
  6. * @author Administrator
  7. *
  8. */ 
  9. public class PersonServiceBean{ 
  10.      
  11.      
  12.     private String user = null
  13.      
  14.     public String getUser() { 
  15.         return user; 
  16.     } 
  17.  
  18.      
  19.     public PersonServiceBean(){} 
  20.      
  21.     public PersonServiceBean(String user){ 
  22.         this.user = user; 
  23.     } 
  24.  
  25.     public String getPersonName(Integer personid) { 
  26.         System.out.println("我是  getPersonName()方法 "); 
  27.         return "xxx"
  28.     } 
  29.  
  30.     public void save(String name) { 
  31.         System.out.println("我是 save() 方法"); 
  32.     } 
  33.  
  34.     public void update(String name, Integer personid) { 
  35.         System.out.println("我是 update() 方法"); 
  36.     } 
  37.  

使用cglib实现:

  1. package cn.itm.aop; 
  2.  
  3. import java.lang.reflect.Method; 
  4.  
  5. import net.sf.cglib.proxy.Enhancer; 
  6. import net.sf.cglib.proxy.MethodInterceptor; 
  7. import net.sf.cglib.proxy.MethodProxy; 
  8. import cn.itm.service.impl.PersonServiceBean; 
  9.  
  10. public class CGLIBProxyFactory implements MethodInterceptor{ 
  11.  
  12. private Object targetObject; 
  13.      
  14.     public Object createProxyInstance(Object targetObject){ 
  15.         this.targetObject = targetObject; 
  16.         Enhancer enhancer = new Enhancer();//该类用于生成代理对象 
  17.         enhancer.setSuperclass(this.targetObject.getClass());//设置父类 
  18.          
  19.         enhancer.setCallback(this);//设置回调用对象为本身 
  20.         return enhancer.create();  // 创建代理对象。 
  21.  
  22.     } 
  23.      
  24.     public Object intercept(Object proxy, Method method, Object[] args, 
  25.             MethodProxy methodProxy) throws Throwable { 
  26.          
  27.         PersonServiceBean bean = (PersonServiceBean)this.targetObject; 
  28.         Object result = null
  29.         if(bean.getUser() != null){ // 代表如果有权限。 
  30.             // 委派给目标对象。 
  31.             result = methodProxy.invoke(targetObject, args); 
  32.         } 
  33.          
  34.         return result; 
  35.      
  36.     } 
  37.  

测试类

  1. package junit.test; 
  2.  
  3.  
  4. import org.junit.BeforeClass; 
  5. import org.junit.Test; 
  6.  
  7. import cn.itm.aop.CGLIBProxyFactory; 
  8. import cn.itm.service.impl.PersonServiceBean; 
  9.  
  10. public class AOPTest { 
  11.  
  12.     @BeforeClass 
  13.     public static void setUpBeforeClass() throws Exception { 
  14.     } 
  15.     @Test public void cglibproxyTest(){ 
  16.         CGLIBProxyFactory factory = new CGLIBProxyFactory(); 
  17.         // 注意要使用接口 来饮用代理对象。 
  18.         PersonServiceBean personServiceBean = (PersonServiceBean)factory.createProxyInstance(new PersonServiceBean(/*"XXX"*/)); 
  19.         personServiceBean.save("CGLIB----> 999"); 
  20.     } 
  21.  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值