1.首先在xml文件中导入命名空间和xsd文件
命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
xsd文件
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
maven依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
2.配置spring扫描注解,aop注解实现
<context:component-scan base-package="com.demo" /> spring自动扫描包下注解
<aop:aspectj-autoproxy/> 扫描@Aspect注解,将其作为切面类
3.自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "insuranceDataSource";
public static String insurance = "insuranceDataSource";
public static String activity = "activityDataSource";
}
@Target 用于描述注解的使用范围(即:被描述的注解可以用在什么地方),其取值有:
取值 | 描述 |
CONSTRUCTOR | 用于描述构造器(领盒饭)。 |
FIELD | 用于描述域(领盒饭)。 |
LOCAL_VARIABLE | 用于描述局部变量(领盒饭)。 |
METHOD | 用于描述方法。 |
PACKAGE | 用于描述包(领盒饭)。 |
PARAMETER | 用于描述参数。 |
TYPE | 用于描述类或接口(甚至 enum )。 |
@Retention 用于描述注解的生命周期(即:被描述的注解在什么范围内有效),其取值有:
取值 | 描述 |
SOURCE | 在源文件中有效(即源文件保留,领盒饭)。 |
CLASS | 在 class 文件中有效(即 class 保留,领盒饭)。 |
RUNTIME | 在运行时有效(即运行时保留)。 |
@Documented 在默认的情况下javadoc命令不会将我们的annotation生成再doc中去的,所以使用该标记就是告诉jdk让它也将annotation生成到doc中去
@Inherited 比如有一个类A,在他上面有一个标记annotation,那么A的子类B是否不用再次标记annotation就可以继承得到呢,答案是肯定的
4.编写切面类
@Aspect
@Component
@Slf4j
public class DataSourceAspect {
//表示DataSource注解标注的地方即为切点
@Pointcut("@annotation(com.zhangjian.demo.aop.DataSource)")
//指定切点
//@Pointcut("execution(public * com.zhangjian.demo.controller..*.*(..))")
public void pointCut() {//切点的公共约束
log.info("point cut......");
}
//前置通知
//切点为公共约束+注解
@Before(value = "pointCut()&&@annotation(dataSource)")
public void before(DataSource dataSource) {
log.info("set data source: {}", dataSource);
}
//环绕通知
@Around(value = "pointCut()&&@annotation(dataSource)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, DataSource dataSource) throws Throwable {
log.info("before data source: {}", dataSource);
return proceedingJoinPoint.proceed();
log.info("after data source: {}", dataSource);
}
//最终通知
@After(value = "pointCut()&&@annotation(dataSource)")
public void methodAfter(JoinPoint joinPoint, MethodLog methodLog) throws Throwable {
log.info("after data source: {}", dataSource);
}
//后置通知
@AfterReturning(value = "pointCut()&&@annotation(dataSource)")
public void methodAfterReturning(JoinPoint joinPoint, MethodLog methodLog, Object result) throws Throwable {
log.info("after data source: {}", dataSource);
}
//标注该方法体为异常通知,当目标方法出现异常时,执行该方法体
@AfterThrowing(pointcut="within(com.abchina.irms..*) && @annotation(rl)")
public void addLog(JoinPoint jp, rmpfLog rl, BusinessException ex){
...
}
}
执行顺序为@Around,@Before,@Around,@After,@AfterReturning