JDK接口动态代理
JDK自带的动态代理通过动态的根据接口生成字节码(实现接口的一个具体类)的方式,为接口的实现类提供代理。被代理的对象和代理对象通过InvocationHandler建立关联
package com.tom; import com.tom.model.User; import com.tom.service.IUserService; import com.tom.service.UserService; import java.lang.reflect.*; class JdkInvocationHandler<T> implements InvocationHandler { //target是被代理的对象,构造注入到InvocationHandler中 private T target; public JdkInvocationHandler(T target) { this.target = target; } //invoke方法由代理对象调用,其中的proxy即是代理对象(不是被代理的对象) //method和args是代理对象要执行的方法及其参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(String.format("Start to call %s", method.getName())); Object obj = method.invoke(this.target, args); System.out.println(String.format("End to call %s", method.getName())); return obj; } } public class JdkProxyTest { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { InvocationHandler h = new JdkInvocationHandler<IUserService>(new UserService()); //****************第一种方法**************** //获得JDK的Proxy类字节码,类型为com.sun.proxy.$Proxy0 Class proxyClass = Proxy.getProxyClass(UserService.class.getClassLoader(), new Class[]{IUserService.class}); //获得com.sun.proxy.$Proxy0还有InvocationHandler参数的构造方法 Constructor proxyConstructor = proxyClass.getConstructor(InvocationHandler.class); //构造$Proxy0的实例 IUserService service = (IUserService) proxyConstructor.newInstance(h); //调用$Proxy0的save方法,方法实现是将方法调用转到InvocationHandler.invoke的调用 service.save(new User()); //****************第二种方法**************** //使用Proxy.newProxyInstance一步到位创建$Proxy0实例 service = (IUserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{IUserService.class}, h); service.save(new User()); } }
cglib类动态代理
cglib是一个开源项目! 是强大的,高性能字节码生成类库,它可以在运行期扩展Java类与实现Java接口。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。通过使用CGLIB来为那些没有接口的类创建代理对象。
Spring AOP提供了JDK接口动态代理和基于cglib类代理两种方式。使用cglib代理时,需要在配置中显式指明要使用cglib代理
cglib通过运行时创建被代理类的子类的方式生成字节码,通过被代理类的子类提供代理功能。因此声明为final的类不能被代理
CGLIB类动态代理
package com.tom; import com.tom.model.User; import com.tom.service.IUserService; import com.tom.service.UserService; import net.sf.cglib.proxy.*; import java.lang.reflect.Method; class UserServiceMethodInterceptor1 implements MethodInterceptor { @Override /** * * @param o 代理对象,例如com.tom.service.UserService$$EnhancerByCGLIB$$9257af4@360771 * @param method 被代理类定义的原始方法,比如UserService.save * @param objects 方法调用的参数列表 * @param methodProxy 对method进行代理的方法,比如CGLIB$save$0 * @return * @throws Throwable */ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //输出:MethodInterceptor is called ..save , CGLIB$save$0 System.out.println("MethodInterceptor1 is called .." + method.getName() + " , " + methodProxy.getSuperName()); //调动UserService的方法 return methodProxy.invokeSuper(o, objects); } } class UserServiceMethodInterceptor2 implements MethodInterceptor { @Override /** * * @param o 代理对象,例如com.tom.service.UserService$$EnhancerByCGLIB$$9257af4@360771 * @param method 被代理类定义的原始方法,比如UserService.save * @param objects 方法调用的参数列表 * @param methodProxy 对method进行代理的方法,比如CGLIB$save$0 * @return * @throws Throwable */ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //输出:MethodInterceptor is called ..save , CGLIB$save$0 System.out.println("MethodInterceptor2 is called .." + method.getName() + " , " + methodProxy.getSuperName()); //调动UserService的方法 return methodProxy.invokeSuper(o, objects); } } public class CglibTest { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserService.class); enhancer.setClassLoader(UserService.class.getClassLoader()); //Callback干啥的,Callback接口没有任何方法 //MethodInterceptor接口继承了Callback接口,因此这里可以注入三个MethodInterceptor的实例 enhancer.setCallbacks(new Callback [] {new UserServiceMethodInterceptor1(), new UserServiceMethodInterceptor2(), NoOp.INSTANCE}); //过滤?? enhancer.setCallbackFilter(new CallbackFilter() { @Override public int accept(Method method) { //UserService中定义的所有方法都要过滤一遍,比如save,delete,hashCode,equals,finalize等 if (method.getName().equals("save")) { return 0; //使用第一个拦截器(这里设置了两个Callback)进行拦截 } if (method.getName().equals("delete")) { return 1; } return 2; //使用第三个拦截器,不做任何拦截 } }); //创建代理类实例,因为代理类被代理类的子类,因此,需要考虑父类的构造 IUserService proxyObj = (IUserService) enhancer.create();//调用父类的构造方法,create的重载方法可以调用指定参数的构造方法 //代理对象调用方法 proxyObj.save(new User()); proxyObj.delete(new User()); proxyObj.hashCode(); //不会调用拦截器 System.out.println(proxyObj.getClass().getName()); } }
总结
cglib创建代理对象的速度比JDK动态代理慢几倍,代理对象调用方法执行时,cglib执行速度要比JDK快几倍,因此如果需要频繁的创建代理对象,可以使用JDK动态代理,如果代理对象是单例,考虑使用cglib代理
性能比较参考:http://exceptioneye.iteye.com/blog/1774631
相关推荐
Java设计模式——代理设计模式(静态代理和动态代理) 各种情况例子源码
java语言反射与动态代理学习笔记
NULL 博文链接:https://whp0731.iteye.com/blog/343787
java动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdfjava动态代理(JDK和cglib).pdf
java注解、反射和动态代理 简易Android Retrofit和Butter Knife 框架 https://blog.csdn.net/soulshui/article/details/123332183?spm=1001.2014.3001.5501
java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar /** * 代理模式 * 在开发者的角度来看,创建一个代理对象,提供给用户使用,避免用户直接访问真正的对象 * 在用户角度来看,就是普通的类方法...
本文首先介绍了AOP 的基本思想,然后针对它在JAVA 语言 中的实现,具体介绍了JAVA 的动态代理来怎样实现一个简单的AOP 容器
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。 代理模式是常用的java设计模式,他的特征是代理类与委托类有...
lotus domnio java代理输出html代理
该源码包含Java语言的动态代理和静态代理的详细demo,适合初学者系统了解Java代理机制
编程语言Java代理模式.pdf
Java的HTTP代理服务器 Smart Cache
lotus domnio java代理传值
java语言 netbeans平台 MySQL数据库 代理起口令认证等安全功能与信息中转功能
这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。Java 反射机制主要提供了以下功能: l 在运行时判断任意一个对象所属的类; l 在运行时构造任意一个类的对象; l ...
lotus domino java代理_获取传递值json
自己实现java动态代理、自动注入、切面编程(类似于Spring IOC、AOP)
java设计模式【之】Cglib动态代理【源码】【场景:帮爸爸买菜】 /** * 代理模式 * 在开发者的角度来看,创建一个代理对象,提供给用户使用,避免用户直接访问真正的对象 * 在用户角度来看,就是普通的类方法调用...
我们知道,使用 JNI 调用 .dll/.so 共享类库是非常非常麻烦和痛苦...使用 JNA ,不需要再编写适配用的 .dll/.so ,只需要在 Java 中编写一个接口和一些代码,作为 .dll/.so 的代理,就可以在 Java 程序中调用 dll/so 。
lotus domnio java代理获取当前用户名