对于JDK动态代理和Cglib动态代理,如何分析和实现?

本文介绍了Java的JDK动态代理和Cglib动态代理,包括它们的实现原理、步骤以及适用场景。JDK基于接口,Cglib则支持无接口类的代理。
摘要由CSDN通过智能技术生成

JDK动态代理和Cglib动态代理都是Java中常用的动态代理实现方式,它们各有特点和应用场景:

  1. JDK动态代理:JDK动态代理是基于接口的代理方式。它使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来创建代理对象。在这种方式下,代理类在运行时动态创建,并且必须实现一个或多个接口。使用JDK动态代理时,你需要提供一个实现了InvocationHandler接口的类,这个类的invoke方法将定义代理逻辑。

    实现步骤大致如下:

    • 定义一个接口和该接口的实现类;
    • 创建一个实现了InvocationHandler接口的处理器类;
    • 使用Proxy.newProxyInstance方法动态创建代理对象。
  2. Cglib动态代理:与JDK动态代理不同,Cglib代理不需要接口,它是通过继承方式实现的。Cglib包含了一组底层字节码操作工具,能动态生成新的类。它通过继承目标类并重写其中的方法来实现代理。由于是通过继承实现,因此它不能代理声明为final的类和方法。

    实现步骤大致如下:

    • 创建一个实现了MethodInterceptor接口的类;
    • 使用Cglib的Enhancer类来创建代理对象,指定父类和回调。

在选择使用哪种代理方式时,如果所有目标对象都实现了接口,可以使用JDK动态代理;如果目标对象没有实现接口,或者你需要代理类的所有方法,那么可以考虑使用Cglib代理。

JDK动态代理

如何创建代理对象:使用Proxy类中的newProxyInstance方法

创建代理对象的要求:被代理类至少实现一个接口

newProxyInstance方法的参数

ClassLoader:类加载器,同于加载被代理对象字节码

Class[]:字节码数组---用于让代理对象和被代理对象拥有相同的方法

InvocationHandler:用于提供被增强的代码

/**
		接口类
 */
public interface FindHouse2 {

    /**
     * 找房子
     */
    void find1();


    /**
     * 找房子
     */
    void find2();


    /**
     * 获取名字
     * @return
     */
    String getName();

}


/**
		测试类
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {


    public static void main(String[] args) {


        //如何动态创建一个代理类对象(接口的代理类对象)
        //【这里代理的是FindHouse2.class类】
        FindHouse2 obj = (FindHouse2) (Proxy.newProxyInstance(
                FindHouse2.class.getClassLoader(),
                new Class[]{FindHouse2.class},
                new MyInvocationHandler()));

        //调用代理类对象的find1()方法
        obj.find1();

        //调用代理类对象的find2()方法
        obj.find2();

        //调用代理类对象的getName()方法
        System.out.println(obj.getName());

    }


    ///方法调用处理器///
    private static class MyInvocationHandler implements InvocationHandler {

        //钩子函数
        //obj.find1()  => 调用方法
        //在调用方法时,回调这个钩子
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("正在努力找房源...");
            System.out.println("ing...");
            System.out.println("找到了xxx的房子");

            //返回 null   -> 相当于是void
            //返回 其他值  -> 相当于是对应的值的类型
            return "哈哈";
        }

    }


}


Cglib动态代理

Enhancer是cglib中使用频率很高的一个类,它是一个字节码增强器,可以用来为无接口的类创建代理。它的功能与java自带的Proxy类挺相似的。它会根据某个给定的类创建子类,并且所有非final的方法都带有回调钩子。最终通过字节码技术动态创建子类实例。

1. 定义类(无需接口):

public class MyCglibClass {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

2. 创建MethodInterceptor:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method");
        return result;
    }
}

3. 创建代理实例:

public class Demo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyCglibClass.class);
        enhancer.setCallback(new MyMethodInterceptor());

        MyCglibClass proxy = (MyCglibClass) enhancer.create();
        proxy.doSomething();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Micek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值