java spring 加载bean_Spring之基于Java类的配置bean的加载注册流程

描述

Spring Bean定义的三种方式:

基于XML的配置

基于注解的配置,在类中加入如下注解通过包扫描加载注册bean:

@Component:当对组件的层次难以定位的时候使用这个注解

@Controller:表示控制层的组件

@Service:表示业务逻辑层的组件

@Repository:表示数据访问层的组件

基于Java类的配置:

使用@Configuration注解需要作为配置的类,表示该类将定义Bean的元数据

使用@Bean注解相应的方法,该方法名默认就是Bean的名称,该方法返回值就是Bean的对象。

下面跟踪源码查看spring基于Java类的配置定义bean的加载注册流程

Java类配置的模型

@Configuration描述的类模型ConfigurationClass

final class ConfigurationClass {

/**

* 注解元数据

*/

private final AnnotationMetadata metadata;

/**

* 资源信息

*/

private final Resource resource;

/**

* bean定义的名称

*/

@Nullable

private String beanName;

/**

* import 注解导入的配置类(被@Configuration注解的类)集合

*/

private final Set importedBy = new LinkedHashSet<>(1);

/**

* 配置类下被@Bean注解的方法结合

*/

private final Set beanMethods = new LinkedHashSet<>();

/**

* 跳过的方法名集合

*/

final Set skippedBeanMethods = new HashSet<>();

}

ConfigurationClass 类主要用于描述被@Configuration注解的配置类的信息,我们在spring中定义的配置类,会被spring首先解析成BeanDefinition,然后spring会根据此BeanDefinition创建配置类对应的ConfigurationClass

如下类,spring会生成对应的ConfigurationClass模型

@Configuration

@Import({ SessionRouteConfig.class })

@EnableConfigurationProperties({ ServiceInstanceProperties.class, SessionProperties.class })

public class GatewayConfiguration {

@Bean

@ConditionalOnMissingBean

SessionFilterPredicateFactory sessionFilterPredicateFactory() {

return new DefaultSessionFilterPredicateFactory();

}

}

配置类中被@Bean注解的方法模型BeanMethod

final class BeanMethod extends ConfigurationMethod {

public BeanMethod(MethodMetadata metadata, ConfigurationClass configurationClass) {

super(metadata, configurationClass);

}

@Override

public void validate(ProblemReporter problemReporter) {

if (getMetadata().isStatic()) {

// static @Bean methods have no constraints to validate -> return immediately

return;

}

if (this.configurationClass.getMetadata().isAnnotated(Configuration.class.getName())) {

if (!getMetadata().isOverridable()) {

// instance @Bean methods within @Configuration classes must be overridable to accommodate CGLIB

problemReporter.error(new NonOverridableMethodError());

}

}

}

}

BeanMethod 用于描述配置类下被@Bean修饰的方法的模型,spring会BeanMethod 模型创建方法返回类的BeanDefinition,并将其注册到bean定义注册中心,以达到bean定义的加载注册,如上例中sessionFilterPredicateFactory方法,spring会生成对应的BeanMethod 模型与之对应。

java配置定义bean加载解析入口

// 类 ConfigurationClassPostProcessor

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,

PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

/**

* 从注册表中的配置类派生进一步的bean定义。

* Derive further bean definitions from the configuration classes in the registry.

*/

@Override

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {

//处理配置类的bean定义

processConfigBeanDefinitions(registry);

}

/**

* Build and validate a configuration model based on the registry of

* {@link Configuration} classes.

*/

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

//存在配置类bean定义的集合,用于存储所有被@Configuration注解的类

List configCandidates = new ArrayList<>();

//获取bean定义注册中心的bean定义名称集合

String[] candidateNames = registry.getBeanDefinitionNames();

for (String beanName : candidateNames) {

//遍历名称根据名称在注册中心获取当前名称的BeanDefinition

BeanDefinition beanDef = registry.getBeanDefinition(beanName);

//校验当前bean定义是否为配置类

//判断当前的bean定义是否为存在精简或者完整的配置类标识,当存在此标识时标识已被处理过

if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||

ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {

//检测bean定义是否已经被处理

if (logger.isDebugEnabled()) {

logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);

}

}

//检测给定的bean定义是否是描述的配置类

else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {

//将配置类的bean定义添加到configCandidates

configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));

}

}

//配置类bean定义的集合为空时不做任何处理直接返回

// Return immediately if no @Configuration classes were found

if (configCandidates.isEmpty()) {

return;

}

//配置类bean定义的集合 排序

// Sort by previously determined @Order value, if applicable

configCandidates.sort((bd1, bd2) -> {

int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());

int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());

return Integer.compare(i1, i2);

});

//检测获取命名生成策略器

// Detect any custom bean name generation strategy supplied through the enclosing application context

SingletonBeanRegistry sbr = null;

if (registry instanceof SingletonBeanRegistry) {

sbr = (SingletonBeanRegistry) registry;

if (!this.localBeanNameGeneratorSet) {

BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);

if (generator != null) {

this.componentScanBeanNameGenerator = generator;

this.importBeanNameGenerator = generator;

}

}

}

if (this.environment == null) {

this.environment = new StandardEnvironment();

}

//创建配置类的解析器,解析每个@Configuration注解的类

// Parse each @Configuration class

ConfigurationClassParser parser = new ConfigurationClassParser(

this.metadataReaderFactory, this.problemReporter, this.environment,

this.resourceLoader, this.componentScanBeanNameGenerator, registry);

//准备解析的bean定义集合

Set candidates = new LinkedHashSet<>(configCandidates);

//处理完成的模型的集合

Set alreadyParsed = new HashSet<>(configCandidates.size());

do {

//解析bean定义,生成ConfigurationClass模型

parser.parse(candidates);

//校验ConfigurationClass模型

parser.validate();

//获取解析到的ConfigurationClass模型集合

Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());

//当前处理的模型中移除已经处理的的模型

configClasses.removeAll(alreadyParsed);

//读取模型并根据内容创建bean定义

// Read the model and create bean definitions based on its content

if (this.reader == null) {

this.reader = new ConfigurationClassBeanDefinitionReader(

registry, this.sourceExtractor, this.resourceLoader, this.environment,

this.importBeanNameGenerator, parser.getImportRegistry());

}

//加载创建模型中的所有bean定义

this.reader.loadBeanDefinitions(configClasses);

//当前模型集合添加到已处理集合中

alreadyParsed.addAll(configClasses);

candidates.clear();

//判断注册中心中注册表是否存在新增数据,如果有新增数据,重新遍历获取新增数据解析

if (registry.getBeanDefinitionCount() > candidateNames.length) {

String[] newCandidateNames = registry.getBeanDefinitionNames();

Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));

Set alreadyParsedClasses = new HashSet<>();

for (ConfigurationClass configurationClass : alreadyParsed) {

alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());

}

for (String candidateName : newCandidateNames) {

if (!oldCandidateNames.contains(candidateName)) {

BeanDefinition bd = registry.getBeanDefinition(candidateName);

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&

!alreadyParsedClasses.contains(bd.getBeanClassName())) {

candidates.add(new BeanDefinitionHolder(bd, candidateName));

}

}

}

candidateNames = newCandidateNames;

}

}

while (!candidates.isEmpty());

}

}

类 ConfigurationClassPostProcessor 为spring对@Configuration解析处理的后置处理器。

ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,此接口是BeanFactoryPostProcessor的扩展接口,在BeanFactoryPostProcessor执行流程笔记中分析过,允许在正常的BeanFactoryPostProcessor执行检测开始之前注册更多的自定义bean。也就是说BeanDefinitionRegistryPostProcessor的方法postProcessBeanDefinitionRegistry可以在后置处理器执行前自定义注册更多的BeanDefinition

ConfigurationClassPostProcessor 的postProcessBeanDefinitionRegistry方法完成的功能如下:

遍历bean定义注册器中所有的bean定义查找配置bean定义(元数据中含有@Configuration注解的bean定义)

通过配置类解析器ConfigurationClassParser 根据配置bean定义创建配置模型ConfigurationClass和BeanMethod

//解析bean定义,生成ConfigurationClass模型

parser.parse(candidates);

//校验ConfigurationClass模型

parser.validate();

根据配置类模型转换器ConfigurationClassBeanDefinitionReader根据配置类模型创建配置类中的BeanDefinition并注册到BeanDefinition注册中心

//读取模型并根据内容创建bean定义

// Read the model and create bean definitions based on its content

if (this.reader == null) {

this.reader = new ConfigurationClassBeanDefinitionReader(

registry, this.sourceExtractor, this.resourceLoader, this.environment,

this.importBeanNameGenerator, parser.getImportRegistry());

}

//加载创建模型中的所有bean定义

this.reader.loadBeanDefinitions(configClasses);

配置类解析器ConfigurationClassParser

配置类解析器ConfigurationClassParser 根据配置类的BeanDefinition生成配置类模型数据ConfigurationClass与BeanMethod

解析主方法parse

public void parse(Set configCandidates) {

this.deferredImportSelectors = new LinkedList<>();

for (BeanDefinitionHolder holder : configCandidates) {

//循环遍历配置类的bean定义,解析生成对应的ConfigurationClass模型

BeanDefinition bd = holder.getBeanDefinition();

try {

if (bd instanceof AnnotatedBeanDefinition) {

parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

}

else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {

parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());

}

else {

parse(bd.getBeanClassName(), holder.getBeanName());

}

}

catch (BeanDefinitionStoreException ex) {

throw ex;

}

catch (Throwable ex) {

throw new BeanDefinitionStoreException(

"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);

}

}

processDeferredImportSelectors();

}

此方法最终调用doProcessConfigurationClass方法对ConfigurationClass创建初始化

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)

throws IOException {

// 递归处理配置类的成员嵌套类

processMemberClasses(configClass, sourceClass);

//处理配置类上的@PropertySource注解

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), PropertySources.class,

org.springframework.context.annotation.PropertySource.class)) {

if (this.environment instanceof ConfigurableEnvironment) {

processPropertySource(propertySource);

}

else {

}

}

//处理配置类上的@ComponentScan注解

Set componentScans = AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

if (!componentScans.isEmpty() &&

!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

for (AnnotationAttributes componentScan : componentScans) {

// The config class is annotated with @ComponentScan -> perform the scan immediately

Set scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

// Check the set of scanned definitions for any further config classes and parse recursively if needed

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();

if (bdCand == null) {

bdCand = holder.getBeanDefinition();

}

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {

parse(bdCand.getBeanClassName(), holder.getBeanName());

}

}

}

}

//处理配置类上的@Import注解

processImports(configClass, sourceClass, getImports(sourceClass), true);

//处理配置类上的@ImportResource注解

AnnotationAttributes importResource =

AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);

if (importResource != null) {

String[] resources = importResource.getStringArray("locations");

Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");

for (String resource : resources) {

String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);

configClass.addImportedResource(resolvedResource, readerClass);

}

}

//处理配置类里@Bean注解的方法

Set beanMethods = retrieveBeanMethodMetadata(sourceClass);

for (MethodMetadata methodMetadata : beanMethods) {

configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));

}

// Process default methods on interfaces

processInterfaces(configClass, sourceClass);

// Process superclass, if any

if (sourceClass.getMetadata().hasSuperClass()) {

String superclass = sourceClass.getMetadata().getSuperClassName();

if (superclass != null && !superclass.startsWith("java") &&

!this.knownSuperclasses.containsKey(superclass)) {

this.knownSuperclasses.put(superclass, configClass);

// Superclass found, return its annotation metadata and recurse

return sourceClass.getSuperClass();

}

}

return null;

}

doProcessConfigurationClass 方法依次完成如下功能:

递归处理配置类的成员嵌套类

处理配置类上的@PropertySource注解

处理配置类上的@ComponentScan注解

处理配置类上的@Import注解

处理配置类上的@ImportResource注解

处理配置类里@Bean注解的方法

处理接口上的默认方法

处理配置类的父类,如果有的话

最后spring 通过ConfigurationClassParser类将一个配置类的bean定义,解析成完整的ConfigurationClass(配置数据模型)

配置类模型转换bean定义

ConfigurationClassBeanDefinitionReader 会根据配置类模型ConfigurationClass读取创建BeanDefinition,并将BeanDefinition注册到bean定义注册表中。

加载配置中的BeanDefinition入口loadBeanDefinitions方法:

public void loadBeanDefinitions(Set configurationModel) {

TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();

for (ConfigurationClass configClass : configurationModel) {

//遍历ConfigurationClass依次加载注册配置的bean定义

loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);

}

}

loadBeanDefinitions 通过调用loadBeanDefinitionsForConfigurationClass加载注册bean定义

private void loadBeanDefinitionsForConfigurationClass(

ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

if (configClass.isImported()) {

//将ConfigurationClass本身的bean定义注册到注册中心

registerBeanDefinitionForImportedConfigurationClass(configClass);

}

for (BeanMethod beanMethod : configClass.getBeanMethods()) {

// 遍历BeanMethod

//根据BeanMethod 创建bean定义,此方法根据配置类中被@Bean注解的方法生成bean定义

//将生成的bean定义注册到注册中心

loadBeanDefinitionsForBeanMethod(beanMethod);

}

//加载来自ImportedResources的bean定义并注册

loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

//加载来自Import的bean定义并注册

loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

}

loadBeanDefinitionsForConfigurationClass 根据ConfigurationClass 创建其配置的bean定义,并将其注册到bean定义注册中心

接下来整体梳理下@Configuration配置的bean定义加载解析流程:

在spring完成基于注解配置bean定义的扫描注册后,通过后置处理器,获取到注册表中所有的bean定义。

遍历bean定义生成含有@Configuration注解的bean定义的集合。

根据配置类bean定义集合通过配置类解析器ConfigurationClassParser生成ConfigurationClass集合。

根据ConfigurationClass集合通过ConfigurationClassBeanDefinitionReader类加载注册配置里的bean定义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值