博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
静态代理与动态代理(JDK代理/cglib代理)的区别
阅读量:7219 次
发布时间:2019-06-29

本文共 5859 字,大约阅读时间需要 19 分钟。

前提知识:

  

  

   

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

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

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

静态代理图解与代码说明:  本质是对于 的一种应用。

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

JDK代理主要是通过java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)函数基于实现,类似来创建代理类

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 this38 );39 }40 41 /**42 * 通过反射执行回调方法 在代理实例上处理方法调用并返回结果。43 * Object proxy : 代理对象(几乎不用)44 * java.lang.reflect.Method method : 实际执行的方法对象45 * Object[] args : 实际调用方法中的参数46 * 返回的是方法执行之后的返回值47 */48 @Override49 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 @Test86 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字节码操作框架子包,利用的原理生成代理类

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); 不推荐    }}@Testpublic 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);}

 更多详情:请参考

转载于:https://www.cnblogs.com/qq1452753919/p/10507227.html

你可能感兴趣的文章
rhel6.2配置在线yum源
查看>>
分级聚类算法
查看>>
Web Services 入门(之二)
查看>>
随机模拟MCMC和Gibbs Sampling
查看>>
网络安全是一种态度
查看>>
POJ1131 Octal Fractions
查看>>
mysql-ulogd2.sql
查看>>
119. Pascal's Triangle II - Easy
查看>>
349. Intersection of Two Arrays - Easy
查看>>
[算法练习]最长公共子串(LCS)
查看>>
p转c++
查看>>
树(tree)
查看>>
codevs——2645 Spore
查看>>
ssh服务之 远程登录和端口转发
查看>>
java环境配置正确,但是tomcat不能启动的解决办法
查看>>
我就是想找个人聊聊天,说说我这近四年来的经历
查看>>
不同的测试方法使用的场景
查看>>
Hadoop快速入门
查看>>
Problem S
查看>>
SVN上传的时候没法显示文件名,只显示后缀名
查看>>