Spring-30-AOP快速入门案例
1、aop 相关依赖
aop 相关的有两个依赖,spring-aop 和 aspectjweaver
由于 spring-context 依赖于 spring-aop,所以导入 spring-context 就包含了 spring-aop,只需再导入 aspectjweaver 即可
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
</dependency>
2、需求 (aop 实现的功能)
现有下面一个 dao 类,类中有 save() 和 update() 两个方法,调用 save() 方法会打印耗费的时间,调用 update() 则不会
现在实现不对原来代码进行修改(无侵入式),并让 update() 方法也能打印耗时,使其在功能上与 save() 相同
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
long beginTime = System.currentTimeMillis();
System.out.println("book dao save..."); // dao 操作,用打印一句话代替
long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - beginTime) + " ms");
}
@Override
public void update() {
System.out.println("book dao update...");
}
}
3、通知 (Advice) 类
(1) 定义切入点
切入点依托于一个无意义的成员方法(无返回值,无参,无内容),在此方法上注解 @Pointcut,注解内写明作为切入点的函数
Pointcut 注解形式:
@Pointcut(“execution(返回类型 类全限定名.方法名(形参类型))”)
(2) 绑定切入点,并指定通知(advice)添加到原始连接点的执行位置
将下面两个注解添加到相应的方法上,分别表明执行位置在切入点方法之前与之后,pt() 为切入点定义时所依托的方法名
@Before(“pt()”)
@After(“pt()”)
(事实上用 @Around 更为合适,但此次用上面两个做演示)
(3) 在类上添加 @Component 和 @Aspect 注解,使其可以被 Spring 扫描到并表明这是一个切面
@Component
@Aspect
public class MyAdvice {
private long beginTime;
// 定义切入点
@Pointcut("execution(void com.xxx.dao.BookDao.update())")
private void pt(){}; // 切入点依托方法
@Before("pt()") // 绑定,在切入点前执行的方法
public void beginMethod() {
beginTime = System.currentTimeMillis();
}
@After("pt()") // 绑定,在切入点后执行的方法
public void endMethod() {
long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - beginTime) + " ms");
}
}
4、SpringConfig 类
除了常规的 @Configuration 和 @ComponentScan 注解外,还要添加 @EnableAspectJAutoProxy 注解(启用 AspectJ 自动代理)
@Configuration
@ComponentScan("com.xxx")
@EnableAspectJAutoProxy
public class SpringConfig {
}