JDK、CGLIB、Spring三种实现代理的区别(二)CGLIB中proxy动态代理

CGLIB中的动态代理是JDK proxy的一个很好的补充,在JDK中实现代理时,要求代理类必须是继承接口的类,因为JDK最后生成的proxy class其实就是实现了被代理类所继承的接口并且继承了java中的Proxy类,通过反射找到接口的方法,调用InvocationHandler的invoke 方法实现拦截。CGLIb中最后生成的proxy class是一个继承被代理类的class,通过重写被代理类中的非final的方法实现代理。总结为:
JDK proxy:代理类必须实现接口
CGLIB: 代理类不能是final,代理的方法也不能是final(继承限制)
关于JDK proxy原理,可参看之前的整理
http://blog.csdn.net/sunnycoco05/article/details/78845878
下面看看CGLIb中的处理,我们要实现对一个类进行代理,在调用方法前后进行简单处理
创建一个要代理的类:
有一个printName类方法

public class MyTarget {

    public void printName() {
        System.err.println("name:Target-");
    }

自己的拦截器,CGLIb中实现MethodInterceptor接口,它可支持对不同方法的拦截,这里我们统一处理:

public class MyInterceptor implements MethodInterceptor {
   

    @Override
    public Object intercept(Object obj, Method method, Object[] params, MethodProxy proxy) throws Throwable {
        System.err.println("=======before======");
        Object res = proxy.invokeSuper(obj, params);
        System.err.println("=======and======");
        return res;
    }
}

只是在方法调用前后进行简单打印。CGLIb中通过Enhancer类进行代理操作,开始测试:

@Test
    public void proxyTest() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyTarget.class);
        enhancer.setCallback(new MyInterceptor());
        MyTarget target = (MyTarget) enhancer.create();
        target.printName();
        System.out.println("proxy class name:" + target.getClass().getName());
    }

运行结果:
这里写图片描述

成功实现拦截。
动态代理,其实就是动态的生成一个有关被代理类的class文件,并加装运行这个class文件的过程。如果我们可以把JVM中生成的class 文件保存下来,再通过反编译后的Java文件去分析,应该就很清楚的去看懂它的原理。我们可以用-javaagent去实现这个功能。自定义一个agent 类, 这个Agent在class文件装载的时候,我们判断是否是生成的代理类(根据class name判断),如果符合,将class的字节流写入文件,存在指定位置

public class MyAgent implements ClassFileTransformer {
   
    //会在main方法之前执行,添加自定义的的ClassFileTransformer
    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new MyAgent());
    }

    //每次装载class文件都会执行
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        //com.cglib.MyTarget$$EnhancerByCGLIB$$65288428
        //com.sun.proxy.$Proxy4
        //CGLIB和JDK proxy生成的代理类进行拦截
        if (className.contains("$$EnhancerByCGLIB$$") || className.contains("$Proxy")) {
            //指定存放路径
            String path = "yourdirpath";
            int lastIndexOf = className.lastIndexOf("/") + 1;
            String classFileName = className.substring(lastIndexOf) + ".class";
            writeClassToDisk(path + classFileName, classfileBuffer);
            System.out.println(className + "---writeClassToDisk Succeess!");
        }
        return classfileBuffer;
    }

    //将class文件存在磁盘
    private void writeClassToDisk(String fileName, byte[] data) {
        try {
            File file = new File(fileName);
            if (!file.exists()) {
           
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值