实现动态代理的两种方式

常见的实现代理的两种方式:(1)JDK动态代理(2)使用cglib产生代理

这两种方法各有好坏。jdk动态代理是由java内部的反射机制生成字节码并生成对象来实现的,而cglib代理底层是借助asm来实现的,这个asm就是一个java字节码操纵框架,它能用来动态生成类或者增强类的功能,ASM从类文件中读入信息后,改变类的行为,分析类的信息,这就跟aop实现方式中的静态织入的是一样的,就是相当于把切面织入类的字节码文件中,以此达到拦截的作用。一般jdk动态代理用于目标类都是基于统一的接口,cglib多用于对类的代理,这些类不需要实现统一的接口。

1.jdk动态代理

假设我们要实现对时间的代理,首先我们先定义一个TimeHandler的类,并让这个类实现InvocationHandler的接口,在这个接口中有invoke()方法,我们需要重写这个方法

 1 public class TimeHandler implements InvocationHandler{  
 2        public Object target;//要代理的类的对象  
 3        public TimeHandler(Object target){  
 4        super();  
 5        this.target=target;  
 6        }  
 7        public Object invoke(object proxy,Method  
 8  method,Object[] args)throws Throwable{  
 9     //方法调用前可以执行比如说权限检查之类的  
10      method.invoke(target);  
11     //方法调用后可以执行比如说日志输出等等  
12      return null;  
13     }  
14 }  

测试方法如下

public class Test {  
  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        Move car=new Car();//需要代理的类  
        TimeHandler t=new TimeHandler(car);  
        Move car1=(Move)Proxy.newProxyInstance(car.getClass().getClassLoader(), car.getClass().getInterfaces(), t);//创建代理类  
        car1.move();  
    }  
}  

这里解释一下很多人不理解为什么jdk动态代理的对象必须实现一个统一的接口,其实我的理解大致是代理类本身已经extends了TimeHandler,如果传入的是父类,很可能出现这种情况:

public class $Proxy1 extends Proxy extends 传入的父类{  
      
}  

这个明显在java中是不允许的,Java只支持单继承,但是实现接口是完全可以的。

2.cglib动态代理

针对类来实现代理,对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

编写cglib动态代理要引入一个jar包,包名为cglib-nodep-2.2.jar。

首先我们要创建CglibProxy的类,这个类实现MethodInteceptor接口

public class CglibProxy implements MethodInterceptor{  
    @Override  
    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {  
        // TODO Auto-generated method stub  
        //方法拦截前可以执行比如说权限检查之类的  
        arg3.invokeSuper(arg0, arg2);//代理类调用父类的方法  
        //方法拦截后可以执行比如说日志输出等等  
        return null;  
    }  
}  

测试方法如下:

 
public class Test {  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        Car c=new Car();  
        CglibProxy cg=new CglibProxy();  
        Enhancer enhance=new Enhancer();//作用是创建一段动态地类字节码  
        enhance.setSuperclass(c.getClass());//设置父类,也就是使用传递过来的类来创建代理类  
        enhance.setCallback(cg);//这个回调函数就是把调用的方法改为CglibProxy中的inteceptor方法,并称此行为为增强目标类  
        Car c1=(Car)enhance.create();  
        c1.move();  
    }  
}  

猜你喜欢

转载自www.cnblogs.com/hunrry/p/9183068.html