【源码】Spring AOP 14 原理解读三
前言
一般的,我们使用 Spring AOP
时,会在对应的配置类加上 @EnableAspectJAutoProxy
注解以开启 AOP
能力,本章节就以此入手,总结一下 Spring AOP
的整体原理
EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
// 是否代理目标对象,即是否 CGLIB 代理
boolean proxyTargetClass() default false;
// 是否暴露代理对象到 AopContext
boolean exposeProxy() default false;
}
- 基于注解暴露了
proxyTargetClass
和exposeProxy
属性 - 核心是
Import
了一个AspectJAutoProxyRegistrar
可以看到 Spring 是默认 JDK 代理的(proxyTargetClass = false)
但是 Spring Boot 是默认 CGLIB 哦,可参考 AopAutoConfiguration
AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册核心组件 AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 基于注解上的属性做标识,创建代理的时候用 ...
}
}
- 它是一个
ImportBeanDefinitionRegistrar
,因此会在registerBeanDefinitions
方法中注册对应的BeanDefinition
- 此处基于
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
方法注册我们上一章节了解的AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils
public abstract class AopConfigUtils {
// 内置 beanName
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
/**
* 这里借由 List 来维护这几个 AbstractAutoProxyCreator 的等级
* 从上到下依次提高,功能越来越强嘛
*/
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
// ...
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
/**
* AnnotationAwareAspectJAutoProxyCreator
* 这里注册的是 AnnotationAwareAspectJAutoProxyCreator
* 它是最高等级,所以只会覆盖其他(如果有的话)
* 举个例子,如果 Spring AOP 和 Spring Cache 都存在
* 那就是 AnnotationAwareAspectJAutoProxyCreator
* 覆盖 InfrastructureAdvisorAutoProxyCreator 咯
*/
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
/** registerOrEscalateApcAsRequired **/
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
/**
* 先从容器中查看是否有目标 bean
* 如果容器中的 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;
}
// 如果不存在就直接注册了
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;
}
}
AopConfigUtils
是个挺有意思的工具类,它主要的作用就是负责注册这些 AbstractAutoProxyCreator
- 它给
InfrastructureAdvisorAutoProxyCreator
AspectJAwareAdvisorAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
从低到高排了等级 - 当它注册对应的实例时,会先从容器中查看是否存在当前实例,如果存在且等级比当前实例低,则会进行覆盖
- 因此,此处注册的是最高等级的
AnnotationAwareAspectJAutoProxyCreator
,它会覆盖容器中存在的其他实例,比如Spring Cache
引入的InfrastructureAdvisorAutoProxyCreator
等 - 至此,
Spring AOP
就实现了,跟我们上一章节末尾的示例差不多
原理解读
现在基于一段 Spring AOP
示例来重温一下整个流程
示例demo
@Configuration
@EnableAspectJAutoProxy
public class SpringAopDemo {
@Aspect
@Component
public static class MyAspect {
@Pointcut("execution(* com.example.springdemoall.aop.aop..*.hello())")
public void pointcut() {}
@Before("pointcut()")
public void before() {
System.out.println("before");
}
}
public interface Hello {
void hello();
}
@Component
public static class HelloImpl implements Hello {
@Override
public void hello() {
System.out.println("hello");
}
}
@Test
public void test() {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(SpringAopDemo.class);
Hello bean = context.getBean(Hello.class);
bean.hello();
}
}
流程解析
- 因为
@EnableAspectJAutoProxy
注解,容器中注册了AnnotationAwareAspectJAutoProxyCreator
实例 - 它作为一个
AbstractAutoProxyCreator
,在HelloImpl
的bean
实例生命周期阶段对它进行代理 - 作为一个
AbstractAdvisorAutoProxyCreator
,它会收集容器中的Advisor
s,同时作为AspectJAwareAdvisorAutoProxyCreator
它会解析我们定义的切面为Advisor
s(这部分工作由ReflectiveAspectJAdvisorFactory
完成),这些Advisor
s 会交给ProxyFactory
来创建代理对象 ProxyFactory
会基于代理配置选择对应的代理创建器,比如JdkDynamicAopProxy
或ObjenesisCglibAopProxy
,在本例中是JdkDynamicAopProxy
JdkDynamicAopProxy
它本身就是个InvocationHandler
,因此代理后的方法调用为invoke
,在invoke
方法中JdkDynamicAopProxy
会基于之前获取的Advisor
s (在本例中即我们基于切面解析的),获取当前方法匹配的Interceptors Chain
,封装成ReflectiveMethodInvocation
,最终通过ReflectiveMethodInvocation#proceed
和MethodInterceptor#invoke
完成巧妙递归执行完所有拦截通知ObjenesisCglibAopProxy
即CGLIB
也是差不多一样的原理
总结
大体上的原理了解的差不多了,Spring AOP
作为 Spring
的核心特征之一,自然不是十几篇文章就能了解清楚的,但基于这些内容也能略知一二,无论是代码结构抽象设计上的学习、还是日常使用排错的学习,都是很有帮助的
参考
【小家Spring】Spring AOP的核心类:AbstractAdvisorAutoProxy自动代理创建器深度剖析(AnnotationAwareAspectJAutoProxyCreator)