【spring源码】六、@EnableAspectJAutoProxy

invokeBeanFactoryPostProcessors()

先说明:invokeBeanFactoryPostProcessors()是在refresh()方法中的第⑤步,他的作用是注册bean的定义信息,但还没进行创建实例。我们下面介绍了注解@EnableAspectJAutoProxy就是在这个阶段注册一个bean定义,但实例化要推迟到第⑥步registerBeanPostProcessor()完成

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy的作用是给spring容器中注册一个bean:这个bean名为internalAutoProxyCreator,类型为AnnotationAwareAspectJAutoProxyCreator.class “注册装配模式的切面自动代理创建器”

另外可以注意,是在invokeBeanFactoryPostProcessors()阶段进来调用注册的

@EnableAspectJAutoProxy标准在配置类上,在EnableAspectJAutoProxy接口类上有@Import(AspectJAutoProxyRegistrar.class),该@Import给容器中导入了AspectJAutoProxyRegistrar这个bean,而这个bean作用是手动注册bean定义到ac容器中。

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({
    
    AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    
    
    // 用于强制使用cglib动态代理,即使实现了接口。
    // 如果希望强制使用CGLIB代理(例如希望代理目标对象的所有方法,而不只是实现自接口的方法)// 但需要保证有CGLIB包
    boolean proxyTargetClass() default false;

    // 事务中会用到 // 是否暴露代理对象,暴露出来的代理对象和线程绑定,用的是threadLocal // 设置为true之后还得用(AopContext.currentProxy()).被调方法() 替换原来的 被调方法()
    // 比如切入点表达式是save方法,saveAll方法没在切入点表达式里,saveAll调用了save方法,此时调用saveAll方法并不执行save的AOP方法//走save的时候该轮到增强的事情已经过去了//AopContext.currentProxy()获取代理对象
    boolean exposeProxy() default false;
}

exposeProxy解释:

public interface UserService{
     
     
	public void a();
	public void a();
}

public class UserServiceImpl implements UserService{
     
     
	@Transactional(propagation = Propagation.REQUIRED)
	public void a(){
     
     
		this.b();
	}
	@Transactional(propagation = Propagation.REQUIRED_NEW)
	public void b(){
     
     
		System.out.println("b has been called");
	}
}
代码参照《Spring源码解析》p173页。
Q1:b中的事务会不会生效?
A1:不会,a的事务会生效,b中不会有事务,因为a中调用b属于内部调用,没有通过代理,所以不会有事务产生。
Q2:如果想要b中有事务存在,要如何做?
A2:<aop:aspectj-autoproxy expose-proxy=true> ,设置expose-proxy属性为true,将代理暴露出来,使用AopContext.currentProxy()获取当前代理,将this.b()改为((UserService)AopContext.currentProxy()).b()

Import(AspectJAutoProxyRegistrar)

而注解驱动里的知识告诉我们@Import与实现ImportBeanDefinitionRegistrar接口的类注册bean的用法,这时@Import就会调用这个类的registerBeanDefinitions()方法,(可以在这个方法上打断点)

class AspectJAutoProxyRegistrar 
    implements ImportBeanDefinitionRegistrar {
    
    	// 实现该接口的话会自动调用registerBeanDefinitions()方法

    @Override
    public void registerBeanDefinitions(//注册bean定义,而不是注册bean实例
        AnnotationMetadata importingClassMetadata, 
        BeanDefinitionRegistry registry) {
    
    //bean定义注册器
        
        // 去注册bean // 如有必要就注册AspectJ注解自动代理创建器
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        // 拿到注解@EnableAspectJAutoProxy注解的属性信息,proxyTargetClass、exposeProxy
        AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, //当前类的元数据
                                                EnableAspectJAutoProxy.class);// 哪个注解
        // 如果拿到了注解信息
        if (enableAspectJAutoProxy != null) {
    
    
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
    
    
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    
    
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

    ...;
}
//==========多次重载跳到===============================
public abstract class AopConfigUtils {
    
    
    // 注册类
    private static BeanDefinition registerOrEscalateApcAsRequired(
        Class<?> cls, //AnnotationAwareAspectJAutoProxyCreator.class
        BeanDefinitionRegistry registry, //注册器
        @Nullable Object source) {
    
    

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        // 如果bean定义存在了
        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;
        }
        // else 如果该bean定义不存在
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);//AnnotationAwareAspectJAutoProxyCreator.class
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        // 注册bean定义
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

比如现在我们有个逻辑(有红蓝色颜料就能造出彩虹),该方法可以通过registry.containsBeanDefinition("com.atguigu.bean.MyRed");判断容器中是否有了对应的红bean(的定义信息),同理还判断有没有蓝bean定义,如红蓝bean定义信息都有,就创建一个彩虹BeanDefinition定义信息,:new RootBeanDefinition(RainBow.class);,然后注册bean定义信息到容器中:registry.registerBeanDefinition("rainBow", beanDefinition);从而创建bean的时候工厂容器就知道要创建哪些bean了。

也就是说:@Import(AspectJAutoProxyRegistrar)的作用的注册一个bean定义信息:这个bean名为internalAutoProxyCreator,类型为AnnotationAwareAspectJAutoProxyCreator.class

AnnotationAwareAspectJAutoProxyCreator

“org.springframework.aop.config.internalAutoProxyCreator”

上面说了:AspectJAutoProxyRegistrar的作用的注册一个bean:internalAutoProxyCreator。而internalAutoProxyCreator是bean name,对应的值是类AnnotationAwareAspectJAutoProxyCreator(注解装配方式的切面自动代理创建器)。他是一个后置处理器。AnnotationAwareAspectJAutoProxyCreator的继承关系如下:

类继承关系
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
    
    }
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
    
    }
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    
    }
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    }
总结关系如下:
---AnnotationAwareAspectJAutoProxyCreator
------AnnotationAwareAspectJAutoProxyCreator
--------->AspectJAwareAdvisorAutoProxyCreator
------------>AbstractAdvisorAutoProxyCreator
--------------->AbstractAutoProxyCreator 
------------------>BeanFactoryAware  //(这个接口可以把bean工厂拿到)
------------------>SmartInstantiationAwareBeanPostProcessor //(注意这个)
---------------------->InstantiationAwareBeanPostProcessor
-------------------------->BeanPostProcessor

img

每个类的作用:
==父类-->子类
=====AbstractAutoProxyCreator======
public void setBeanFactory(BeanFactory beanFactory) {
    
    }
public boolean postProcessBeforeInstantiation();
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
    
    }

=====AbstractAdvisorAutoProxyCreator========;
public void setBeanFactory(BeanFactory beanFactory);{
    
    initBeanFactory((ConfigurableListableBeanFactory)beanFactory);}//子类重写了setBeanFactory方法//refresh(){registerBeanPostProcessor(){这里调用了set方法}}

========AspectJAwareAdvisorAutoProxyCreator===========;
========AnnotationAwareAspectJAutoProxyCreator====protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    
    }//前面的setBeanFactory调用了该方法,这里重写了

如果想了解xml方式的AspectJAwareAdvisorAutoProxyCreator是如何注入到容器的,可以参考https://blog.csdn.net/qq_26323323/article/details/81012855

第⑤部分更多的内容我们放后面点拓展部分再讲

AnnotationAwareAspectJAutoProxyCreator注册时机

这里说下流程,具体步骤可以看后文的附录的⑤

main方法
invokeBeanFactoryPostPostProcessors() 注册bean工厂的后置处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
遍历所有所有bean工厂后置处理器,依次实例化工厂后置处理器,然后依次调用他们里面重写了的registerBeanDefinitions方法
refresh();

invokeBeanFactoryPostProcessors(beanFactory);

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

postProcessor.postProcessBeanDefinitionRegistry(registry);//

processConfigBeanDefinitions(registry);

this.reader.loadBeanDefinitions(configClasses);//ConfigurationClassPostProcessor.java

loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);//此处的变量内容如下图 //并不是每个configModel都会走这个方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
registrars.forEach((registrar, metadata) ->
                   registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));


class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
    

    @Override
    public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
    
        // 这个方法就是我们之前看过的
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
    
    
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
    
    //jdk动态代理还是CGLIB动态代理
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    
    //暴露代理对象
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);//就是给bean定义中添加一个属性是exposeProxy
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/hancoder/article/details/111413353