Spring 源码分析--AOP篇 一、从@EnableAspectJAutoProxy开始

746 阅读3分钟

一、从@EnableAspectJAutoProxy开始

要使用Spring 的 AOP功能,就得先开启该功能,在注解式开发中,该功能的开关就是@EnableAspectJAutoProxy,我们先来看看这个注解的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// ① 导入了一个AspectJAutoProxyRegistrar
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass() default false;
	boolean exposeProxy() default false;
}

可以看到①使用了@Import导入了一个AspectJAutoProxyRegistrar类,我们再点进去看看它是个什么

//①
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(
                //importingClassMetadata 标有@import注解的类的元信息
                //BeanDefinitionRegistry 其他bean定义的注册表
		AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        
                // ② 如果有需要则注册AspectJAnnotationAutoProxyCreator
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

                //获取@EnableAspectJAutoProxy注解的属性
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        
                // 强制使用CGLIB
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
        
                //是否暴露被代理后的bean到AopContext中,详见该注解属性的用法
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}

}

可以看到AspectJAutoProxyRegistrar是一个ImportBeanDefinitionRegistrar(import注解的bean定义导入器,用来手动注册bean定义信息,在Spring的复习笔记中也提到过)。接下来观察下它的源码,非常明显②是最关键的。

//如果有需要则注册AspectJAnnotationAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

进去看看,下面AutoProxyCreator(自动代理创建器)简称Apc

// ① Apc的bean名称,该bean名称将在后面的源码分析中经常出现
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
    "org.springframework.aop.config.internalAutoProxyCreator";	

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    //往下一层调用
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    // ② 往下一层调用,按需要注册或者升级Apc,这里我们需要注册AnnotationAwareAspectJAutoProxyCreator(注解版Apc)
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    //判断bean注册表中是否有Apc,我们这里只用了注解的AOP且程序第一次启动,所以容器中没有其他的Apc
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        //若有则取出,并与我们传进来的AspectJAnnotationAutoProxyCreator比较优先级,取优先级较高的Apc
        //有哪些Apc可以具体点进findPriorityForClass方法查看
        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;
    }

    // ③ 创建 注解版Apc的bean定义
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    // TODO 设置bean定义的一些属性
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 向bean定义注册表中 注册了 注解版Apc
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

结合①②③,我们可以总结出,在我们这个例子中@EnableAspectJAutoProxy实际作用就是往bean定义注册表中注册了AnnotationAwareAspectJAutoProxyCreator(注解版Apc)的bean定义信息。

对于一个类,我们可以观察的它的继承体系来快速了解它的基本作用,我们观察下注解版Apc的继承体系

image-20211030231115332.png

关注红框部分,在之前的复习笔记中得知,注解版Apc不仅能够Aware(感知)BeanFactoryBeanClassLoader还是一个BeanPostProcess能够处理其他bean在初始化前后的一些逻辑。不仅如此,我们可以发现它还是个InstantiationAwareBeanPostProcess,观察这个接口定义的方法,不能判断出它可以处理bean在实例化前后的逻辑,这使 bean的生命周期变得更加灵活。在之后的笔记中,我们再来分析注解版Apc是如何实现这些接口的,实现方法中又做了哪些事情。

image-20211030233036550.png