参考博客:
http://blog.youkuaiyun.com/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、动态代理在什么情况下应用最好?