AOP相关的重要概念
- Aspect(切面)
- Aspect声明类似于java的类声明,在Aspect中包含一些Pointcut和相应的Advice
- Joint point(连接点)
- 表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等,它自身还可以嵌套其他的joint point
- Pointcut(切点)
- 表示一组joint point,这些连接点或是通过逻辑关系组合起来,或是通过统配、正则表达式等方式集中起来,它定义了相应的Advice将要发生的地方。
- Target(目标对象)
- 织入Advice的目标对象
- Weaving(织入)
- 定义一个config类(配置类),相当于一个applicationContext.xml文件,用于配置注解扫描包等
- 定义切面类,增强方法,实现AOP
- 定义目标类和目标方法
- 测试
AspectJ是一个专门用于实现Spring的AOP的框架,比Spring自带的AOP工具更强大、更好用,所以普遍使用AspectJ。先加入依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
package com.quail.config;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @author quail
* @date 2021/3/19 18:18
* @TODO 定义配置类,用于告诉spring我们使用注解方式
*/
@Configurable//表示这个是一个配置类
@ComponentScan("com.quail")//表示扫描包
@EnableAspectJAutoProxy//开启Aspectj的自动代理
public class AppConfig {
}
package com.quail.aspects;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author quail
* @date 2021/3/19 18:23
* @TODO 用注解方式实现切面
*/
@Component//将该类交给spring管理
@Aspect//表示这是一个切面类
public class AspectsAnnotation {
// 定义切点描述,这个方法的名字就是引用这个切点
@Pointcut("execution(* com.quail.dao..*.*(..))")
public void daoPointCut(){}
//前置通知
@Before("args(name) && daoPointCut()")//值是切点描述
public void before(JoinPoint joinPoint,String name){
System.out.println("--前置通知--"+name);
}
@After("daoPointCut()")
public void After(){
System.out.println("最终通知");
}
@Around("daoPointCut()")
public Object around(ProceedingJoinPoint joinPoint){
System.out.println("--环绕通知的前置通知--");
// 目标方法
Object proceed = null;
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("--环绕通知的后置通知--");
return proceed;
}
@AfterReturning(value = "daoPointCut()",returning = "valueResult")
public void afterReturning(int valueResult){
System.out.println("--后置通知--");
System.out.println("--目标方法的返回值--"+valueResult);
}
}
@Component//表示将这个类交给spring管理,创建这个类的bean
public class UserDaoImpl implements UserDao {
public int save(String name) {
System.out.println("我的名字是:"+name);
return 1;
}
}
public class AspectsTest {
@Test
public void test(){
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);//注册配置类,必须
ctx.refresh();//刷新容器,必须
UserDao userDao = ctx.getBean(UserDao.class);
userDao.save("quail");
}
}
执行结果: