Spring Boot 中如何使用 Aspect 切面编程
(1) . 导入AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
(2) . 创建切面类 设置切入关注点
<!-- 创建切面类 当前类需要 添加 @Aspect 注解 -->
@Aspect
public class AspectDemo {
@Pointcut("execution (* com.example.init.bean.Car.* (..))")
public void pointcut () {}
@Before("pointcut ()")
public void before (JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName());
System.out.println("目标方法执行之前:" );
}
@After("pointcut ()")
public void after (JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName());
System.out.println("目标方法执行之后:");
}
@AfterReturning(value = "pointcut ()" ,returning = "count")
public void afterReturning (JoinPoint joinPoint ,int count) {
System.out.println(joinPoint.getSignature().getName() + "执行的结果是:[" + count + "]");
}
@AfterThrowing(value = "pointcut ()" ,throwing = "error")
public void afterThrowing (JoinPoint joinPoint ,Exception error) {
System.out.println(joinPoint.getSignature().getName() + "执行产生异常:" + error.getLocalizedMessage());
error.printStackTrace();
}
}
(3). 给当前项目启用 Aspect 代理
<!-- @EnableAspectJAutoProxy 注解可以添加在spring boot 启动类上 也可以添加配置类上 当前是添加在启动类上 -->
@EnableAspectJAutoProxy
@Configuration
@Import(AspectDemo.class)
public class AspectConfig {
}
@EnableAspectJAutoProxy 的作用
- 查看@EnableAspectJAutoProxy 注解源码
<!-- 查看源码可以发现 该注解为spring 容器添加了一个 AspectJAutoProxyRegistrar.class 类型的 bean ,
下面需要对这个类做了哪些事情进行追踪. -->
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
- 查看 AspectJAutoProxyRegistrar.class 类的源码
<!-- ImportBeanDefinitionRegistrar 该接口具有向容器内注册bean 的功能 -->
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
<!-- 第一步具体调用见下方 -->
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
第一步
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
// 调用了下面的方法
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
// 该方法又向下调用了 registerOrEscalateApcAsRequired 方法
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
<!--
需要主要的是 该方法的 cls 是 AnnotationAwareAspectJAutoProxyCreator.class 类型的,后面还要具体分析.
-->
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
<!--利用注册器查看容器中是否存在 AUTO_PROXY_CREATOR_BEAN_NAME("org.springframework.aop.config.internalAutoProxyCreator") 的实例.-->
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
<!--
在容器中不存在的情况下,向容器内注册 一个 AUTO_PROXY_CREATOR_BEAN_NAME
名字的bean实例
-->
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
AnnotationAwareAspectJAutoProxyCreator.class 类图
从类图中发现 AnnotationAwareAspectJAutoProxyCreator 是一个后置处理器