IOC 容器:BeanDefinition 篇
参考文档:
- Spring 官方文档
- 《Spring 技术内幕:深入解析 Spring 架构与设计原理》
演示代码地址:
https://github.com/xuliangliang1995/grasswort-spring
涉及问题
- 什么是配置元数据(
ConfigurationMetadata
)? - 什么是
BeanDefinition
? BeanDefinition
与配置元数据的关系?包含了哪些配置元数据?- 配置元数据有哪些表现形式?以及相应的载入方式。
配置元信息(ConfigurationMetadata
)
- 什么是配置元数据?
A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container (for example, in the form of XML
<bean/>
definitions).
This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application.
由此可知,配置元数据是指我们提供给 Spring 容器的一些配置信息,其中包含了 Bean
的定义信息,通过这些配置信息,我们可以告诉 Spring 容器如何去实例化、配置以及组装 Bean。
Within the container itself, these bean definitions are represented as
BeanDefinition
objects.
在容器内部,这些 Bean
的定义信息经过封装后表现为一个或多个 BeanDefinition
对象。spring
就是通过解析这些 BeanDefinition
实例来生成所定义的 Bean
实例。
Bean 的定义类(BeanDefinition
)
BeanDefinition
设计意图:
Java Doc 注释:
A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
This is just a minimal interface: The main intention is to allow a {@link
BeanFactoryPostProcessor
} to introspect and modify property values and other bean metadata.
BeanDefinition
是 spring
设计的用来描述一个 Bean
实例的接口。包含了许多关于 Bean
实例的信息。并且 spring
还设计了一个 BeanFactoryPostProcessor
容器后置处理器接口,可以在容器初始化阶段对 BeanDefinition
元数据或属性值进行修改。
-
BeanDefinition
继承关系:
BeanDefinition
是 spring
定义的一个用来描述 bean
实例的接口。它继承了 AttributeAccessor
和 BeanMetadataElement
接口。
AttributeAccessor
要求BeanDefinition
需要具备属性存储的能力。此处的属性并非指对象的Field
,而是近似于一个标签的作用,例如,ConfigurationClass
对应的BeanDefinition
会在容器启动过程中标记一个org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
的属性,来标记为是配置类。BeanMetadataElement
允许BeanDefinition
配置一个类型为Object
的配置源。
BeanDefinition
接口中声明的方法:
/**
* Set the name of the parent definition of this bean definition, if any.
*/
void setParentName(@Nullable String parentName);
/**
* Return the name of the parent definition of this bean definition, if any.
*/
@Nullable
String getParentName();
说明 BeanDefinition
具备父子层级关系,子 BeanDefinition
可以复用父 BeanDefinition
中配置的元数据信息,从而减少不必要的重复配置。
/**
* Specify the bean class name of this bean definition.
* <p>The class name can be modified during bean factory post-processing,
* typically replacing the original class name with a parsed variant of it.
* @see #setParentName
* @see #setFactoryBeanName
* @see #setFactoryMethodName
*/
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
指定 BeanDefinition
对应的 Bean
实例化时所对应的 class
类。
/**
* Override the target scope of this bean, specifying a new scope name.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
void setScope(@Nullable String scope);
@Nullable
String getScope();
scope
为范围的意思,这里我们通常可以理解为作用域。不同作用域的 Bean
获取方式的内部实现策略可能会存在差异。 spring
提供了 singleton
和 prototype
两种常用的作用域,分别对应设计模式中的单例模式和原型模式。
/**
* Set whether this bean should be lazily initialized.
* <p>If {@code false}, the bean will get instantiated on startup by bean
* factories that perform eager initialization of singletons.
*/
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
设置 Bean
是否延迟初始化,如果设置为 true
,在容器对单例对象进行预先初始化时,会跳过该 BeanDefinition
所对应 Bean
的实例化,而是在向容器第一次获取该 Bean
的时候才进行实例化。但如果该 Bean
是别的非延迟加载单例 Bean
的依赖对象时,则在容器对单例对象进行预先初始化是,也会被实例化。
/**
* Set the names of the beans that this bean depends on being initialized.
* The bean factory will guarantee that these beans get initialized first.
*/
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
设置该 Bean
实例所依赖的其他 Bean
, spring
容器会先去初始化所依赖的其他 Bean
。
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
* <p>Note that this flag is designed to only affect type-based autowiring.
* It does not affect explicit references by name, which will get resolved even
* if the specified bean is not marked as an autowire candidate. As a consequence,
* autowiring by name will nevertheless inject a bean if the name matches.
*/
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
设置该 Bean
是否为依赖注入候选者(把当前 Bean
注入到其他 Bean
中)。该属性仅影响基于类型的依赖注入。如果是通过 beanName
来进行依赖注入,则该属性不生效。
/**
* Set whether this bean is a primary autowire candidate.
* <p>If this value is {@code true} for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
void setPrimary(boolean primary);
boolean isPrimary();
设置该 Bean
是否为优先候选者,该属性同样是仅影响基于类型的依赖注入,当存在多个候选者时,会优先选用 primary
为 true
的候选者(只能有一个)。否则系统将会因为无法选定候选者而抛出异常。
/**
* Specify the factory bean to use, if any.
* This the name of the bean to call the specified factory method on.
* @see #setFactoryMethodName
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
/**
* 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.
* @see #setFactoryBeanName
* @see #setBeanClassName
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
setFactoryBeanName
和 setFactoryMethodName
对应设计模式中的工厂模式。 setFactoryBeanName(String factoryBeanName)
指定生产 Bean
的工厂实例,setFactoryMethodName
指定对应的工厂方法名称。
/**
* Return the constructor argument values for this bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the ConstructorArgumentValues object (never {@code null})
*/
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
获取构造参数值,对应类实例化时调用构造函数的参数值。如果是通过工厂方法来生成实例的话,则对应工厂方法的参数值。
/**
* Return the property values to be applied to a new instance of the bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the MutablePropertyValues object (never {@code null})
*/
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
获取所描述Bean
实例的属性值,Mutable
为可修改的意思,获取 MutablePropertyValues
对象后可以对里面的 PropertyValue
进行编辑修改。
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
以上方法分别为设置 Bean
实例的初始化方法,和销毁方法。
void setRole(int role);
int getRole();
设置 Bean
的角色,该方法没有什么功能上的意义。仅用来对 Bean
做一个功能上的标识。
void setDescription(@Nullable String description);
@Nullable
String getDescription();
设置类的描述信息。
/**
* Return a resolvable type for this bean definition,
* based on the bean class or other specific metadata.
* <p>This is typically fully resolved on a runtime-merged bean definition
* but not necessarily on a configuration-time definition instance.
* @return the resolvable type (potentially {@link ResolvableType#NONE})
* @since 5.2
* @see ConfigurableBeanFactory#getMergedBeanDefinition
*/
ResolvableType getResolvableType();
获取该 BeanDefinition
所描述 Bean
的 ResolvableType
。ResolvableType
是 spring
设计的一个支持获取泛型信息的接口,方便泛型操作。
boolean isSingleton();
boolean isPrototype();
/**
* Return whether this bean is "abstract", that is, not meant to be instantiated.
*/
boolean