JDK与CGlib动态代理的实现

Posted benefitworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK与CGlib动态代理的实现相关的知识,希望对你有一定的参考价值。

应用的原型为

执行者:房屋中介Agency(分为JDKAgency、CGlibAgency)

被代理对象:程序员Programmer

被代理对象的实现接口:租户Tenement(CGlibAgency时不需要实现接口)

Tenement 接口:
package com.suzao.spring.test;

/**
 * Tenement
 * @Description 租户
 * @Param
 * @return
 * @Author mc
 * @Date 2018/12/28 16:44
 */
public interface Tenement {

    /**
     * rentHouse
     * @Description 租房方法
     * @Param []
     * @return
     * @Author mc
     * @Date 2018/12/28 18:51
     */
    void rentHouse();
}
Programmer 实现类
package com.suzao.spring.test;

/**
 * Programmer
 * @Description 程序员
 * @Param
 * @return
 * @Author mc
 * @Date 2018/12/28 18:21
 */
public class Programmer implements Tenement {

    /**
     * rentHouse
     * @Description 租房方法
     * @Param []
     * @return
     * @Author mc
     * @Date 2018/12/28 18:52
     */
    @Override
    public void rentHouse() {
        System.out.println("我是程序员,我在找房子!");
    }
}

JDK动态代理:执行者  JDKAgency 

package com.suzao.spring.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDKAgency
 * @Description JDK房屋中介
 * @Param
 * @return
 * @Author mc
 * @Date 2018/12/28 18:22
 */
public class JDKAgency implements InvocationHandler{

    //拿到被代理对象的引用
    private Tenement target;

    public Object getTenementProxy(Tenement target){
        this.target = target;
        Class clazz = target.getClass();
        //clazz.getInterfaces() 获取它的接口
        //重新动态生成一个class字节码
        //编译
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK房屋中介开始执行。。。");
        System.out.println("----------------------------");
        method.invoke(this.target,args);
        System.out.println("----------------------------");
        System.out.println("JDK房屋中介结束执行。。。");
        return null;
    }
}

CGlib动态代理:执行者  CGlibAgency 

package com.suzao.spring.test;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * CGlibAgency
 * @Description CGlib 租房中介
 * @Param
 * @return
 * @Author mc
 * @Date 2018/12/28 19:11
 */
public class CGlibAgency implements MethodInterceptor{


    public Object getTenmentProxy(Class clazz){

        Enhancer enhancer = new Enhancer();

        //告诉cglib,生成的子类需要继承那个类
        enhancer.setSuperclass(clazz);

        //设置回调
        enhancer.setCallback(this);

        //加载到jvm中,并返回代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGlib房屋中介开始执行。。。");
        System.out.println("----------------------------");
        methodProxy.invokeSuper(obj,args);
        System.out.println("----------------------------");
        System.out.println("CGlib房屋中介结束执行。。。");
        return null;
    }
}

代理测试类 TestProxy 

package com.suzao.spring.test;

/**
 * TestProxy
 * @Description 测试代理
 * @Param
 * @return
 * @Author mc
 * @Date 2018/12/28 18:46
 */
public class TestProxy {


    public static void main(String[] args) {

        //java动态代理是利用反射机制生成一个实现被代理对象的接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

        //执行者 JDKAgency
        //被代理对象 Programmer
        //被代理对象实现的接口 Tenement
        Tenement  tenement= (Tenement) new JDKAgency().getTenementProxy(new Programmer());
        tenement.rentHouse();
        System.out.println("

");
        
        //cglib动态代理利用asm开源包,对被代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
        //执行者 CGlibAgency
        //被代理对象 Programmer
        Programmer  programmer= (Programmer) new CGlibAgency().getTenmentProxy(new Programmer().getClass());
        programmer.rentHouse();
    }
}

执行结果:

JDK房屋中介开始执行。。。
----------------------------
我是程序员,我在找房子!
----------------------------
JDK房屋中介结束执行。。。



CGlib房屋中介开始执行。。。
----------------------------
我是程序员,我在找房子!
----------------------------
CGlib房屋中介结束执行。。。

pom.xml中引用:

<dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>${org.springframework-version}</version>
                </dependency>
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

 

以上是关于JDK与CGlib动态代理的实现的主要内容,如果未能解决你的问题,请参考以下文章

JDK动态代理与CGLIB动态代理

JDK动态代理与CGLIB动态代理

DK动态代理与CGLib动态代理的区别

Spring AOP JDK动态代理与CGLib动态代理区别

Spring框架中的JDK与CGLib动态代理

CGlib和JDK动态代理