Aop 原理

概述

  • 利用代理模式实现 aop,从具体的实现细节可以划分为静态代理,动态代理,cglib 生成子类的代理
  • 使用预编译的方法进行静态代理
  • 使用使用自定义加载器的方法进行动态代理。

后两种代理都可以代理更多的内容,比如构造函数,静态方法,静态块,私有方法等。

静态代理

AspectJ 属于静态 Aop,是在编译的时候进行增强,会在编译的时候将 aop 逻辑织入到代码中,需要有专门的编译器和织入器。 优点:被织入的类不受影响 缺点:不够灵活

JDK 动态代理

在运行期,目标类加载后,为接口动态生成代理类,将切面织入到代理类中。java 从 1.3 引入动态代理。实现原理是为被代理的业务接口生成代理类,将 aop 逻辑写入到代理类中,在运行时动态织入 aop.使用反射执行织入的逻辑。主要依赖的是 java.lang.reflect 包下的 InvocationHandler 和 proxy 类。

  • 优化:java 标准库的原生支持,使用简单,无需引用额外的包,相对静态 aop 更为简单。
  • 缺点:带代理的类必须实现接口,灵活性受到一定的限制,使用反射会影响性能。

CGLIB 代理

cglib 代理:是动态代码字节生成的实现,他封装字节码生成工具 Asm,原理是在运行期间目标字节加载后,生成目标类的子类,将切面逻辑加入到子类中,所以 Cglib 实现 aop 不需要基于接口。CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。 CGLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理

  • 优点:没有接口也可以织入,灵活性高
  • 缺点:扩展类的实现方法为 final 时,则无法进行织入。

参考