BeanDefinition在Spring初始化階段保存Bean的元資料資訊,包括Class名稱、Scope、構造方法引數、屬性值等資訊,本文將介紹一下BeanDefinition介面、重要的實作類,以及在Spring中的使用示例,
BeanDefinition介面
用于描述了一個Bean實體,該Bean實體具有屬性、構造方法引數以及由具體實作提供的其他資訊,
這是一個基礎介面:主要目的是允許BeanFactoryPostProcessor獲取和修改Bean實體屬性和其他元資料,
封裝以下資訊:
- ParentName - The name of the parent definition of this bean definition.
- BeanClassName - The bean class name of this bean definition. The class name can be modified during bean factory post-processing, typically replacing the original class name with a parsed variant of it.
- Scope - Override the target scope of this bean, specifying a new scope name.
- isLazyInit - Whether this bean should be lazily initialized.
- DependsOn - The names of the beans that this bean depends on being initialized. The bean factory will guarantee that these beans get initialized first.
- AutowireCandidate - Whether this bean is a candidate for getting autowired into some other bean.
- Primary - Whether this bean is a primary autowire candidate.
- FactoryBeanName - The factory bean to use. This the name of the bean to call the specified factory method on.
- FactoryMethodName - Specify a factory method, if any. This method will be invoked with constructor arguments, or with no arguments if none are specified. The method will be invoked on the specified factory bean, if any, or otherwise as a static method on the local bean class.
- ConstructorArgumentValues - Constructor argument values for this bean.
- PropertyValues - The property values to be applied to a new instance of the bean.
- InitMethodName - The name of the initializer method.
- DestroyMethodName - The name of the destroy method.
- Role - The role hint for this BeanDefinition. The role hint provides the frameworks as well as tools an indication of the role and importance of a particular BeanDefinition.
- ResolvableType - A resolvable type for this bean definition, based on the bean class or other specific metadata.
- isSingleton - Whether this a Singleton, with a single, shared instance returned on all calls.
- isPrototype - Whether this a Prototype, with an independent instance returned for each call.
- isAbstract - Whether this bean is "abstract", that is, not meant to be instantiated.
- OriginatingBeanDefinition - The originating BeanDefinition.
AbstractBeanDefinition類
實作了BeanDefinition介面,具體的、完整的BeanDefinition基類,抽取出GenericBeanDefinition、RootBeanDefinition和ChildBeanDefinition的公共屬性,
擴展的屬性:
- AutowireMode - The autowire mode. This determines whether any automagical detection and setting of bean references will happen. Default is AUTOWIRE_NO which means there won't be convention-based autowiring by name or type (however, there may still be explicit annotation-driven autowiring).
- AUTOWIRE_NO
- AUTOWIRE_BY_NAME
- AUTOWIRE_BY_TYPE
- AUTOWIRE_CONSTRUCTOR
- AUTOWIRE_AUTODETECT
RootBeanDefinition類
繼承AbstractBeanDefinition類,
RootBeanDefinition表示在運行時支持BeanFactory中指定Bean的合并BeanDefinition,它可能是由多個相互繼承的原始BeanDefinition創建的,通常注冊為GenericBeanDefinitions,RootBeanDefinition本質上是運行時的"統一"RootBeanDefinition視圖,
RootBeanDefinition也可以用于在配置階段注冊各個BeanDefinition,然而,自Spring2.5以來,以編程方式注冊BeanDefinition的首選方式是GenericBeanDefinition類,GenericBeanDefinition的優勢是允許動態定義父依賴項,而不是將角色硬編碼為RootBeanDefinition,
擴展的屬性:
- DecoratedDefinition - Target definition that is being decorated by this bean definition.
- QualifiedElement - Specify the AnnotatedElement defining qualifiers, to be used instead of the target class or factory method.
- TargetType - Specify a generics-containing target type of this bean definition, if known in advance.
- stale - Determines if the definition needs to be re-merged.
- allowCaching
- isFactoryBean
GenericBeanDefinition類
繼承AbstractBeanDefinition類,
GenericBeanDefinition是用于構建標準BeanDefinition的一站式組件,與其他BeanDefinition一樣,它允許指定一個類以及可選的構造方法引數和屬性,另外,從父BeanDefinition派生可以通過parentName屬性靈活配置,
通常,使用GenericBeanDefinition類來注冊用戶可見的BeanDefinition,后置處理器可能會對其進行操作,甚至可能重新配置parentName屬性,如果父子關系恰好是預先確定的,請使用RootBeanDefinition和ChildBeanDefinition,
AnnotatedBeanDefinition介面
繼承BeanDefinition介面,
擴展BeanDefinition介面,提供Bean的AnnotationMetadata,而不需要加載該類,
public interface AnnotatedBeanDefinition extends BeanDefinition {
/**
* Obtain the annotation metadata (as well as basic class metadata)
* for this bean definition's bean class.
*/
AnnotationMetadata getMetadata();
/**
* Obtain metadata for this bean definition's factory method, if any.
*/
MethodMetadata getFactoryMethodMetadata();
}
ScannedGenericBeanDefinition類
GenericBeanDefinition類的擴展,基于ASM ClassReader,實作了AnnotatedBeanDefinition介面,可以獲取注解元資料,
這個類不會提前加載Bean Class,它從.class檔案檢索所有相關的元資料,并使用ASM ClassReader進行決議,
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {
private final AnnotationMetadata metadata;
/**
* Create a new ScannedGenericBeanDefinition for the class that the
* given MetadataReader describes.
* @param metadataReader the MetadataReader for the scanned target class
*/
public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
this.metadata = https://www.cnblogs.com/xugf/p/metadataReader.getAnnotationMetadata();
setBeanClassName(this.metadata.getClassName());
setResource(metadataReader.getResource());
}
@Override
public final AnnotationMetadata getMetadata() {
return this.metadata;
}
@Override
public MethodMetadata getFactoryMethodMetadata() {
return null;
}
}
AnnotatedGenericBeanDefinition類
GenericBeanDefinition類的擴展,實作了AnnotatedBeanDefinition介面,可以獲取注解元資料,
public class AnnotatedGenericBeanDefinition
extends GenericBeanDefinition implements AnnotatedBeanDefinition {
private final AnnotationMetadata metadata;
private MethodMetadata factoryMethodMetadata;
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
setBeanClass(beanClass);
this.metadata = https://www.cnblogs.com/xugf/p/AnnotationMetadata.introspect(beanClass);
}
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
if (metadata instanceof StandardAnnotationMetadata) {
setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
} else {
setBeanClassName(metadata.getClassName());
}
this.metadata = metadata;
}
public AnnotatedGenericBeanDefinition(
AnnotationMetadata metadata,
MethodMetadata factoryMethodMetadata) {
this(metadata);
setFactoryMethodName(factoryMethodMetadata.getMethodName());
this.factoryMethodMetadata = factoryMethodMetadata;
}
@Override
public final AnnotationMetadata getMetadata() {
return this.metadata;
}
@Override
public final MethodMetadata getFactoryMethodMetadata() {
return this.factoryMethodMetadata;
}
}
Spring中使用BeanDefinition示例
注冊componentClasses
AnnotationConfigApplicationContext啟動代碼:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(ServiceConfig.class);
applicationContext.refresh();
AnnotationConfigApplicationContext在啟動時可以使用register方法注冊@Configuration類,本小節將從這個方法入手看一個BeanDefinition的使用示例:
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
// reader.register(...)
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
private <T> void doRegisterBean(Class<T> beanClass, String name,
Class<? extends Annotation>[] qualifiers, Supplier<T> supplier,
BeanDefinitionCustomizer[] customizers) {
// 構造方法中會決議AnnotationMetadata元資料
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 判斷是否允許裝配
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = https://www.cnblogs.com/xugf/p/this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 決議Lazy,Primary,DependsOn,Role等屬性
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 處理Scope的proxyMode
definitionHolder = AnnotationConfigUtils
.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注冊到容器
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
// BeanDefinitionReaderUtils.registerBeanDefinition(...)
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 將Bean注冊到BeanDefinitionRegistry
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
此處的registry是AnnotationConfigApplicationContext物件,registerBeanDefinition方法的實作在GenericApplicationContext類:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
// beanFactory.registerBeanDefinition(...)
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
} else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
} else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
@Bean注解
@Bean注解注入的Bean最終在ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForBeanMethod方法注冊BeanDefinition:
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = https://www.cnblogs.com/xugf/p/beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// Do we need to mark the bean as skipped by its condition?
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
// Consider name and any aliases
List 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);
}
// Has this effectively been overridden before (e.g. via XML)?
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
return;
}
// 創建ConfigurationClassBeanDefinition
// 是RootBeanDefinition的子類
ConfigurationClassBeanDefinition beanDef =
new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
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 {
// instance @Bean method
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
if (metadata instanceof StandardMethodMetadata) {
beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
}
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
// Consider scoping
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;
}
}
// Replace the original bean definition with the target one, if necessary
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);
}
@ComponentScan注解
支持@ComponentScan注解的最終邏輯在ClassPathScanningCandidateComponentProvider類的scanCandidateComponents方法中:
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (resource.isReadable()) {
try {
// 此處獲取到的是SimpleMetadataReader物件,
// 內部使用ASM決議.class檔案封裝AnnotationMetadata物件
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 判斷是一個Component
if (isCandidateComponent(metadataReader)) {
// 創建ScannedGenericBeanDefinition物件
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
}
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556581.html
標籤:Java
下一篇:返回列表