aop 入门
- 导入相关坐标
- 在业务层抽取通用代码
- 把通知加入 spring 容器管理
- 在配置文件中配置 aop 的配置
aop 案例
application.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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启 aop 注解驱动 -->
<aop:aspectj-autoproxy/>
<!-- 开启 spring 注解驱动-->
<context:component-scan base-package="com.asaawan"/>
<!-- 抽取的功能要配置成 spring 控制的资源-->
<bean id="accountAdvice" class="com.asaawan.aop.AccountAdvice"/>
<!-- aop 配置 -->
<aop:config>
<!--配置公共切入点-->
<aop:pointcut id="pc" expression="execution(* com.asaawan.service.*Service.*(..))"/>
<!--配置切面-->
<aop:aspect id="aspect" ref="accountAdvice">
<!--配置局部切入点-->
<!--<aop:pointcut id="pt" expression="execution(* *(..))"/>-->
<!--直接配置切入点-->
<!--<aop:before method="runtimeAround" pointcut="execution(* *(..))"/>-->
<!--通知与切入点之间的关系-->
<aop:around method="runtimeAround" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
AccountAspect 配置
public class AccountAspect {
public Object runtimeAround(ProceedingJoinPoint pjp) throws Throwable {
//获取执行签名信息
Signature signature = pjp.getSignature();
//通过签名获取执行类型(接口名)
String className = signature.getDeclaringTypeName();
//通过签名获取执行操作名称(方法名)
String methodName = signature.getName();
//执行时长累计值
long sum = 0L;
Object proceed = null;
for (int i = 0; i < 10000; i++) {
//获取操作前系统时间 startTime
long startTime = System.currentTimeMillis();
//原始操作调用
proceed = pjp.proceed(pjp.getArgs());
//获取操作后系统时间 endTime
long endTime = System.currentTimeMillis();
sum += endTime - startTime;
}
//打印信息
System.out.println(className + ":" + methodName + " (万次)run:" + sum + "ms");
//返回结果
return proceed;
}
}
AccountAspect 注解
@Component
@Aspect
public class AccountAspect {
@Pointcut("execution(* com.asaawan.service.*Service.*(..))")
public void pointcut(){}
@Around("pointcut()")
public Object runtimeAround(ProceedingJoinPoint pjp) throws Throwable {
//获取执行签名信息
Signature signature = pjp.getSignature();
//通过签名获取执行类型(接口名)
String className = signature.getDeclaringTypeName();
//通过签名获取执行操作名称(方法名)
String methodName = signature.getName();
//执行时长累计值
long sum = 0L;
Object proceed = null;
for (int i = 0; i < 10000; i++) {
//获取操作前系统时间 startTime
long startTime = System.currentTimeMillis();
//原始操作调用
proceed = pjp.proceed(pjp.getArgs());
//获取操作后系统时间 endTime
long endTime = System.currentTimeMillis();
sum += endTime - startTime;
}
//打印信息
System.out.println(className + ":" + methodName + " (万次)run:" + sum + "ms");
return proceed;
}
}
常见通知类型注解
- @Before
- @After
- @AfterReturning
- @AfterThrowing
- @Around