AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构
作用:在不惊动原始设计的基础上为其进行功能增强
Spring理念:无入侵式/无侵入式
1、导入aop相关坐标
<properties>
<spring.version>5.2.10.RELEASEspring.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.7version>
dependency>
2、定义dao接口与实现类
public interface BookDao {
public void save();
public void update();
}
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println(System.currentTimeMillis());
System.out.println("book dao save ...");
}
@Override
public void update() {
System.out.println("book dao update ...");
}
}
3、定义通知类,制作通知
public class MyAdvice {
public void method(){
System.out.println(System.currentTimeMillis());
}
}
4、定义切入点
//说明:切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑,如:pt
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
}
5、绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置
6、定义通知类受Spring容器管理,并定义当前类为切面类
@Component //容器管理
@Aspect //切面类
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
7、开启Spring对AOP注解驱动支持
@Configuration
@ComponentScan("com.liming")
@EnableAspectJAutoProxy //开启Spring对AOP注解驱动支持
public class SpringConfig {
}
目标对象
)的代理
对象切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式
描述方式一:执行com.liming.dao包下的BookDao接口
中的无参update方法
@Pointcut("execution(void com.liming.dao.BookDao.update())")
描述方式二:执行com.liming.dao.impl包下的BookDaoImpl实现类
中的无参update方法
@Pointcut("execution(void com.liming.dao.impl.BookDaoImpl.update())")
5.1、切入点表达式的标准格式
例如:execution(public User com.liming.service.UserService.findById(int))
execution
表示执行到指定切入点public,private等
,可以省略5.2、通配符描述切入点
*
:单个独立的任意符号,可以独立出现,也可以作为前缀或后缀的匹配符出现(必须有)//匹配com.liming包下的任意包中的UserService接口中所有find开头的带有一个参数的方法
@Pointcut("execution(public * com.liming.*.UserService.find*(*))")
..
:多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写(可有可无)//匹配com包下的任意包中的UerService接口中所有名称为findById的方法
@Pointcut("execution(public User com..UserService.findById(..))")
+
:专用于匹配子类类型//匹配项目中所有业务层实现类的所有方法
@Pointcut("execution(* *..*Service+.*(..))")
5.3、书写技巧
@Before
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行
相关属性:value(默认)
:切入点方法名,格式为类名.方法名()
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
@Before("MyAdvice.pt()")
//@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
@After
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行
相关属性:value(默认)
:切入点方法名,格式为类名.方法名()
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
//@After("pt()")
@After("MyAdvice.pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
@Around(重点,常用)
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
//@Around("pt()")
@Around("MyAdvice.pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice ...");
Object res = pjp.proceed();
System.out.println("around after advice ...");
return res;
}
}
@AfterReturning(了解)
作用:把当前方法看成是后置通知
相关属性:value(默认)
:切入点方法名,格式为类名.方法名()
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
@AfterReturning("pt()")
public void method(){
System.out.println("AfterReturning ...");
}
}
@AfterThrowing(了解)
作用:把当前方法看成是异常通知
相关属性:value(默认)
:切入点方法名,格式为类名.方法名()
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.liming.dao.BookDao.update())")
private void pt(){}
@AfterThrowing("pt()")
public void method(){
System.out.println("AfterReturning ...");
}
}
@Before("pt()")
public void before(JoinPoint jp){
Object[] args = jp.getArgs();
System.out.println(Arrays.toString(args));
}
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
System.out.println(Arrays.toString(args));
Object res = pjp.proceed();
return res;
}
@AfterReturning(value = "pt()",returning = "ret")
public void afterReturning(String ret){
System.out.println("afterReturning advice ..."+ret);
}
@Around("MyAdvice.pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object res = pjp.proceed();
return res;
}