CGLIB相比于JDK动态代理更加强大,JDK动态代理虽然简单易用,但是其有一个致命缺陷是,只能对接口进行代理。如果要代理的类为一个普通类、没有接口,那么Java动态代理就没法使用了。

  1. import net.sf.cglib.proxy.Enhancer;
  2. import net.sf.cglib.proxy.MethodInterceptor;
  3. import net.sf.cglib.proxy.MethodProxy;
  4. import java.lang.reflect.Method;
  5. /**
  6. * @author wjj
  7. * @date 2021/3/1 14:28
  8. */
  9. public class CglibDemo {
  10. public void test() {
  11. System.out.println("hello world");
  12. }
  13. public static void main(String[] args) {
  14. Enhancer enhancer = new Enhancer();
  15. enhancer.setSuperclass(CglibDemo.class);
  16. enhancer.setCallback(new MethodInterceptor() {
  17. @Override
  18. public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  19. System.out.println("before method run...");
  20. Object result = proxy.invokeSuper(obj, args);
  21. System.out.println("after method run...");
  22. return result;
  23. }
  24. });
  25. CglibDemo sample = (CglibDemo) enhancer.create();
  26. sample.test();
  27. }
  28. }

Enhancer

Enhancer可能是CGLIB中最常用的一个类,和Java1.3动态代理中引入的Proxy类差不多(如果对Proxy不懂,可以参考这里)。和Proxy不同的是,Enhancer既能够代理普通的class,也能够代理接口。Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。Enhancer不能够拦截final方法,例如Object.getClass()方法,这是由于Java final方法语义决定的。基于同样的道理,Enhancer也不能对fianl类进行代理操作。这也是Hibernate为什么不能持久化final class的原因。

Enhancer.setSuperclass用来设置父类型

Enhancer.create(Object…)方法是用来创建增强对象的,其提供了很多不同参数的方法用来匹配被增强类的不同构造方法。

MethodInterceptor

CallbackFilter

ImmutableBean

通过名字就可以知道,不可变的Bean。ImmutableBean允许创建一个原来对象的包装类,这个包装类是不可变的,任何改变底层对象的包装类操作都会抛出IllegalStateException

CGLIB和Java动态代理的区别

  1. Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);CGLIB能够代理普通类;
  2. Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效