静态代理与动态代理(JDK代理/cglib代理)的区别

前提知识:

  (暂未发布)java代理设计模式

  (暂未发布)java发射相关知识

   (暂未发布)java装饰设计模式

静态代理与动态代理的区别:

  静态代理:创建代理类java文件或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。

  动态代理:在程序运行时运用反射机制动态创建代理对象而成.在程序运行前代理类的.class文件不存在。

静态代理图解与代码说明:  本质是对于 (暂未发布)java装饰设计模式的一种应用。

动态代理主要包括两种模式JDK代理模式与cglib代理模式(参考spring的org.springframework.cglib.proxy包)

JDK代理主要是通过java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)函数基于(暂未发布)ClassLoader类加载机制实现,类似(暂未发布)java装饰设计模式来创建代理类

jdk代码说明:

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 
 5 import cn.it.TxManager;
 6 
 7 /**创始一个使用jdk的proxy完成动态代理工具 
 8  *  implements InvocationHandler 自己创建的一个回调的处理器
 9  * */
10 public class JDKProxyFactory implements InvocationHandler {
11     /**用于接收真实主题角色(目标对象) 多态的调用 */
12     private Object target;
13     
14     /**用于接收事务对象*/
15     private TxManager txManager;
16     
17     /**使用构造方法传递目标对象与事务对象*/
18     public JDKProxyFactory(Object target,TxManager txManager) {
19         this.target = target;
20         this.txManager = txManager;
21     }
22     /**创建代理对象*/
23     public Object createProxy() {
24         /** 使用java.lang.reflect.Proxy完成代理对象创建
25          * Proxy的static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ClassLoader 类加载器 
26          *     所有Class都可以拿到ClassLoader(只要拿到它就可以了)  用于加载 class类文件
27         interfaces 得到目标对象的实现接口的Class[]  
28             抽象主题角色 ,要从真实主题角色中拿到
29         java.lang.reflect.InvocationHandler 代理执行程序接口
30             主要是让咱们来完成相应的处理(添加上咱们想要在代理方法加添加的代码)
31             由于JDKProxyFactory本类implements实现InvocationHandler接口
32             InvocationHandler h 参数就是this对象
33          */
34         return Proxy.newProxyInstance(
35                 this.getClass().getClassLoader(), 
36                 target.getClass().getInterfaces(), //真实主题角色的接口
37                 this
38             );
39     }
40 
41     /**
42      * 通过反射执行回调方法 在代理实例上处理方法调用并返回结果。
43      *     Object proxy : 代理对象(几乎不用)
44      *  java.lang.reflect.Method method : 实际执行的方法对象
45      *  Object[] args : 实际调用方法中的参数
46      *  返回的是方法执行之后的返回值
47      */
48     @Override
49     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
50         
51         Object result = null;
52         try {
53             txManager.begin();//开始事务 调用事务对象的方法
54             /**
55              java.lang.reflect.Method method 的 Object invoke(Object obj, Object... args) 
56                 相当于result=target.invoke(args)*/
57             
58             /**    加强  target.getName() 能获得执行的对象的类名  能够针对某些类来进行增强
59                 if(target.getName().endwith("Dao")){
60                     //增强的代码
61                 }
62             */
63 
64             /**对执行的方法进行判断 针对某些方法对象增强
65                 save可以通过配置文件读取 dog4j解析  
66                 如 startwith  endwith  equals 来进行判断
67             */
68             if(method.endwith("save")){
69                 //增强save方法执行前的代码
70                 result = method.invoke(target, args);
71                 //增强save方法执行后的代码
72             }else{
73                 result = method.invoke(target, args);
74             }
75 
76             txManager.commit();//提交事务
77         } catch (Exception e) {
78             txManager.rollback();//回滚事务
79             e.printStackTrace();
80         }
81         return result;
82     }
83 }
84 
85 @Test
86 public void testProxy() throws Exception {
87     User user = new User("小红");
88     IUserService userService = new UserServiceImpl();
89     TxManager txManager = new TxManager();
90 
91     JDKProxyFactory handler = new JDKProxyFactory(userService,txManager);
92     IUserService proxy = (IUserService)handler.createProxy();
93     // JDK底层使用的是装饰设计模式的代理
94     //UserServiceImpl proxy = (UserServiceImpl)handler.createProxy();会报错 CGlib不会报错
95 
96     //proxy.update();
97     proxy.save(user);
98 }

 cglib代理模式主要是通过org.springframework.cglib.proxy包利用spring的jar包中内置的asm字节码操作框架子包,利用(暂未发布)java继承增强的原理生成代理类

Cglib代理模式代码案例说明
import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/***cglib创建的 动态代理工具 */
public class CglibProxyFactory implements MethodInterceptor {
    private Object target;
    private TxManager txManager;
    public CglibProxyFactory(Object target,TxManager txManager) {
        this.target = target;
        this.txManager = txManager;
    }

    // 创建代理对象
    public Object createProxy() {
        // 1.创建Enhancer
        Enhancer enhance = new Enhancer();

        // 2.参数:传递目标对象的Class 这样enhance对象就是目标对象的子类 底层使用子类继承的方式来增强父类方法
        enhance.setSuperclass(target.getClass());

        // 3.设置回调操作 (相当于InvocationHandler)
        //传入Callback callback   CglibProxyFactory implements MethodInterceptor implements Callback
        //所以  this也就是callback对象
        enhance.setCallback(this);

        return enhance.create();
    }

    /**
     * 回调方法  参考 InvocationHandler中的invoke方法内的写法
     *     Object proxy : 代理对象(几乎不用)
     *  Method method : 执行的方法
     *  Object[] args : 方法中的参数
     *  MethodProxy mehtodProxy : 代理方法(用不到) 子类复写的方法
     *  返回的是方法执行之后的返回值
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methdoProxy) throws Throwable {
        System.out.println("日志操作....");
        return method.invoke(target, args); // 与jdk的proxy中操作类似
        // return methdoProxy.invokeSuper(proxy, args); 不推荐
    }
}

@Test
public void testProxy() throws Exception {
    User user = new User("小红");
    //真实主题角色
    UserServiceImpl userService = new UserServiceImpl();
    TxManager txManager = new TxManager();

    //代理主题主题没创建出来
    CglibProxyFactory handler = new CglibProxyFactory(userService, txManager);
    UserService obj = (UserService)handler.createProxy();
    UserServiceImpl obj = (UserServiceImpl)handler.createProxy();
    // UserServiceImpl$$EnhancerByCGLIB$$2536a285
    System.out.println(obj.getClass());    
    obj.save(user);
}

 更多详情:请参考我的GitHub

posted @ 2019-03-10 21:16  等价交换原则  阅读(1070)  评论(0编辑  收藏  举报