关于jdk代理和cglib代理
简单的说说两个代理的不同,CGLIB代理可以视为JDK代理的补充,JDK的代理是基于接口来实现的,也就是说使用JDK代理的类必须包含至少一个接口,调用代理的方法时,会不断地找寻接口中与调用方法匹配的值,然后通过反射找到此接口的方法,调用InvocationHandler的invoke方法拦截代理。
再说CGLIB,与JDK不同,CGLIB不要求代理类必有什么接口的,它通过制造一个类,通过继承的方式实现代理类,类似于钩子回调,也就是说CGLIB要求代理的类不能是final调用的方法也不能是final的。通过查看各开源框架,也能够发现使用CGLIB代理,反射,泛型等乱七八糟的方法比较多。
cglib有两种可选方式,继承和引用。第一种是基于继承实现的动态代理,所以可以直接通过super调用target方法,但是这种方式在spring中是不支持的,因为这样的话,这个target对象就不能被spring所管理,所以cglib还是才用类似jdk的方式,通过持有target对象来达到拦截方法的效果。通过CGLIB代理可以很大程度的增强代理方法。如spring中AOP相关的拦截方法,和hibernate中,毕竟hibernate中有大量的缓存机制和ORM工具方法。当然我并没有说JDK代理要比CGLIB好。在框架中二中代理都被大量的使用,并且在spring中如spring AOP中默认是使用JDK代理实现来实现接口,你可以强制使用CGLIB。在使用struts2框架时,你可能碰到过一种莫名奇妙的场景,就是使用ActionAware接口时,调用代理方法报错找不到有关的方法,这很可能是因为Spring关注到你的action实现了某个接口,于是为你使用JDK代理,进而使你调用的方法不被找到。
那么接下来请参照下面两段代码,进一步理解
首先是基础工作,一个接口:
public interface UserService { Boolean addUser(User user); }
实现类
public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper;// 插入用户 用户id用uuid @Override public Boolean addUser(User user) { user.setRole_id(11001); user.setActivecode(UUID.randomUUID().toString().replace("-", "")); user.setUser_id(UUID.randomUUID().toString().replace("-", "")); user.setRegister(new Date()); return true;//此处请无视// TODO } }
这里是代理的实现
package com.dabai.test 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 o, Method method, Object[] args) throws Throwable { if("getName".equals(method.getName())){ System.out.println("start--" + method.getName()); Object result = method.invoke(target, args); System.out.println("end--" + method.getName()); return result; }else{ Object result = method.invoke(target, args); return result; } } }
这里调用
package com.dabai.test.jdk; package com.dabai.mytwo.service; package com.dabai.mytwo.service.impl;
import com.dabai.mytwo.entity.User; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Proxy_Jdk { 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); userServiceProxy.addUser(new User()); } }
接下来是CGLIB代理
package com.dabai.test.cglib; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxy implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("start cg----" + methodProxy.getSuperName()); System.out.println(method.getName()); Object obj = methodProxy.invokeSuper(o, args); System.out.println("end----" + methodProxy.getSuperName() ); return obj; } }
package com.dabai.test.cglib; package com.dabai.mytwo.service; package com.dabai.mytwo.service.impl import net.sf.cglib.proxy.Enhancer; public class Proxy_Cglib { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); //在此处增强代理方法 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(cglibProxy); UserService userService = (UserService)enhancer.create(); userService.addUser(new User()); } }