java动态代理与cglib

来源:互联网 发布:vb6.0连接mysql数据库 编辑:程序博客网 时间:2024/05/21 12:40

转载自:http://langyu.iteye.com/blog/410071

              http://www.cnblogs.com/xiaoluo501395377/p/3383130.html

 

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

    1. InvocationHandler:该接口中仅定义了一个invoke方法。每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

   1: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{...}

    第一个参数obj一般是指要代理的类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。

    2. Proxy:该类的作用就是用来动态创建一个代理对象的类,其中主要包含以下方法:

   1: public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException{…}
   2: //获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组.

   1: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{…}
   2: //返回代理类的一个实例,返回后的代理类可以当作被代理类使用.

    loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载。

    interfaces: 一个Interface对象的数组,表示的是要给需要代理的对象提供一组什么接口,如果提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样就能调用这组接口中的方法了。

    h: 一个InvocationHandler对象,表示的是当这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。


    Proxy.newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下几件事.

    (1)根据参数loader和interfaces调用getProxyClass(loader, interfaces)创建代理类$Proxy. $Proxy0类实现了interfaces的接口,并继承了Proxy类.

    (2)实例化$Proxy0并在构造方法中把loader传过去, 接着$Proxy0调用父类Proxy的构造器,为h赋值。接着把得到的$Proxy0实例强制转换成代理类. 当执行代理类的方法时,就调用了$Proxy0类中的方法.在执行代理类方法中,调用父类Proxy中的h的invoke()方法.即InvocationHandler.invoke()。

示例:

   1: package com.zero;
   2:  
   3: public interface IHello {
   4:     void say();
   5: }

   1: package com.zero;
   2:  
   3: public class HelloImpl implements IHello {
   4:  
   5:     @Override
   6:     public void say() {
   7:         // TODO Auto-generated method stub
   8:         System.out.println("Say hello!");
   9:     }
  10: }

   1: package com.zero;
   2:  
   3: import java.lang.reflect.InvocationHandler;
   4: import java.lang.reflect.Method;
   5:  
   6: public class JDKProxyHandler implements InvocationHandler {
   7:     // 这个就是我们要代理的真实对象
   8:     private Object realObject;
   9:  
  10:     // 构造方法,给我们要代理的真实对象赋初值
  11:     public JDKProxyHandler(Object target) {
  12:         this.realObject = target;
  13:     }
  14:  
  15:     @Override
  16:     public Object invoke(Object proxy, Method method, Object[] args)
  17:             throws Throwable {
  18:         // TODO Auto-generated method stub
  19:         System.out.println("jdk...invoke() begin");
  20:         System.out.println(method);
  21:         Object result = method.invoke(realObject, args);
  22:         System.out.println("jdk...invoke() end");
  23:         return result;
  24:     }
  25: }

   1: package com.zero;
   2:  
   3: import java.lang.reflect.Proxy;
   4:  
   5: public class JDKProxyTest {
   6:  
   7:     public static void main(String[] args) {
   8:         // TODO Auto-generated method stub
   9:         HelloImpl impl = new HelloImpl();
  10:         // 这里把handler与impl新生成的代理类相关联
  11:         JDKProxyHandler handler = new JDKProxyHandler(impl);
  12:          // 获得代理类($Proxy0 extends Proxy implements IHello)的实例.
  13:         IHello hello = (IHello) Proxy.newProxyInstance(impl.getClass()
  14:                 .getClassLoader(), impl.getClass().getInterfaces(), handler);
  15:         // 这里无论访问哪个方法,都是会把请求转发到handler.invoke
  16:         hello.say();
  17:         System.out.println(hello.getClass());
  18: //class com.sun.proxy.$Proxy0
  19:     }
  20: }


    JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

示例:

   1: package com.zero;
   2:  
   3: import java.lang.reflect.Method;
   4:  
   5: import org.springframework.cglib.proxy.Enhancer;
   6: import org.springframework.cglib.proxy.MethodInterceptor;
   7: import org.springframework.cglib.proxy.MethodProxy;
   8:  
   9: public class CGlibProxyHander implements MethodInterceptor {
  10:     private Object target;
  11:  
  12:     // target不必须使用接口
  13:     public Object createProxyInstance(Object target) {
  14:         this.target = target;
  15:         Enhancer enhancer = new Enhancer();
  16:         // 实际上是继承了目标类,覆盖目标类所有非final方法,再基础上添加新的代码
  17:         // 使用Enhancer可以对任意类生成代理类,
  18:         // 只要enhancer.setSuperclass(this.target.getClass());
  19:         // 其实质是代理类是目标类的子类。
  20:         enhancer.setSuperclass(this.target.getClass());
  21:         enhancer.setCallback(this);
  22:         return enhancer.create();
  23:     }
  24:  
  25:     // 从参数构成上,intercept的输入参数比invoke多1个,其实前3个参数对象的含义与invoke的含义是相同的
  26:     // 第一个参数表示调用方法来自哪个对象;
  27:     // 第二个参数表示调用方法的Method对象;
  28:     // 第三个参数表示此次调用的输入参数列表;
  29:     // 多出来的参数是MethodProxy 类型的,它应该是cglib生成用来代替Method对象的一个对象,
  30:     // 使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升
  31:     @Override
  32:     public Object intercept(Object object, Method method, Object[] args,
  33:             MethodProxy methodProxy) throws Throwable {
  34:         Object result = null;
  35:         System.out.println("CGlib代理 " + method.getName() + "()方法");
  36:         result = methodProxy.invoke(this.target, args);
  37:         return result;
  38:     }
  39: }

   1: package com.zero;
   2:  
   3: import java.lang.reflect.Proxy;
   4:  
   5: public class CGlibProxyTest {
   6:  
   7:     public static void main(String[] args) {
   8:         // TODO Auto-generated method stub
   9:         HelloImpl impl = new HelloImpl();
  10:         CGlibProxyHander hander = new CGlibProxyHander();
  11:         
  12:         IHello hello = (IHello) hander.createProxyInstance(impl);
  13:         hello.say();
  14:         System.out.println(hello.getClass());
  15: // class com.sun.proxy.$Proxy0
  16:     }
  17: }

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 商标是tm标怎么办 环保合格证掉了怎么办 车子合格证丢了怎么办 大牙附近肿了怎么办 办好营业执照后怎么办商标 商标十年到期了怎么办 公司注册了商标怎么办 2018年属兔不适合结婚怎么办 交通事故对方没钱赔怎么办 滴滴快车出车祸怎么办 交警法院扣车怎么办 肇事逃逸没钱赔怎么办 撞死人无力赔偿怎么办 宝贝咳嗽很厉害怎么办 开车有人别车怎么办 判刑罚金交不起怎么办 罚金太多交不起怎么办 判决书上的罚金怎么办 刑事罚款不交怎么办 缎面的鞋脏了怎么办 夏天脸上长粉刺怎么办 鬃狮不吃东西怎么办 买二手车的车牌怎么办 榴莲打开了肉没熟怎么办 gmat的prep做完怎么办 电脑没ip地址怎么办 电脑ip地址缺失怎么办 cos还原不了人物怎么办 执行局抓人十五天不放人怎么办 笔记本电脑键盘按键错乱怎么办 靠墙倒立上不去怎么办 医院多收钱了怎么办 学生总是转笔怎么办 吃错东西呕吐怎么办 手腕筋扭伤了怎么办 右膝盖内侧疼痛怎么办 膝盖关节腔积液怎么办 小孩玩游戏花钱怎么办 初三玩手机上瘾怎么办 无线网有感叹号怎么办 台式电脑网络感叹号怎么办