AOP核心概念
- 连接点(JoinPoint):需要被增强的方法
- 切入点(PointCut):匹配连接点的式子
- 通知(Advice,增强 ):在切入点处执行的方法,分为前置通知、后置通知、环绕通知、异常通知、返回通知
- 通知类:定义通知的类
- 切面(Aspect):描述通知与切入点的对应关系
AOP实现
- 创建一个简单的maven项目,然后在pom.xml文件中导入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.21</version>
</dependency>
- 确定连接点(需要被增强的目标对象的方法)
package org.example.dao;
public interface BookDao {
public void save();
public void insert();
public void delete();
public void update();
}
package org.example.dao.Impl;
import org.example.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
@Override
public void insert() {
System.out.println("book dao insert...");
}
@Override
public void delete() {
System.out.println("book dao delete...");
}
@Override
public void update() {
System.out.println("book dao update...");
}
}
- 定义切面,包括通知和切入点
package org.example;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@Pointcut("execution(void org.example.dao.BookDao.save())")
private void pointCut0() {
}
@Pointcut("execution(* org.example.dao.BookDao.*(..))")
private void pointCut1() {
}
@Before("pointCut0()")
public void beforeAdvice() {
System.out.println("beforeAdvice running...");
}
@After("pointCut0()")
public void afterAdvice() {
System.out.println("afterAdvice running...");
}
@Around("pointCut1()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("before...");
try {
proceedingJoinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
System.out.println("after...");
}
}
这里定义了两个切入点pointCut0和pointCut1,execution()
括号里的就是连接点位置,也就是需要被增强的业务逻辑方法。
加上@Aspect
代表这是一个切面类,@Component
把切面类注入到Spring的容器中作为bean对象进行管理。
pointCut0的连接点(目标方法)是void org.example.dao.BookDao.save()
,pointCut1的目标方法是* org.example.dao.BookDao.*(..))
,代表BookDao中的所有方法。
- 开启注解格式AOP功能
package org.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("org.example")
@EnableAspectJAutoProxy
public class SpringConfig {
}
有了@EnableAspectJAutoProxy
这个注解才能支持@Aspect等相关的一系列AOP注解的功能
6. 运行程序
package org.example;
import org.example.config.SpringConfig;
import org.example.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = (ApplicationContext) new AnnotationConfigApplicationContext(SpringConfig.class);
// BookDao bookDao = (BookDao) applicationContext.getBean("bookDaoImpl");
BookDao bookDao = applicationContext.getBean(BookDao.class);
bookDao.save();
System.out.println("-----------------------------");
bookDao.insert();
}
}
测试结果:
注意
@Aspect 类注解,放在切面类上方
@Pointcut 方法注解,放在切入点方法定义的上方
@EnableAspectJAutoProxy 配置类注解,放在配置类定义上方,开启注解格式AOP功能
@Before、@After、@Around、@AfterRunning、@AfterThrowing