Java中的动态代理

Java中的动态代理

说起动态代理,首先想到的就是 Spring
,在 Spring
中有两种动态代理方式: JDK
动态代理和 Cglib
动态代理。

JDK动态代理

JDK
动态代理是 Java
本来就有的一种代理方式,关键类是 java.lang.reflect.InvocationHandler

我们先创建一个简单的 SpringBoot
项目,然后创建 UserService
UserServiceImpl

public interface UserService {
    void add();
}



@Service
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("添加用户...");
    }
}
复制代码

这个 UserServiceImpl
就是我们要代理的类,它继承了 UserService
接口,所以使用 JDK
动态代理。

然后我们创建一个简单的类来模拟事务处理

@Component
public class TransactionManager {

    public void begin() {
        System.out.println("创建事务");
    }

    public void commit() {
        System.out.println("提交事务");
    }

    public void rollback() {
        System.out.println("回滚事务");
    }
}
复制代码

代理器

最后要创建代理器了,首先要实现 java.lang.reflect.InvocationHandler
这个接口,复写 invoke
方法。

@Component
public class JdkProxyHandler implements InvocationHandler {

    /**
     * 事务处理器
     */
    @Resource
    private TransactionManager transcationManager;

    @Setter
    private Object target;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        Object ret = null;
        try {
            //模拟事务开始
            transcationManager.begin();
            ret = method.invoke(target, args);
            //模拟事务提交
            transcationManager.commit();
        } catch (Exception e) {
            //模拟事务回滚
            transcationManager.rollback();
            e.printStackTrace();
        }
        return ret;
    }

    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(
                //类加载器
                this.getClass().getClassLoader(),
                //为哪些接口做代理
                target.getClass().getInterfaces(),
                //增强对象
                this);
    }
}
复制代码

测试

首先我们把代理器和要代理的对象注入进来,通过 jdkProxyHandler.getProxy
方法得到代理对象。

@SpringBootTest
class Springdemo1ApplicationTests {

    @Resource
    private JdkProxyHandler jdkProxyHandler;

    @Resource
    private UserService userService;

    @Test
    public void testJdkProxy() throws Exception {
       //设置要代理的对象
        jdkProxyHandler.setTarget(userService);
        //得到代理对象
        UserService proxy = jdkProxyHandler.getProxy();
        //代理对象执行方法
        proxy.add();
    }
}
复制代码

执行结果:

Java中的动态代理

Cglib动态代理

我们也要实现一个接口 InvocationHandler
,不过这个接口是 Spring
提供的 org.springframework.cglib.proxy.InvocationHandler
。复写其中的 invoke
方法。
获取代理类的方式不一样,使用 org.springframework.cglib.proxy.Enhancer#create()
这个方法获取。

@Component
public class CglibProxyHandler implements InvocationHandler {

    /**
     * 事务处器
     */
    @Resource
    private TransactionManager transcationManager;

    @Setter
    private Object target;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        Object ret = null;
        try {
            //模拟事务开始
            transcationManager.begin();
            ret = method.invoke(target, args);
            //模拟事务提交
            transcationManager.commit();
        } catch (Exception e) {
            //模拟事务回滚
            transcationManager.rollback();
            e.printStackTrace();
        }
        return ret;
    }

    public <T> T getProxy() {
        //增强类
        Enhancer hancer = new Enhancer();
        //对哪一个父类增强
        hancer.setSuperclass(target.getClass());
        //如何设置增强
        hancer.setCallback(this);
        //返回并创建对象
        return (T) hancer.create();
    }
}
复制代码

测试

同样的,我们在测试类里加上下面的代码,测试 cglib
代理:

@Resource
private CglibProxyHandler cglibProxyHandler;

@Test
public void testCglibProxy() throws Exception {
    //设置要代理的对象
    cglibProxyHandler.setTarget(userService);
    //得到代理对象
    UserService proxy = cglibProxyHandler.getProxy();
    //代理对象执行方法
    proxy.add();
}
复制代码

执行结果:

Java中的动态代理

总结

Java中的动态代理

可以看到, JDK
动态代理,代理的是实现了接口的类,而 Cglib
则没有这个要求,它是把要代理的类作为父类,然后创建一个代理类继承父类,复写并增强父类中的方法。

最后

欢迎大家关注我的公众号,共同学习,一起进步。加油

Java中的动态代理

本文使用 mdnice
排版

原文 

https://juejin.im/post/5f1bfe2c6fb9a07e802060f2

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Java中的动态代理

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址