Java进阶之 JDK动态代理与Cglib动态代理
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java进阶之 JDK动态代理与Cglib动态代理,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5354字,纯文字阅读大概需要8分钟。
内容图文
一、动态代理概述:与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式【Proxy Pattern】),
动态代理类的字节码是在程序运行时由Java反射机制动态生成。
注意:1、AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理
2、Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于AspectJ较差
二、JDK动态代理 [对有实现接口的对象做代理]
1、JDK动态代理中 需要了解的两个重要的类或接口 [InvocationHandler 和 Proxy]
① InvocationHandler接口
public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; }参数说明:
Object proxy:指被代理的对象
Method method:我们所要调用被代理对象的某个方法的Method对象
Object[] args:被代理对象某个方法调用时所需要的参数
可以将InvocationHandler接口的子类想象成一个代理的最终操作类。
说明:每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类(Proxy)的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。同时在invoke的方法里 我们可以对被代理对象的方法调用做增强处理(如添加事务、日志、权限验证等操作)。
② Proxy类
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,该类常用的调用方法如下:
newProxyInstance方法参数说明如下:
ClassLoader loader:类加载器,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
Class<?>[] interfaces:得到被代理类全部的接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口,这样我就能调用这组接口中的方法了
InvocationHandler h:得到InvocationHandler接口的子类实例
2、JDK动态代理代码示例:
首先我们定义了一个Subject类型的接口:Subject.java
public interface Subject { public void visit(); }接着定义一个接口的实现类,这个类就是我们示例中的被代理对象:RealSubject.java
/** * 被代理类 * @author lvzb.software@qq.com * */ public class RealSubject implements Subject { @Override public void visit() { System.out.println("I am 'RealSubject',I am the execution method"); } }第三步 定义一个动态代理类(必须要实现 InvocationHandler 这个接口):DynamicProxy.java
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * JDK动态代理类 * @author lvzb.software@qq.com * */ public class DynamicProxy implements InvocationHandler { // 我们要代理的真实对象(委托对象) private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public DynamicProxy(Object obj){ this.subject = obj; } @Override public Object invoke(Object object, Method method, Object[] args) throws Throwable { // 在代理真实对象操作前 我们可以添加一些自己的操作 System.out.println("before proxy invoke"); // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 method.invoke(subject, args); // 在代理真实对象操作后 我们也可以添加一些自己的操作 System.out.println("after proxy invoke"); return null; } }最后代理测试类:Client.java
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { // 我们要代理的真实对象 Subject realSubject = new RealSubject(); // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象调用方法的 InvocationHandler handler = new DynamicProxy(realSubject); /* * 通过Proxy的newProxyInstance方法来动态创建我们的代理对象,我们来看看其三个参数<br/> * 参数一:我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象<br/> * 参数二:我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了<br/> * 参数三:我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上 */ Subject proxyInstance = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), RealSubject.class.getInterfaces(), handler); System.out.println(proxyInstance.getClass().getName()); proxyInstance.visit(); } }运行->控制台输出结果如下:
com.sun.proxy.$Proxy0 before proxy invoke I am 'RealSubject',I am the execution method after proxy invoke
三、Cglib(Code Generation Library)动态代理 [对没有实现接口的普通类做代理]
1、概述:
Cglib是一个优秀的动态代理框架,它的底层使用ASM(JAVA字节码处理框架)在内存中动态的生成被代理类的子类。使用CGLIB即使被代理类没有实现任何接口也可以实现动态代理功能。但是不能对final修饰的类进行代理。
2、原理:
通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。
<JDK动态代理与CGLib动态代理均是实现Spring AOP的基础>
3、使用:
使用Cglib前需要导入以下两个jar文件:
asm.jar – Cglib的底层实现。
【cglib包的底层是使用字节码处理框架ASM来转换字节码并生成新的类,所以cglib包要依赖于asm包】
cglib.jar - Cglib的核心jar包。
4、Cglib动态代理代码示例:
首先定义一个没有实现接口的代理委托类:CglibRealSubject.java
/** * 没有实现接口的代理委托类 * @author lvzb.software@qq.com * */ public class CglibRealSubject{ public void visit() { System.out.println("I am 'RealSubject',I am the execution method"); } }接着 定义一个Cglib动态代理类: CglibDynamicProxy.java
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 使用cglib动态代理 * @author lvzb.software@qq.com * */ public class CglibDynamicProxy implements MethodInterceptor { private Object target; /** * 创建代理对象 * @param target 被代理的对象 * @return */ public Object getProxyInstance(Object target){ this.target = target; // 声明增强类实例 Enhancer enhancer = new Enhancer(); // 设置被代理类字节码,CGLIB根据字节码生成被代理类的子类 enhancer.setSuperclass(this.target.getClass()); // 设置要代理的拦截器,回调函数,即一个方法拦截 new MethodInterceptor() enhancer.setCallback(this); // 创建代理对象 实例 return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在代理真实对象操作前 我们可以添加一些自己的操作 System.out.println("前置代理,增强处理"); proxy.invokeSuper(obj, args); // 在代理真实对象操作后 我们也可以添加一些自己的操作 System.out.println("后置代理,增强处理"); return null; } }最后测试客户端类: CglibClient .java
public class CglibClient { public static void main(String[] args) { CglibDynamicProxy cglib = new CglibDynamicProxy(); CglibRealSubject realSubject = (CglibRealSubject) cglib.getProxyInstance(new CglibRealSubject()); realSubject.visit(); } }运行->控制台输出结果如下:
前置代理,增强处理 I am 'RealSubject',I am the execution method 后置代理,增强处理
四、扩展学习
关于什么是AOP思想?Spring AOP实现原理?及什么样的系统业务场景我们可以使用到AOP这种动态代理技术?
小吕推荐一篇非常值得阅读和学习的文章: Spring AOP实现原理与CGLIB应用
—————————————————————————————————————
如果文章内容对您有帮助, 不要忘记 顶 一下,来支持一下哦!
如果您对文章内容有任何疑问或有更好的见解, 可以通过评论留言或发邮件的方式联系我:
ice_zhengbin@163.com
如果需要转载,请注明出处,谢谢!!
—————————————————————————————————————
原文:http://blog.csdn.net/janice0529/article/details/42884019
内容总结
以上是互联网集市为您收集整理的Java进阶之 JDK动态代理与Cglib动态代理全部内容,希望文章能够帮你解决Java进阶之 JDK动态代理与Cglib动态代理所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。