一、需求背景
面向切面编程的简单使用,对特定controller下面的方法进行切面编程,以此来熟悉切面编程、环绕通知、切点的使用
二、实现方案
定义切面
写测试类
改造切面、改造切点
三、编码实现
3.1 项目结构
3.2 pom添加Aop依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3.3 添加切面
这里使用环绕通知
package com.saferycom.aop1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.time.Duration;
/**
* @author LH
*/
@Aspect
@Component
public class Aop1Aspect {
private static final Log logger = LogFactory.getLog(Aop1Aspect.class);
@Around("execution(public void com.saferycom.aop1.AopTestController.test1*(..))")
public void importExcel(ProceedingJoinPoint joinPoint) {
long startTime = System.nanoTime();
logger.info("环绕通知开始:" + joinPoint.getSignature().getName());
try {
joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
Duration time = Duration.ofNanos(System.nanoTime() - startTime);
logger.info("环绕通知结束,消耗了:" + time.getSeconds() + "s");
}
}
}
3.4 接口测试
package com.saferycom.aop1;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author LH
*/
@RestController
public class AopTestController {
@RequestMapping("/test1")
public void test1() {
System.out.println("test1 = " + "test1");
}
@RequestMapping("/test12")
public void test12() {
System.out.println("test12 = " + "test12");
}
}
3.5 启动服务,请求接口测试
查看执行日志
再执行test1接口
在查看日志
发现test1接口和test12接口都能走到切面逻辑里去
我们再来看下环绕通知的切点的写法,指定特定的类下的特定方法(模糊匹配),匹配到的接口方法执行切面逻辑。
@Around("execution(public void com.saferycom.aop1.AopTestController.test1*(..))")
3.6 改造环绕通知的切点
package com.saferycom.aop1;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.time.Duration;
/**
* @author LH
*/
@Aspect
@Component
public class Aop1Aspect {
private static final Log logger = LogFactory.getLog(Aop1Aspect.class);
/**
* 配置切入点,该方法无方法体,主要为了方便同类中其他方法使用此处配置的切入点
*/
@Pointcut("execution(public void com.saferycom.aop1.AopTestController.test1*(..))")
public void pointcut() {
}
@Around("pointcut()")
public void importExcel(ProceedingJoinPoint joinPoint) {
long startTime = System.nanoTime();
logger.info("环绕通知开始:" + joinPoint.getSignature().getName());
try {
joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
Duration time = Duration.ofNanos(System.nanoTime() - startTime);
logger.info("环绕通知结束,消耗了:" + time.getSeconds() + "s");
}
}
}
3.7 启动服务测试验证
改造切点的写法,切面仍然生效。
四、总结
切面的简单使用,实现面向切面编程,注意切点的写法,可以指定特定类下的特定方法去执行切面逻辑,支持模糊匹配。
想让你的代码变得优雅,切面、切点、环绕通知等AOP知识,快点学起来吧。