JDK动态代理

本文介绍了JDK动态代理的实现原理,通过Proxy和InvocationHandler两个核心类来创建代理对象。示例展示了如何创建接口的代理类,并在调用方法前后添加自定义逻辑。在测试中,注意到在IDE的debug模式下,代理对象会额外调用toString方法。同时,对比了JDK代理与CGLIB代理在方法内部调用上的区别。

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

一、JDK动态代理(只能代理接口,不能代理类)

主要用到这两个类 Proxy和InvocationHandler

Proxy,通过这个类的newProxyInstance方法可以创建代理类的实例对象。

InvocationHandler,动态代理类实现这个接口,可以对目标对象的方法进行处理

二、实现

接口

package com.sunshine.boot.proxy.jdk;

public interface IService {

    void test1();

}

实现类

package com.sunshine.boot.proxy.jdk;

public class ServiceA implements IService{
    @Override
    public void test1() {
        System.out.println("我是serviceA的test1方法");
    }
}

动态代理类

package com.sunshine.boot.proxy;

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

/**
 * jdk动态代理类
 */
public class JDKProxyTest implements InvocationHandler {
    // 被代理的目标对象
    private Object target;

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

  /**
     * 
     * @param proxy 代理对象
     * @param method 被代理对象的方法
     * @param args 被代理对象的方法中的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行方法名称"+method.getName());
        System.out.println("我是代理对象的before");
        Object result = method.invoke(this.target, args);
        System.out.println("我是代理对象的after");
        return result;
    }

    public static <T> T createProxy(Object target, Class<T> targetInterface) {
        if(!targetInterface.isInterface()) {
            throw new RuntimeException("targetInterface必须是接口类型!");
        }else if(!targetInterface.isAssignableFrom(target.getClass())) {
            throw new RuntimeException("target必须是targetInterface接口的实现类!");
        }else {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new JDKProxyTest(target));
        }
    }
}

三、测试

   public static void main(String[] args) {

        IService proxyA = JDKProxyTest.createProxy(new ServiceA(), IService.class);
        proxyA.test1();

    }

结果:

执行方法名称test1
我是代理对象的before
我是serviceA的test1方法
我是代理对象的after

彩蛋

在idea中,我采用debug模式进行jdk动态代理测试,会出现下面结果

执行方法名称toString
我是代理对象的before
我是代理对象的after
执行方法名称test1
我是代理对象的before
我是serviceA的test1方法
我是代理对象的after

执行方法名称toString
我是代理对象的before
我是代理对象的after

查询网上资料发现,出现上述情况,是因为在debug模式下idea会调用被代理类的toString()方法。代理类会代理该类的所有方法,因此会重复输出。

补充:

JDK代理,当实现类中test1方法中调用test2方法,只是代理test1,不会在test1方法中代理test2

执行结果

执行方法名称test1
我是代理对象的before
我是serviceA的test1方法
我是serviceA的test2方法
我是代理对象的after

cglib代理,会代理所有方法,当test1方法中调用test2方法,这两个方法都会代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值