参考博客:
http://blog.csdn.net/heyutao007/article/details/49738887
https://www.jianshu.com/p/58759fef38b8
其中简书博客中,代码有些细节上的错误,本篇基本参照的是第一个链接
一、准备
本人1.8的jdk,cglib需要依赖的架包(下面的链接是我使用的架包)
cglib:http://mvnrepository.com/artifact/cglib/cglib/3.2.6
asm:http://mvnrepository.com/artifact/org.ow2.asm/asm/6.0
特别注意:cglib和asm架包的版本要配套,如果两个jar之间版本差别大,可能会导致各种Exception。
二、正题
公用类:
public interface UserService { String getName(int id); Integer getAge(int id); }
public class UserServiceImpl implements UserService { @Override public String getName(int id) { System.out.println("------getName------"); return "Tom"; } @Override public Integer getAge(int id) { System.out.println("------getAge------"); return 10; } }
1、JDK自带动态代理
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; MyInvocationHandler() { super(); } MyInvocationHandler(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("getName".equals(method.getName())) { System.out.println("++++++before " + method.getName() + "++++++"); Object result = method.invoke(target, args); System.out.println("++++++after " + method.getName() + "++++++"); return result; } else { Object result = method.invoke(target, args); return result; } } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test1 { public static void main(String[] args) { UserService userService = new UserServiceImpl(); InvocationHandler invocationHandler = new MyInvocationHandler(userService); UserService userServiceProxy = (UserService)Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler); System.out.println(userServiceProxy.getName(1)); System.out.println(userServiceProxy.getAge(1)); } }
2、CGLIB自动代理
import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("++++++before " + methodProxy.getSuperName() + "++++++"); System.out.println(method.getName()); Object o1 = methodProxy.invokeSuper(o, args); System.out.println("++++++before " + methodProxy.getSuperName() + "++++++"); return o1; } }
import net.sf.cglib.proxy.Enhancer; public class Test2 { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(cglibProxy); UserService o = (UserService)enhancer.create(); System.out.println(o.getName(1)); System.out.println(o.getAge(1)); } }
三、总结
别人的总结:
dk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。
总的来说,反射机制在生成类的过程中比较高效,
而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。
还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。
自己的总结:动态代理的优点如下:在不修改原接口的情况下,对该接口进行扩展。
留下的疑惑:1、还没有完全理解动态代理的原理。
2、动态代理在什么情况下应用最好?