zoukankan      html  css  js  c++  java
  • 实现动态代理的两种方式

    常见的实现代理的两种方式:(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();  
        }  
    }  
  • 相关阅读:
    Educational Codeforces Round 86 (Rated for Div. 2) D. Multiple Testcases
    Educational Codeforces Round 86 (Rated for Div. 2) C. Yet Another Counting Problem
    HDU
    HDU
    HDU
    HDU
    Good Bye 2019 C. Make Good (异或的使用)
    Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam
    codeforces 909C. Python Indentation
    codeforces1054 C. Candies Distribution
  • 原文地址:https://www.cnblogs.com/hunrry/p/9183068.html
Copyright © 2011-2022 走看看