关于java:Spring-AOPAspectJCGLIB-都是什么鬼它们有什么关系

33次阅读

共计 3754 个字符,预计需要花费 10 分钟才能阅读完成。

作者: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;
@Component
public 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
@Component
public 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 开发手册(嵩山版)》最新公布,速速下载!

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

正文完
 0