JDK动态代理和CGLIB动态代理举例

深碍√TFBOYSˉ_ 2022-04-05 10:00 396阅读 0赞

文章目录

          • 前言
          • 接口和接口实现类
          • JDK 动态代理
            • 实现 InvocationHandler 构建代理对象
            • 测试方法
            • 结果
          • CGLIB 动态代理
            • 实现 MethodInterceptor 构建代理对象
            • 测试方法
            • 结果
          • 参考文档
前言

代理模式的实现分为静态代理和动态代理,静态代理比较简单,动态代理分为JDK 动态代理和CGLIB动态代理,本文举一个JDK动态代理的小例子。

接口和接口实现类
  • MyInterface.java

    public interface MyInterface {

    1. void printName(String name);

    }

  • MyClass.java

    public class MyClass implements MyInterface {

    1. @Override
    2. public void printName(String name) {
    3. System.out.println("Your name is "+name);
    4. }

    }

JDK 动态代理

JDK 的基础类库为我们提供了动态代理的实现方案。
需要四个点,3和4可以写到2中,也可以单独写通过构造方法传递到2中:
1、创建接口和接口实现类
2、实现 java.lang.reflect.InvocationHandler 接口,从写 invoke 方法,invoker 方法内部使用反射机制调用目标对象的方法
3、自定义方法 将目标对象委托给代理对象
4、将目标对象传递给 invoke 方法

实现 InvocationHandler 构建代理对象

构建代理对象的过程可以单独存在,不过那样要将目标对象通过构造方法传递到实现类内部,本文参考了 《深入浅出 Mybatis 技术原理与实战》,写在了实现类内部,综合考虑,这样其实使代码简洁了很多。

  • MyJDKProxy.java

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

    /* JDK 动态代理 @author WuJie /
    public class MyJDKProxy implements InvocationHandler {

    1. //真实的服务对象
    2. private Object target;
    3. /** * 将目标对象委托给代理对象并返回代理对象 * @param target * @return */
    4. public Object bind(Object target){
    5. this.target=target;
    6. //取得代理对象
    7. return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    8. }
  1. /** * 当通过代理实例化接口并调用接口方法时,将自动调用 invoke 方法,invoke 方法内部通过反射机制调用目标对象的方法 */
  2. @Override
  3. public Object invoke(Object proxy, Method method, Object[] args)
  4. throws Throwable {
  5. System.out.println("自动运行开始");
  6. //反射机制调用方法
  7. method.invoke(target,args);
  8. System.out.println("自动运行结束");
  9. return null;
  10. }
  11. }
测试方法
  1. import org.junit.Test;
  2. /** * JDK动态代理测试 * @author WuJieJecket * */
  3. public class TestMyJDKProxy {
  4. @Test
  5. public void testPrintName(){
  6. MyJDKProxy myProxy=new MyJDKProxy();
  7. MyInterface myInterface=(MyInterface)myProxy.bind(new MyClass());
  8. myInterface.printName("Jecket");
  9. }
  10. }
结果
  1. 自动运行开始
  2. Your name is Jecket
  3. 自动运行结束
CGLIB 动态代理

和JDK动态代理相比,接口不是必须的,当然也可以有

实现 MethodInterceptor 构建代理对象
  1. import java.lang.reflect.Method;
  2. import org.springframework.cglib.proxy.Enhancer;
  3. import org.springframework.cglib.proxy.MethodInterceptor;
  4. import org.springframework.cglib.proxy.MethodProxy;
  5. public class MyCglibProxy implements MethodInterceptor {
  6. private Object target;
  7. /** * 创建代理对象 * @param target * @return */
  8. public Object bind(Object target){
  9. //传递目标对象
  10. this.target=target;
  11. //Enhancer:增强者
  12. Enhancer enhancer=new Enhancer();
  13. enhancer.setSuperclass(target.getClass());
  14. enhancer.setCallback(this);
  15. //创建代理对象
  16. return enhancer.create();
  17. }
  18. @Override
  19. public Object intercept(Object arg0, Method arg1, Object[] arg2,
  20. MethodProxy arg3) throws Throwable {
  21. System.out.println("自动调用开始");
  22. //arg1.invoke(target, arg2);
  23. arg3.invoke(target, arg2);
  24. System.out.println("自动调用结束");
  25. return null;
  26. }
  27. }
测试方法
  1. import org.junit.Test;
  2. /** * JDK动态代理测试 * @author WuJieJecket * */
  3. public class TestMyCglibProxy {
  4. //接口模式
  5. @Test
  6. public void testPrintName(){
  7. MyCglibProxy myProxy=new MyCglibProxy();
  8. MyInterface myInterface=(MyInterface)myProxy.bind(new MyClass());
  9. myInterface.printName("Jecket");
  10. }
  11. //非接口模式
  12. @Test
  13. public void testPrintName2(){
  14. MyCglibProxy myProxy=new MyCglibProxy();
  15. MyClass myClass=(MyClass)myProxy.bind(new MyClass());
  16. myClass.printName("Jecket");
  17. }
  18. }
结果
  1. 自动调用开始
  2. Your name is Jecket
  3. 自动调用结束
  4. 自动调用开始
  5. Your name is Jecket
  6. 自动调用结束
参考文档

[1]、https://www.cnblogs.com/luoquan/p/5304296.html
[2]、https://www.cnblogs.com/MOBIN/p/5597215.html
[3]、《深入浅出 Mybatis 技术原理与实战》

发表评论

表情:
评论列表 (有 0 条评论,396人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JDK动态代理CGLib动态代理

        JDK 动态代理是 JVM 根据传进来的对象,动态的创建对象的代理对象并返回。     CGLib 动态代理比较复杂,它是通过继承的方式来实现类的代理。 JDK