【源码】Spring —— BeanDefinition 解读2
前言
本章节想要结合 Spring
中几处使用案例来进一步了解 BeanDefinition
ClassPathScanningCandidateComponentProvider
该类基于类路径扫描获取 BeanDefinition
,其构造的 BeanDefinition
实例类型为 ScannedGenericBeanDefinition
。不难理解,其内部的元数据基于 SimpleMetadataReader
获取,代码片段如下
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// ...
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
// ...
}
}
}
}
}
}
- 此处只填充了
source
属性,后续还有基础属性的填充,此处略过,可参考ClassPathBeanDefinitionScanner
类 - 与之相似的还有
AnnotatedBeanDefinitionReader
类,它是基于配置类扫描,注册的BeanDefinition
类型为AnnotatedGenericBeanDefinition
ScopedProxyUtils
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
// 原名
String originalBeanName = definition.getBeanName();
// 目标 bd
BeanDefinition targetDefinition = definition.getBeanDefinition();
// 目标 bd 名称
String targetBeanName = getTargetBeanName(originalBeanName);
// 代理 bean 的类型为 ScopedProxyFactoryBean
// 主要是解决不同作用域实例互相依赖的问题
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(targetDefinition.getRole());
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
}
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
// 目标 bd setAutowireCandidate(false) setPrimary(false)
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false);
// 先注册目标 bd
registry.registerBeanDefinition(targetBeanName, targetDefinition);
// 返回代理 bd holder
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}
这是对需要代理的目标 BeanDefinition
生成代理 BeanDefinition
相关操作,在之前提到的 ClassPathBeanDefinitionScanner
和 AnnotatedGenericBeanDefinition
中都有调用,细节描述:
- 为目标
BeanDefinition
构造新的名称 - 构造的代理
BeanDefinition
类型为RootBeanDefinition
,同时指定其decoratedDefinition
resource
属性为目标BeanDefinition(Holder)
- 其余部分属性诸如
source
role
primary
等都是直接复制 - 特殊处理诸如
propertyValues
attribute
,维护代理相关标识 - 处理目标
BeanDefinition
并注册 - 最后返回代理
BeanDefinitionHolder
,后续也会被注册
ConfigurationClassBeanDefinitionReader
该类负责注册由 ConfigurationClassParser
解析配置类后相关的 BeanDefinition
,我们重点关注:
registerBeanDefinitionForImportedConfigurationClass
方法,注册配置类内部的普通成员类
或被Import
的普通类等对应的BeanDefinition
loadBeanDefinitionsForBeanMethod
方法,注册配置类@Bean
方法对应的BeanDefinition
registerBeanDefinitionForImportedConfigurationClass
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
// 元数据
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
// ScopeMetadata 解析
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
// beanName 解析
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
// 基于 元数据 解析 DependsOn Primary 等属性
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
// 代理 bd 的构造
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isTraceEnabled()) {
logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
}
}
方法总结:
- 对于如上配置类注册的是
AnnotatedGenericBeanDefinition
- 其注册流程与
AnnotatedBeanDefinitionReader
扫描配置类的流程别无二致:ScopeMetadata
解析、beanName
解析、基于元数据
的属性解析、代理BeanDefinition
构造、注册 - 其中代理
BeanDefinition
的构造流程就是由之前提到的ScopedProxyUtils
负责
loadBeanDefinitionsForBeanMethod
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
// 方法元数据
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// Condition 校验
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
// 基于 元数据 获取 @Bean 方法的所有属性
/**
* @Bean 注解的相关属性:
* name value 会被解析成 beanName
* autowire:默认值为 Autowire.NO,即基于注解注入,
* 且该属性已被标注为 @Deprecated
* autowireCandidate:是否注入备选 bean,默认 true
* initMethod:初始化前方法指定
* destroyMethod:销毁方法指定
*/
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
// name 处理
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// 构造 ConfigurationClassBeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
/**
* 此处核心是指定 UniqueFactoryMethodName 为当前方法名
*/
if (metadata.isStatic()) {
// static @Bean method
if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
}
else {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
}
beanDef.setUniqueFactoryMethodName(methodName);
}
else {
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
// 指定 ResolvedFactoryMethod
if (metadata instanceof StandardMethodMetadata) {
beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
}
// 设置 AutowireMode = AUTOWIRE_CONSTRUCTOR
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
// Lazy Primary Description 等注解相关解析
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
// 此处如果指定 AutowireMode 为 byType byName 则进行覆盖
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
// autowireCandidate 指定,默认 true
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
// initMethod 解析
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
// destroyMethod 解析
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
// Scope 解析
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// 代理相关
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
}
// 注册
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
- 针对
@Bean
方法,构造的是ConfigurationClassBeanDefinition
,它是AnnotatedBeanDefinition
的实现类 - 这里的核心是对
factoryMethod
相关处理,@Bean
方法本身被指定为创建目标bean
的工厂方法,因此针对该类型bean
的获取最终会被执行该方法 - 此处会指定
autowireMode = AUTOWIRE_CONSTRUCTOR
(工厂方法创建bean
依赖注入类似于构造方法的依赖注入),因此@Bean
方法的参数都会作为依赖自动注入 @Bean
注解可以指定诸如autowire
initMrthod
等属性,此外若显示指定autowire
为byType
byName
,则此处会覆盖原本的AUTOWIRE_CONSTRUCTOR
- 基于
元数据
的其他属性解析、代理相关等,不再重复叙述
总结
示例中是 Spring
注册 BeanDefinition
的经典案例,在上述收集与注册 BeanDefinition
的行为完成后,容器会在后续的阶段基于这些 BeanDefinition
创建对应的 bean
实例