jdk动态代理实现原理(JDK)

 2025-08-09 04:18:02  阅读 967  评论 0

摘要:基于 JDK 实现动态代理JDK 动态代理的原理是利用反射机制,在运行时创建代理类,必要条件是代理对象基于接口实现。创建一个接口及其实现类。public interface IService { void sayHello(); }public class JdkServiceImpl implements IService { @Override public void sayHel

JDK/CGLIB/Spring三种方式实现动态代理

基于 JDK 实现动态代理

JDK 动态代理的原理是利用反射机制,在运行时创建代理类,必要条件是代理对象基于接口实现。

创建一个接口及其实现类。

public interface IService {

    void sayHello();

}
public class JdkServiceImpl implements IService {

    @Override
    public void sayHello() {
        System.out.println("Hello JAVA Proxy");
    }

}

创建代理处理类,必须实现 InvocationHandler 接口。

@AllArgsConstructor
public class ServiceInvocationHandler implements InvocationHandler {

    private final Object target;

    @Override
    public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println("-------- begin ----------");
        Object result = method.invoke(target, args);
        System.out.println("-------- end ----------");
        return result;
    }

}

执行动态代理

public class JdkProxyTest {

    public static void main(String[] args) {
        IService service = new JdkServiceImpl();
        ServiceInvocationHandler handler = new ServiceInvocationHandler(service);
        IService proxy = (IService) Proxy.newProxyInstance(JdkProxyTest.class.getClassLoader(), new Class[]{IService.class}, handler);
        proxy.sayHello();

        System.out.println();
        System.out.println(proxy.getClass().getSimpleName() +
                " extend " + proxy.getClass().getSuperclass().getSimpleName() +
                " implements " + Arrays.stream(proxy.getClass().getInterfaces())
                .map(Class::getSimpleName)
                .collect(Collectors.joining(",")));
    }

}

输出结果如下,可以看出在 sayHello 方法前后,执行了代理处理类中的代码输出,说明通过 JDK 动态代理实现了代理增强。

-------- begin ----------
Hello JAVA Proxy
-------- end ----------

$Proxy0 extend Proxy implements IService

最后一行的输出显示了动态生成的代理类的继承关系,该类实现代理对象的接口,JDK 动态代理的继承机制决定了只能对接口进行代理。

JDK/CGLIB/Spring三种方式实现动态代理

基于 Cglib 实现动态代理

Cglib 动态代理的原理是利用字节码技术,在运行时创建一个继承代理类的 class,所以代理对象不需要实现接口,但要求被代理类及方法必须不是 final 的

创建一个需要被代理的类

public class CglibServiceImpl {

    public void sayHello() {
        System.out.println("Hello Cglib Proxy");
    }

}

创建方法拦截器,必须实现 MethodInterceptor 接口,实现代理增强

public class ServiceInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
        System.out.println("-------- begin ----------");
        Object result = methodProxy.invokeSuper(obj, params);
        System.out.println("-------- end ----------");
        return result;
    }

}

执行代理操作

public class CglibProxyTest {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(CglibServiceImpl.class);
        enhancer.setCallback(new ServiceInterceptor());
        CglibServiceImpl proxy = (CglibServiceImpl) enhancer.create();
        proxy.sayHello();

        System.out.println();
        System.out.println(proxy.getClass().getSimpleName() +
                " extend " + proxy.getClass().getSuperclass().getSimpleName() +
                " implements " + Arrays.stream(proxy.getClass().getInterfaces())
                .map(Class::getSimpleName)
                .collect(Collectors.joining(",")));
    }

}

输出结果如下

-------- begin ----------
Hello Cglib Proxy
-------- end ----------

ServiceImpl$EnhancerByCGLIB$ef25c05 extend ServiceImpl implements Factory

JDK/CGLIB/Spring三种方式实现动态代理

基于 Spring 的 ProxyFactory 实现动态代理

Spring 也提供了自己动态代理实现,但其实做的还是整合的工作,底层依然是基于上文中的两种技术。

创建方法拦截器,需要实现 MethodInterceptor 接口(这个接口在 org.aopalliance.intercept 包中,与 cglib 中的不是同一个)。

public class AopInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("-------- begin ----------");
        Object result = invocation.proceed();
        System.out.println("-------- end ----------");
        return result;
    }

}

执行代理操作

public class SpringProxyTest {

    public static void main(String[] args) {
        executeJdkProxy();
//        executeCglibProxy();
    }

    public static void executeJdkProxy() {
        ProxyFactory factory = new ProxyFactory();
        factory.setInterfaces(IService.class);
        factory.setTarget(new JdkServiceImpl());
        factory.addAdvice(new AopInteceptor());
        IService proxy = (IService) factory.getProxy();
        proxy.sayHello();
        printClassName(proxy);
    }

    public static void executeCglibProxy() {
        ProxyFactory factory1 = new ProxyFactory();
        factory1.setTarget(new CglibServiceImpl());
        factory1.addAdvice(new AopInteceptor());
        CglibServiceImpl proxy1 = (CglibServiceImpl) factory1.getProxy();
        proxy1.sayHello();
        printClassName(proxy1);
    }

    public static void printClassName(Object proxy) {
        System.out.println();
        System.out.println(proxy.getClass().getSimpleName() +
                " extend " + proxy.getClass().getSuperclass().getSimpleName() +
                " implements " + Arrays.stream(proxy.getClass().getInterfaces())
                .map(Class::getSimpleName)
                .collect(Collectors.joining(",")));
    }

}

执行 executeJdkProxy 方法输出

-------- begin ----------
Hello World
-------- end ----------

$Proxy18 extend Proxy implements IService,SpringProxy,Advised,DecoratingProxy

执行 executeCglibProxy 方法输出

-------- begin ----------
Hello Cglib Proxy
-------- end ----------

CglibServiceImpl$EnhancerBySpringCGLIB$57b39275 extend CglibServiceImpl implements SpringProxy,Advised,Factory

通过最后输出的类继承结构可以看出在 ProxyFactory 之下的实现原理,executeJdkProxy 与 executeCglibProxy 方法不同的一点是调用 factory.setInterfaces 设置了接口,如果不设置接口,那么底层还是使用 cglib 实现,虽然最终呈现出来的效果是一样的。所以具体使用哪种方案实现,并不处决了代理对象是不是接口,而是有没有向 ProxyFactory 设置接口(当然设置接口的前提首先得实现接口)。

ProxyFactory 的实现源码分析

根据方法 getProxy 进行源码跟踪

public class ProxyFactory extends ProxyCreatorSupport {
    
    public Object getProxy() {
		return createAopProxy().getProxy();
	}

}

createAopProxy 方法在其父类中实现,调用 AopProxyFactory.createAopProxy 方法创建一个 AopProxy 对象,AopProxyFactory 默认使用 DefaultAopProxyFactory。

public class ProxyCreatorSupport extends AdvisedSupport {

    private AopProxyFactory aopProxyFactory;

    public ProxyCreatorSupport() {
        this.aopProxyFactory = new DefaultAopProxyFactory();
    }
    
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

}

在 DefaultAopProxyFactory 的 createAopProxy 方法,可以看到根据不同的条件会选择创建不同的 AopProxy。

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        } else {
            return new JdkDynamicAopProxy(config);
        }
    }
    
}

AopProxy 的实现类分别代表不同的实现策略

JDK/CGLIB/Spring三种方式实现动态代理

以 JdkDynamicAopProxy 的实现为例,可以看到最终调用的还是 JDK 提供的 Proxy.newProxyInstance() 方法创建代理对象。

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

}

版权声明:我们致力于保护作者版权,注重分享,被刊用文章【jdk动态代理实现原理(JDK)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!;

原文链接:https://www.yxiso.com/zhishi/2033183.html

发表评论:

关于我们
院校搜的目标不仅是为用户提供数据和信息,更是成为每一位学子梦想实现的桥梁。我们相信,通过准确的信息与专业的指导,每一位学子都能找到属于自己的教育之路,迈向成功的未来。助力每一个梦想,实现更美好的未来!
联系方式
电话:
地址:广东省中山市
Email:beimuxi@protonmail.com

Copyright © 2022 院校搜 Inc. 保留所有权利。 Powered by BEIMUCMS 3.0.3

页面耗时0.0347秒, 内存占用1.93 MB, 访问数据库24次

陕ICP备14005772号-15