zoukankan      html  css  js  c++  java
  • JDK动态代理与CGLib动态代理

    JDK动态代理:

    a、先定义一个接口,这个接口中的方法是“目标方法”

    package com.brickworkers;
    
    public interface Sky {
    
        public void rain();
    
    }

    b、接着写一个这个接口的具体实现:

    package com.brickworkers;
    
    public class SkyImpl implements Sky{
    
        @Override
        public void rain() {
            System.out.println("it`s raining");
        }
    
    
    }

    c、如果要完成动态代理,首先需要定义一个InvocationHandler接口的子类:

    package com.brickworkers;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class MyInvocationHandler implements InvocationHandler {
    
        //目标对象
        private Object obj = null;
    
    
        //获取目标对象的代理对象
        public Object getProxy(Object obj){
            this.obj = obj;
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        }
    
        //控制执行目标对象的方法
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("目标对象方法执行之前");
            Object result = method.invoke(obj, args);
            System.out.println("目标对象方法执行之后");
            return result;
        }
    
    }

    d:JDK动态代理测试类:

    package com.brickworkers;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //实例化InvocationHandler
            MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
            //生产代理对象
            Sky sky = (Sky) myInvocationHandler.getProxy(new SkyImpl());
            sky.rain();
        }
    
    }
    
    //执行结果:  目标对象方法执行之前
    //            it`s raining
    //          目标对象方法执行之后

    为什么JDK动态代理只能局限于接口呢?查阅了一些技术文档和JDK动态代理的源码,发现在反编译产生的proxyTest.class中,类的定义如下:

    import dynamic.proxy.UserService;  
    import java.lang.reflect.*;  
    
    public final class $ProxyTest extends Proxy  
        implements Sky
    { 
        ......
    }

    从反编译的源码可以看出,proxyTest继承了Proxy,然而在Java中只支持单继承,但是可以实现多个接口,所以JDK动态代理只能局限于接口。

    那么JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,要实现动态代理要怎么办呢?这个时候就需要CGLib动态代理了。

    CGLib动态代理:

    CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有分类方法的调用,顺势织入和横切逻辑。-http://blog.csdn.net/yakoo5/article/details/9099133/

    点击下载编写CGlib动态代理测试所需jar包

    a、定义一个目标对象:

    package com.brickworkers;
    
    public class Color {
    
        public void showColor(){
            System.out.println("red");
        }
    
    }

    b、如果要完成动态代理,首先需要定义一个MethodInterceptor接口的子类:

    package com.brickworkers;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class MyCglib implements MethodInterceptor {
    
        //目标对象
        private Object obj = null;
    
        public Object getProxy(Object obj){
            this.obj = obj;
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(obj.getClass());
            // 回调方法  
            enhancer.setCallback(this);  
            // 创建代理对象  
            return enhancer.create();
    
        }
    
        @Override
        public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("目标对象方法执行之前");
            Object result = methodProxy.invoke(obj, args);
            System.out.println("目标方法执行之后");
            return result;
        }
    
    }

    c、CGLib动态代理测试类:

    package com.brickworkers;
    
    public class CGLibTest {
    
        public static void main(String[] args) {
            MyCglib myCglib = new MyCglib();
            Color color = (Color) myCglib.getProxy(new Color());
            color.showColor();
        }
    }
    //执行结果:目标对象方法执行之前
    //              red
    //          目标方法执行之后

    因为CGLib动态代理是创建一个子类来实现的,那么对于继承的定义,final类是无法进行代理的。

  • 相关阅读:
    Python下划线简介
    OneHot编码
    搜狗新闻原始数据处理
    2. mirth connect探索------------ cs模式客户端登录
    System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。 ---> System.Security.Authentication.AuthenticationException: 根据验证过程,远程证书无效。
    python学习历程-安装篇(一)
    Python学习笔记(一)
    使用dva 搭建ant design mobile项目
    [error] OpenEvent("Global gx_stop_25184") failed (2: The system cannot find the file specified)
    nginx 上部署 react 项目
  • 原文地址:https://www.cnblogs.com/wyb628/p/8511174.html
Copyright © 2011-2022 走看看