动态代理 - JDK动态代理 & CGLIB动态代理

本文详细介绍了JDK动态代理和CGLIB动态代理的使用步骤,包括创建接口、实现类、代理类和代理工厂。JDK代理适用于实现了接口的类,而CGLIB则能代理未实现接口的类。在性能上,大部分情况下JDK代理优于CGLIB,但CGLIB可以代理final类和方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:JDK动态代理

1,JDK动态代理类使用步骤

1,定义一个接口及其实现类; 
2,自定义 InvocationHandler 并重写invoke方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)
并自定义一些处理逻辑; 
3,通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 
方法创建代理对象;

2,创建接口及实现类

接口
public interface SendMessage {
    String send();
}

实现类(目标类)
public class AliSendMessage implements SendMessage {
    @Override
    public void send() {
        String str = "阿里代理发送验证码";
        System.out.println(str);
    }
}

3,创建代理类

public class SendMessageProxy implements InvocationHandler {
    private Object target;

    public SendMessageProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	// 代理增强内容
        System.out.println("代理增强");
        // 目标类执行
        method.invoke(target,args);
        // 代理增强内容
        System.out.println("代理增强");
        return null;
    }
}

4,JDK代理工厂(创建代理对象)


public class JdkProxyFactory {
/**
newProxyInstance方法的三个参数:

	target.getClass().getClassLoader() – 定义代理类的类加载器
	target.getClass().getInterfaces() - 目标类实现的接口列表
	h – 使用的代理类对象
1,
*/
    public static Object getProxy(Object target){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
        target.getClass().getInterfaces(),new SendMessageProxy(target));
    }
}

5,创建使用代理对象

public class ProxyTest {
    public static void main(String[] args) {
        SendMessage sendMessage =(SendMessage) JdkProxyFactory.getProxy(new AliSendMessage());
        sendMessage.send();
    }
}

6,结果

代理增强
阿里代理发送验证码
代理增强

二,CGLIB动态代理

1,CGLIB 动态代理类使用步骤

1,定义一个类(目标类); 
2,自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法,
   和 JDK 动态代理中的 invoke 方法类似;
3,通过 Enhancer 类的 create()创建代理类;

2,定义一个目标类

public class SendMessage {
    public void send() {
        System.out.println("目标类的目标方法");
    }
}

3,定义代理拦截器(拦截器可以约定需要增强的功能)

public class ProxyMethodInterceptor implements MethodInterceptor {

    /**
     * @param o           代理对象(目标对象)
     * @param method      被拦截的方法(需要增强的方法)
     * @param args        方法入参
     * @param methodProxy 用于调用原始方法
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("切面功能增强");
        methodProxy.invokeSuper(o,args);
        System.out.println("切面功能增强");
        return null;
    }
}

4,代理工厂(从中得到代理类)

public class ProxyFactory {
	//  参数 Class<?> tClass是目标类的Class
    public static Object getProxyClass(Class<?> tClass){
        // 创建动态代理增强类
        Enhancer enhancer = new Enhancer();
        // 设置类加载器
        enhancer.setClassLoader(tClass.getClassLoader());
        // 设置被代理类(目标类)
        enhancer.setSuperclass(tClass);
        // 设置方法拦截器
        enhancer.setCallback(new ProxyMethodInterceptor());
        // 创建代理类
        return enhancer.create();
    }
}

5,测试

public class CglibProxyTest {
    public static void main(String[] args) {
        // 测试
        SendMessage proxyClass = (SendMessage) ProxyFactory.getProxyClass(SendMessage.class);
        proxyClass.send();
    }
}

结果
切面功能增强
目标类的目标方法
切面功能增强

三,JDK 动态代理和 CGLIB 动态代理对比

JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。
 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能将被代理类声明为 final 类型的类和方法。
就二者的效率来说,大部分情况都是 JDK 动态代理更优秀, 随着 JDK 版本的升级,这个优势更加明显。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值