Spring

Spring |3.1.x 下

2020-05-21  本文已影响0人  不一样的卡梅利多

上节简单介绍了3.1.x 版本较以前版本变化之处,以及如何解析注解。这节详细介绍下注解的整个处理流程。

客户端入口代码

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.scan(AnnotationContextTest.class.getPackage().getName());
        context.refresh();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

1、new AnnotationConfigApplicationContext

public AnnotationConfigApplicationContext() {
       this.reader = new AnnotatedBeanDefinitionReader(this);
       this.scanner = new ClassPathBeanDefinitionScanner(this);
   }

先调用父类构造函数:
AnnotationConfigApplicationContext 对bean 操作委派给DefaultListableBeanFactory 处理

public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

1.1.1 registerAnnotationConfigProcessors

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.environment = environment;
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

1、注册系统默认的注解处理器 比如 :ConfigurationClassPostProcessor, @Configuration 注解核心处理类

注解解析流程
1、ClassPathBeanDefinitionScanner 扫描包下面的被注解@Component 的类
以及被 @Component 注解的注解@Repository,@Controller ,@Service,
@Configuration,这些注解的类,除了是配置bean 外也是一个普通的BeaDefiniton。

@Repository,@Controller ,@Service @Configuration,@Component 这类注解被叫做元注解

2、ConfigurationClassPostProcessor 会解析@Configuration注解,然后将解析的结果注册到BeanDefinitionRegister 上面。这部分解析会使用其他注解来进行扩展,去找到更多的BeanDefinition。
1、 @Profile ,
2、@PropertySource
3、@ComponentScan :类扫描注解
4、@ImportResource :资源导入注解
5、@Bean :bean定义 注解
6、@Import :导入其他类定义的注解

这些注解都要联合@Configuration 注解才能生效。@Configuration 注解解析核心方法为:ConfigurationClassParser#processConfigurationClass,会递归解析父类的注解。

3、扩展注解 @Import 解析流程

private void processImport(ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports) throws IOException {
        if (checkForCircularImports && this.importStack.contains(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
        }
        else {
            this.importStack.push(configClass);
            AnnotationMetadata importingClassMetadata = configClass.getMetadata();
            for (String candidate : classesToImport) {
                MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate);
                if (new AssignableTypeFilter(ImportSelector.class).match(reader, this.metadataReaderFactory)) {
                    // the candidate class is an ImportSelector -> delegate to it to determine imports
                    try {
                        ImportSelector selector = BeanUtils.instantiateClass(
                                this.resourceLoader.getClassLoader().loadClass(candidate), ImportSelector.class);
                        processImport(configClass, selector.selectImports(importingClassMetadata), false);
                    }
                    catch (ClassNotFoundException ex) {
                        throw new IllegalStateException(ex);
                    }
                }
                else if (new AssignableTypeFilter(ImportBeanDefinitionRegistrar.class).match(reader, metadataReaderFactory)) {
                    // the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
                    try {
                        ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(
                                this.resourceLoader.getClassLoader().loadClass(candidate), ImportBeanDefinitionRegistrar.class);
                        registrar.registerBeanDefinitions(importingClassMetadata, registry);
                    }
                    catch (ClassNotFoundException ex) {
                        throw new IllegalStateException(ex);
                    }
                }
                else {
                    // the candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class
                    this.importStack.registerImport(importingClassMetadata.getClassName(), candidate);
                    processConfigurationClass(new ConfigurationClass(reader, true));
                }
            }
            this.importStack.pop();
        }
    }

ImportSelector 返回类定义的配置类名称,这样就可以实现灵活扩展
ImportBeanDefinitionRegistrar :灵活注册bean。

@import使用:

@import(ImportSelector.class) 
@import(ImportBeanDefinitionRegistrar.class)

@EnableTransactionManagement 实现分析

注解定义:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {}

ImportSelector 返回扩展的类配置名称,ConfigurationClassParser#processImport 对返回的类,进行配置解析,并且注册bean信息。

public class TransactionManagementConfigurationSelector
        extends AdviceModeImportSelector<EnableTransactionManagement> {

    /**
     * {@inheritDoc}
     * @return {@link ProxyTransactionManagementConfiguration} or
     * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and
     * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively
     */
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] { AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName() };
            case ASPECTJ:
                return new String[] { TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME };
            default:
                return null;
        }
    }


}

如果配置为 :PROXY
返回
1、AutoProxyRegistrar 注册代理类

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

2、ProxyTransactionManagementConfiguration 被@Configuration 注解 生成事务管理相关的配置信息。

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name=TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor =
            new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        advisor.setAdvice(transactionInterceptor());
        advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }
        return interceptor;
    }

}

小结:

注解配置的主要流程为 :
1、ClassPathBeanDefinitionScanner#scan(package) 扫描包下面的被注解@Component 的类以及被 @Component 注解的注解@Repository,@Controller ,@Service, @Configuration 的类

2、ConfigurationClassParser#processConfigurationClass 对注解了@Configuration 的类进行解析, 二次扩展注册bean。

3、其他流程在见AbstractApplicationContext#refresh 方法

Spring 专题

上一篇下一篇

猜你喜欢

热点阅读