上节简单介绍了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 方法
网友评论