Spring AOP 使用切面
🏷️ Spring
1. Maven 配置文件 ( pom.xml ) 中添加依赖
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">
<parent>
<groupId>liujiajia-me</groupId>
<artifactId>liujiajia-me-spring-learn</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liujiajia-me-spring-learn-aop</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2. 创建一个演奏接口(定义一个切点 perform
)
java
package concert;
/**
* Created by liujiajia on 2017/3/28.
*/
public interface Performance {
public void perform();
}
3. 创建实现类
java
package concert;
import org.springframework.stereotype.Component;
/**
* Created by liujiajia on 2017/3/28.
*/
@Component
public class MusicConcert implements Performance {
public void perform() {
System.out.println("Playing music");
}
}
4. 定义切面
使用 @Aspect
注解标记为切面。
使用 @After
@AfterReturning
@AfterThrowing
@Around
@Before
注解来声明通知方法,参数为切点表达式。可以使用 @Pointcut
注解来声明频繁使用的切点表达式。
java
package concert;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* Created by liujiajia on 2017/3/28.
*/
@Aspect
@Component
public class Audience {
// 表演之前
@Before("execution(** concert.Performance.perform(..))")
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
// 表演之前
@Before("execution(** concert.Performance.perform(..))")
public void takeSeats() {
System.out.println("Taking seats");
}
// 表演之后
@AfterReturning("execution(** concert.Performance.perform(..))")
public void applause() {
System.out.println("CLAP CLAP CLAP!!!");
}
// 表演失败之后
@AfterThrowing("execution(** concert.Performance.perform(..))")
public void demandRefund() {
System.out.println("Demanding a refund");
}
}
5. 在 JavaConfig 中使用 @EnableAspectJAutoProxy
注解启用 AspectJ
注解的自动代理
java
package concert;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* Created by liujiajia on 2017/3/28.
*/
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {
}
6. 创建测试类
java
package concert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
/**
* Created by liujiajia on 2017/3/28.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConcertConfig.class)
public class AudienceTest {
@Autowired
private Performance performance;
@Test
public void performance() {
performance.perform();
}
}
7. 测试结果
Silencing cell phones
Taking seats
Playing music
CLAP CLAP CLAP!!!
8. 使用 @Pointcut
标注声明频繁使用的切点表达式
java
package concert;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* Created by liujiajia on 2017/3/28.
*/
@Aspect
@Component
public class Audience {
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
// 表演之前
@Before("performance()")
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
// 表演之前
@Before("performance()")
public void takeSeats() {
System.out.println("Taking seats");
}
// 表演之后
@AfterReturning("performance()")
public void applause() {
System.out.println("CLAP CLAP CLAP!!!");
}
// 表演失败之后
@AfterThrowing("performance()")
public void demandRefund() {
System.out.println("Demanding a refund");
}
}
9. 使用 @Around
环绕通知
java
package concert;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* Created by liujiajia on 2017/3/28.
*/
@Aspect
@Component
public class Audience {
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
@Around("performance()")
public void watchPerformance(ProceedingJoinPoint jp) {
try {
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP!!!");
} catch (Throwable e) {
System.out.println("Demanding a refund");
}
}
}