Spring AOP(面向切面编程)是一种编程范例,它使开发人员可以将横切关注点(跨越整个应用程序的重复代码)从实现他们的业务逻辑代码中分离开来。这样,开发人员可以使他们的代码更容易理解、更易于维护,以及更易于重用。
下面是 Spring AOP 的主要功能:
-
提供声明式企业服务: AOP 可以在不修改业务代码的情况下,将企业处理的规则应用到业务组件。
-
使应用程序更易于维护:由于关注点被分离出来,所以修改和添加新的行为变得容易。这意味着,如果我们要更改日志细节或安全规则,我们只需修改一小部分代码。
-
使应用程序更易于测试:通过将组件分解为多个独立的关注点,使用单元测试进行测试变得更容易。
在 Spring AOP 中,面向切面编程的主要范型由通知(advices)、切入点(join points)和切面(aspects)组成。
-
通知(Advice):这是实际要执行的代码片段。它们是在应用程序代码的某个特定点执行的行为。
-
切入点(Join points):这是在应用程序中的哪个特定点,一个通知应该被织入。
-
切面(Aspect):这是切入点和通知的结合。它基本上是一个代码模块,代表了应用程序的一个横切关注点。
以下是实现通用化切面的方法步骤:
第一步:引入maven相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.20.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.1.1</version>
</dependency>
第二步: 定义 AOP Annotation:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Inherited
@Documented
public @interface Timing {
String key();
}
第三步:定义AOP组件
@Component
@Aspect
public class TimingAspect {
@Around("@annotation(timing)")
public Object timeAdvice(ProceedingJoinPoint pjp, Timing timing) throws Throwable {
long startTime = System.currentTimeMillis();
Object retVal = pjp.proceed();
long totalTime = System.currentTimeMillis() - startTime;
System.out.println("Execution of " + timing.key() + " took " + totalTime + " ms");
return retVal;
}
}
第四步:引入maven build插件
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<Xset>
<overWeaving>true</overWeaving>
</Xset>
<verbose>true</verbose>
<showWeaveInfo>true</showWeaveInfo>
<source>11</source>
<target>11</target>
<complianceLevel>11</complianceLevel>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<verbose>false</verbose>
<Xlint>ignore</Xlint>
<outxml>true</outxml>
<forceAjcCompile>true</forceAjcCompile>
<sources/>
<weaveDirectories>
<weaveDirectory>${project.build.directory}/classes</weaveDirectory>
</weaveDirectories>
</configuration>
<executions>
<execution>
<!-- <phase>process-classes</phase>-->
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.20.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.20.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.1.1</version>
</dependency>
</dependencies>
</plugin>
第五步: 使用 Timing 注解:
现在,你可以在任何你想要跟踪执行时间的方法上添加 @Timing
注解。例如:
@Service
public class SomeService {
@Timing(key = "test")
public void someMethod() {
// ... your code here ...
}
}
如果你需要更复杂的逻辑(例如,只在方法耗时超过特定阈值时记录日志),你可以轻松地在 timeAdvice
方法中实现。
同样的方法,可以对函数方法实现,重试,限流等各种操作.