作者:dolphin叔叔

链接:https://www.jianshu.com/p/fe8...

AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于解决一些具备横切性质的零碎级服务,如事务管理、安全检查、缓存、对象池治理等。

AOP 实现的要害就在于 AOP 框架主动创立的 AOP 代理,AOP 代理则可分为动态代理和动静代理两大类,其中动态代理是指应用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因而也称为编译时加强;而动静代理则在运行时借助于 JDK 动静代理、CGLIB 等在内存中“长期”生成 AOP 动静代理类,因而也被称为运行时加强。

先说说AspectJ

在明天之前,我还认为AspectJ 是Spring的一部分,因为咱们谈到Spring AOP个别都会提到AspectJ。原来AspectJ是一套独立的面向切面编程的解决方案。

上面咱们抛开Spring,单纯的看看AspectJ。

1、AspectJ 装置

下载AspectJ jar包,而后双击装置。装置好的目录构造为:

bin:寄存了 aj、aj5、ajc、ajdoc、ajbrowser 等命令,其中 ajc 命令最罕用,它的作用相似于 javac

doc:寄存了 AspectJ 的应用阐明、参考手册、API 文档等文档

lib:该门路下的 4 个 JAR 文件是 AspectJ 的外围类库

2、AspectJ HelloWorld 实现

业务组件 SayHelloService:

package com.ywsc.fenfenzhong.aspectj.learn;public class SayHelloService {    public void say(){        System.out.print("Hello  AspectJ");    }} 

须要来了,在须要在调用say()办法之后,须要记录日志。那就是通过AspectJ的后置加强吧。

LogAspect 日志记录组件,实现对com.ywsc.fenfenzhong.aspectj.learn.SayHelloService 后置加强:

package com.ywsc.fenfenzhong.aspectj.learn;public aspect LogAspect{    pointcut logPointcut():execution(void SayHelloService.say());    after():logPointcut(){         System.out.println("记录日志 ...");     }}

3、编译SayHelloService

  • 执行命令 ajc -d . SayHelloService.java LogAspect.java
  • 生成 SayHelloService.class
  • 执行命令 java SayHelloService
  • 输入 Hello AspectJ 记录日志

ajc.exe 能够了解为 javac.exe 命令,都用于编译 Java 程序,区别是 ajc.exe 命令可辨认 AspectJ 的语法;咱们能够将 ajc.exe 当成一个增强版的 javac.exe 命令.执行ajc命令后的 SayHelloService.class 文件不是由原来的 SayHelloService.java 文件编译失去的,该 SayHelloService.class 里新增了打印日志的内容——这表明 AspectJ 在编译时“主动”编译失去了一个新类,这个新类加强了原有的 SayHelloService.java 类的性能,因而 AspectJ 通常被称为编译时加强的 AOP 框架。

与 AspectJ 绝对的还有另外一种 AOP 框架,它不须要在编译时对指标类进行加强,而是运行时生成指标类的代理类,该代理类要么与指标类实现雷同的接口,要么是指标类的子类——总之,代理类的实例可作为指标类的实例来应用。一般来说,编译时加强的 AOP 框架在性能上更有劣势——因为运行时动静加强的 AOP 框架须要每次运行时都进行动静加强。

再谈 Spring AOP

Spring AOP也是对指标类加强,生成代理类。然而与AspectJ的最大区别在于---Spring AOP的运行时加强,而AspectJ是编译时加强。

已经认为AspectJ是Spring AOP一部分,是因为Spring AOP应用了AspectJ的Annotation。应用了Aspect来定义切面,应用Pointcut来定义切入点,应用Advice来定义加强解决。尽管应用了Aspect的Annotation,然而并没有应用它的编译器和织入器。其实现原理是JDK 动静代理,在运行时生成代理类。

为了启用 Spring 对 @AspectJ 方面配置的反对,并保障 Spring 容器中的指标 Bean 被一个或多个方面主动加强,必须在 Spring 配置文件中增加如下配置

<aop:aspectj-autoproxy/>

当启动了 @AspectJ 反对后,在 Spring 容器中配置一个带 @Aspect 正文的 Bean,Spring 将会自动识别该 Bean,并将该 Bean 作为方面 Bean 解决。方面Bean与一般 Bean 没有任何区别,一样应用 <bean.../> 元素进行配置,一样反对应用依赖注入来配置属性值。

应用Spring AOP的改写 Hello World的例子。

业务组件 SayHelloService:

package com.ywsc.fenfenzhong.aspectj.learn;import org.springframework.stereotype.Component;@Componentpublic class SayHelloService {    public void say(){        System.out.print("Hello  AspectJ");    }} 

做后置加强的日志解决。

package com.ywsc.fenfenzhong.aspectj.learn;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Aspect@Componentpublic class LogAspect {     @After("execution(* com.ywsc.fenfenzhong.aspectj.learn.SayHelloService.*(..))")     public void log(){         System.out.println("记录日志 ...");     }}
package com.ywsc.fenfenzhong.mongodb;import com.ywsc.fenfenzhong.aspectj.learn.SayHelloService;public class TestCase {    public static void main(String[] args) {        SayHelloService sayHelloService = ApplicationUtil.getContext().getBean(SayHelloService.class);        sayHelloService.say();    }}

输入后果:

Hello  AspectJ记录日志...

总结

AOP 代理 = 原来的业务类+加强解决。

这个生成AOP 代理由 Spring 的 IoC 容器负责生成。也由 IoC 容器负责管理。因而,AOP 代理能够间接应用容器中的其余 Bean 实例作为指标,这种关系可由 IoC 容器的依赖注入提供。回顾Hello World的例子,其中程序员参

与的只有 3 个局部:

  • 定义一般业务组件。
  • 定义切入点,一个切入点可能横切多个业务组件。
  • 定义加强解决,加强解决就是在 AOP 框架为一般业务组件织入的解决动作。

最初说说CGLIB

CGLIB(Code Generation Library)它是一个代码生成类库。它能够在运行时候动静是生成某个类的子类。代理模式为要拜访的指标对象提供了一种路径,当拜访对象时,它引入了一个间接的层。

JDK自从1.3版本开始,就引入了动静代理,并且常常被用来动静地创立代理。JDK的动静代理用起来非常简单,惟一限度便是应用动静代理的对象必须实现一个或多个接口。而CGLIB缺不用有此限度。要想Spring AOP 通过CGLIB生成代理,只须要在Spring 的配置文件引入

<aop:aspectj-autoproxy proxy-target-class="true"/>

CGLIB包的底层是通过应用一个小而快的字节码解决框架ASM(Java字节码操控框架),来转换字节码并生成新的类。因为没有理解过class 文件和字节码,因此也就写不上来了。

兴许学习下来最大的播种便是弄清楚了 AspectJ 和 Spring AOP 在实现上简直无关。

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2021最新版)

2.别在再满屏的 if/ else 了,试试策略模式,真香!!

3.卧槽!Java 中的 xx ≠ null 是什么新语法?

4.Spring Boot 2.5 重磅公布,光明模式太炸了!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!