基于注解的Spring AOP示例

时间:2023-02-25 22:34:32


基于注解的Spring AOP示例

在XML配置文件中开启 @AspectJ 支持

要使用Spring的AOP,首先要在 applicationContext.xml 配置文件中添加如下内容:

<!-- 启动@Aspectj -->
<aop:aspectj-autoproxy/>

声明切面及切入点

在Spring中, 切面 就是使用 @Aspect 注解的类。而 切入点 则由两部分组成:方法签名和切入点表达式。下面的切面中声明了三种切入点。

@Aspect
public class SampleAspect {
// 匹配所有的公共方法
@Pointcut("execution(public * *(..))")
public void publicMethod() {
} // 匹配所有在com.app.bean包中的方法
@Pointcut("within(com.app.bean.*)")
public void inPackage() {
} // 匹配所有带有CustomAnnotation注解的方法
@Pointcut("@annotation(com.app.annotation.CustomAnnotation)")
public void withAnnotation() {
}
}

其中第三个切入点使用了自定义的注解类 CustomAnnotation

public @interface CustomAnnotation {}

声明通知

接下来要声明的是 通知 ,通知与切面的结构基本一致。不同的是通知使用 @Before@Around 等注解同切面中的切入点一起确定执行的方法。下面的通知示例中声明了三种通知方式,其中 @Around 类型的通知需要一个 ProceedingJoinPoint 类的实例作为参数。

@Aspect
public class SampleAdvice {
@Before("com.app.aspect.SampleAspect.publicMethod()")
public void advicePublicMethod() {
System.out.println("before advice matched with public methods");
} @After("com.app.aspect.SampleAspect.inPackage()")
public void adviceInBean() {
System.out.println("after advice matched methods in package");
} @Around("com.app.aspect.SampleAspect.withAnnotation()")
public Object adviceWithAnnotation(ProceedingJoinPoint jp) throws Throwable {
System.out.println("around advice before proceed");
Object ret = jp.proceed();
System.out.print("around advice after proceed");
return ret;
}
}

之前声明的切面和通知都需要在配置文件中声明一下,最终的 applicationContext.xml 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.app"/>
<!-- 启动@Aspectj -->
<aop:aspectj-autoproxy/> <!-- 切面 -->
<bean id="sampleAspect" class="com.app.aspect.SampleAspect"/>
<!-- 通知 -->
<bean id="sampleAdvice" class="com.app.aspect.SampleAdvice"/>
</beans>

测试

现在可以写一个普通的类来测试我们的代码了,在 com.app.bean 包中创建文件:

@Component
public class CommonService {
public void service() {
System.out.println("service method");
} public void transfer() {
System.out.println("transfer method");
} @CustomAnnotation
public void annotated() {
System.out.println("method with annotation");
}
}

测试代码如下:

public class Test {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
CommonService service = context.getBean("commonService", CommonService.class);
service.service();
service.transfer();
service.annotated();
}
}

结语

本文中的示例代码是基于Maven项目的,最终代码的包结构如下:

基于注解的Spring AOP示例

pom.xml 文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.eagle</groupId>
<artifactId>springDemo</artifactId>
<version>1.0-SNAPSHOT</version> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>