JDK 的动态代理:针对实现了接口的类产生代理。
CGlib 的动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术 生成当前类的子类对象
JDK动态代理实现
1. 创建接口和对应实现类
1 public interface UserService { 2 void login(); 3 void loginOut(); 4 }
1 //实现类 2 public class UserServiceImpl implements UserService { 3 public void login() { 4 System.out.println("login方法触发"); 5 } 6 public void loginOut() { 7 System.out.println("loginOut方法触发"); 8 } 9 }
2.创建动态代理类
1 public class PerformHandler implements InvocationHandler { 2 private Object target; //目标对象 3 public PerformHandler(Object target){ 4 this.target = target; 5 } 6 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 7 //本方法中的其他输出输入增强 8 System.out.println("方法触发了"); 9 //执行被代理类 原方法 10 Object invoke = method.invoke(target, args); 11 System.out.println("执行完毕了"); 12 return invoke; 13 } 14 }
测试
1 @Test 2 public void test1(){ 3 //测试JDK动态代理技术 4 UserService userService = new UserServiceImpl(); 5 PerformHandler performHandler = new PerformHandler(userService); 6 userService = (UserService) 7 Proxy.newProxyInstance(userService.getClass().getClassLoader(), 8 userService.getClass().getInterfaces(), 9 performHandler 10 ); 11 userService.login(); 12 }
测试结果: 在调用接口方法的前后都会添加代理类的方法!
CGlib实现代理
使用JDK创建代理有一个限制,它只能为接口创建代理实例.这一点可以从Proxy的接口方法
newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚
第二个入参 interfaces就是需要代理实例实现的接口列表.
对于没有通过接口定义业务方法的类,如何动态创建代理实例呢? JDK动态代理技术显然已经黔驴技穷,CGLib
作为一个替代者,填补了这一空缺.
GCLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用
并顺势织入横切逻辑.
1. 创建创建CGLib代理器
1 public class CglibProxy implements MethodInterceptor { 2 3 private Enhancer enhancer = new Enhancer(); 4 //设置被代理对象 5 public Object getProxy(Class clazz){ 6 enhancer.setSuperclass(clazz); 7 enhancer.setCallback(this); 8 return enhancer.create(); 9 } 10 @Override 11 public Object intercept(Object obj, Method method, 12 Object[] objects, 13 MethodProxy methodProxy) throws Throwable { 14 System.out.println("CGLig代理之前之前"); 15 Object invoke = methodProxy.invokeSuper(obj,objects); 16 System.out.println("CGLig代理之前之后"); 17 return invoke; 18 } 19 20 }
测试
1 @Test 2 public void test2(){ 3 //TODO CGlib实现 4 CglibProxy cglibProxy = new CglibProxy(); 5 UserServiceImpl userService= (UserServiceImpl) 6 cglibProxy.getProxy(UserServiceImpl.class); 7 userService.login(); 8 }
结果: