一、Cglib动态代理
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能。而且,它的运行速度要远远快于JDK的Proxy动态代理。
1.Cglib核心类
- net.sf.cglib.proxy.Enhancer //主要的增强类
- net.sf.cglib.proxy.MethodInterceptor //主要的方法拦截类,它是Callback接口的子接口,需要用户实现。这个接口只定义了一个方法
- public Object intercept(Object object, java.lang.reflect.Method method,Object[] args, MethodProxy proxy) throws Throwable;//第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数
- net.sf.cglib.proxy.MethodProxy //JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用
2.上篇PersonSerivice的Cglib代理实现(实现的前提是导入了Spring框架下的jar包)
被代理的类:
public class PersonServiceImp { private String name; private Integer age; public PersonServiceImp() { super(); } public PersonServiceImp(String name, Integer age) { super(); this.name = name; this.age = age; } public String getName() { System.out.println("---------getName------"); return name; } public Integer getAge() { System.out.println("---------getAge--------"); return age; } public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } }
代理的类:
import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if ("getName".equals(method.getName())) { System.out.println("*********before*******"); System.out.println("method:" + method); Object res = methodProxy.invokeSuper(obj, args); System.out.println("*********after********"); return res; } else { Object res = methodProxy.invokeSuper(obj, args); return res; } } }
测试:
import org.springframework.cglib.proxy.Enhancer; public class CglibProxyTest { public static void main(String[] args) { PersonServiceImp person = new PersonServiceImp(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(PersonServiceImp.class); enhancer.setCallback(new MyMethodInterceptor()); person = (PersonServiceImp) enhancer.create(); person.setName("jack"); person.setAge(20); System.out.println(person.getClass().getName()); System.out.println(person.getName()); System.out.println(person.getAge()); } }
输出结果:
二、Jdk动态道理和Cglib动态代理的区别
1.JDK动态代理是利用反射机制实现的,在调用具体方法前调用InvokeHandler来处理。而Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
2.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,也可以强制使用CGLIB实现AOP;如果目标对象没有实现接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换。
3.JDK动态代理只能对实现了接口的类生成代理,而不能针对类;CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法, 因为是继承,所以该类或方法不要声明成final。
4.使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。