1 AspectJ的CTW介绍
AOP(Aspect Oriented Programming)即面向切面编程,可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AspectJ是一个面向方面的编程(AOP)具体实现框架,它扩展了Java语言,允许程序员定义切面(aspects),这些切面可以改变程序的结构和行为。
AspectJ不但可以通过预编译方式(CTW)和运行期动态代理的方式织入切面,还可以在载入(Load Time Weaving, LTW)时织入,可以实现横切关注点的模块化。其中,编译时织入(Compile-Time Weaving,CTW)是AspectJ实现AOP功能的一种重要方式。
1.1 AspectJ和AOP
-
AspectJ简介:AspectJ是一个基于Java的AOP框架,由Eclipse Foundation维护。它允许开发者定义切面,这些切面包含了影响其他类和方法行为的代码。
-
面向方面的编程(AOP):AOP是一种编程范式,它允许将横切关注点(如日志、事务管理等)从业务逻辑中分离出来,提高了代码的可重用性和可维护性。
1.2 编译时织入(CTW)
-
CTW定义:在AspectJ中,CTW是指在Java源代码编译成字节码时,将切面逻辑插入到目标代码中的过程。
-
CTW的优势:
- 性能:由于切面是在编译时加入,运行时性能较好,因为没有动态代理和反射的开销。
- 类型安全:编译时织入可以在编译阶段检测到某些类型的错误。
-
CTW的过程:
- 开发者编写包含切面定义的AspectJ源代码。
- 使用AspectJ编译器(ajc)编译源代码,编译器将切面逻辑织入到目标类的字节码中。
- 生成的字节码包含了原始的业务逻辑和切面逻辑。
1.3 切面的定义和使用
-
切面(Aspect):一个切面是一个模块化的横切关注点实现,包含切点(pointcuts)和通知(advice)。
-
切点(Pointcut):定义了切面应该在何处应用的规则。
-
通知(Advice):织入到目标代码中的实际代码片段。它们在切点指定的位置执行,可以是前置(before)、后置(after)或环绕(around)通知。
1.4 AspectJ的集成
-
与Java的集成:AspectJ可以与普通的Java代码无缝集成。使用AspectJ不需要对现有的Java代码做出重大修改。
-
构建工具集成:AspectJ可以通过Maven、Gradle等构建工具进行集成。这些工具提供了插件来支持AspectJ编译过程。
1.5 应用场景
-
日志和监控:通过AspectJ,可以在不修改核心业务逻辑的情况下,为应用程序添加日志和监控功能。
-
事务管理:AspectJ可以用于管理数据库事务,确保数据的一致性和完整性。
-
安全性:可以使用AspectJ来实现方法级别的安全性检查。
-
错误处理:利用AspectJ进行统一的异常处理和错误记录。
1.6 注意事项
-
复杂性:AspectJ的学习曲线相对陡峭,需要时间来理解AOP和AspectJ的概念。
-
调试难度:由于代码的某些部分是在编译时添加的,因此可能会增加调试的难度。
-
侵入性:尽管AspectJ提高了代码的模块化,但它的使用在某种程度上是侵入性的。
2 AspectJ的CTW实现
2.1 pom配置maven插件:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.2 增加pom依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
2.3 编写被注入的sevice类
public interface SampleService {
public String getName(String name);
}
public class SampleServiceImpl implements SampleService {
@Override
public String getName(String name) {
return name;
}
}
2.4 编写切面类
@Aspect
public class SampleAspect {
/**
* 切入点:SampleService继承树中所有方法。
*/
@Pointcut("execution(* com.li.service.impl..*(..))")
public void methodePointCut(){
}
@Before("methodePointCut()")
public void monitor(JoinPoint joinPoint) throws Throwable{
System.out.println(joinPoint.getStaticPart());
}
@After("methodePointCut()")
public void monitor2(JoinPoint joinPoint) throws Throwable{
System.out.println(joinPoint.getStaticPart());
}
}
2.5 编写测试用例
public class SampleTest {
@Test
public void testAspect(){
SampleService sampleService = new SampleServiceImpl();
System.out.println(sampleService.getName("aaa"));
}
}
2.6 运行测试
execution(String com.li.service.impl.SampleServiceImpl.getName(String))
execution(String com.li.service.impl.SampleServiceImpl.getName(String))
aaa
2.7 切面单独项目提供
切面所在的pom配置:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
被切入的项目引用切面项目
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<aspectLibraries>
<aspectLibrary>
<groupId>com.li</groupId>
<artifactId>aspectJ2</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>