Spring Framework 源码阅读(二):BeanDefinition的作用
上一篇Spring Framework
源码阅读博客,博主介绍了Aware
接口及其实现类的作用,Aware
的设计模式是模板模式,而BeanDefinition
的设计模式也是模板模式,它们都基于某种职责定义了一个模板,符合开闭原则,对扩展开放,对修改关闭,扩展在子类中实现。
- Spring Framework 源码阅读(一):Aware接口及其实现类的作用
- 设计模式-模板模式(Template Pattern)
- 设计模式的七大原则
BeanDefinition
接口的定义
package org.springframework.beans.factory.config;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
/**
* A BeanDefinition describes a bean instance, which has property values,
* constructor argument values, and further information supplied by
* concrete implementations.
* * <p>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.
* * @author Juergen Hoeller
* @author Rob Harrop
* @since 19.03.2004
* @see ConfigurableListableBeanFactory#getBeanDefinition
* @see org.springframework.beans.factory.support.RootBeanDefinition
* @see org.springframework.beans.factory.support.ChildBeanDefinition
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
...
}
-
BeanDefinition
描述bean
实例,比如bean
实例具有的属性值、构造函数参数值以及由具体实现提供的进一步信息。 - 主要目的是允许
BeanFactoryPostProcessor
检查和修改属性值以及其他bean
元数据,BeanFactoryPostProcessor
博主以后会进行介绍,不然会涉及到很多其他知识,显得杂乱无章,要尽量遵守单一职责原则。
为什么需要BeanDefinition
?这就要讨论Java
对象和bean
有什么不同,很显然bean
也是Java
对象,但它拥有Java
对象所没有的功能,它可以在Spring
容器中很容易实现自动注入、懒加载、多种作用域和根据各种限定条件进行初始化等,Java
中的类可以描述该类实例的属性和行为,因此bean
也需要有描述它附加功能的定义,不然它只是一个Java
对象而已,这就是BeanDefinition
的作用,从接口的命名也可看出来。
BeanDefinition
接口的方法和属性:
属性
-
SCOPE_SINGLETON
:bean
的单例作用域,把bean
设置为单例作用域时,Spring
容器只会创建该bean
的唯一实例。这个单一实例会被存储到单例缓存(singleton cache
)中,并且所有针对该bean
的后续请求和引用都将返回被缓存的对象实例。 -
SCOPE_PROTOTYPE
:bean
的原型作用域,把bean
设置为原型作用域时,每次对bean
的请求(将其注入到另一个bean
中,或者以程序的方式调用容器的getBean()
方法)时Spring
容器都会创建一个新的bean
实例。bean
的其他作用域(request
、session
、globalSession
)需要在Web
环境中才能使用,以后博主再进行详细介绍。 -
ROLE_APPLICATION
:bean
的角色指示,指示该BeanDefinition
是应用程序的主要部分。通常对应于用户定义的bean
。 -
ROLE_SUPPORT
:bean
的角色指示,指示该BeanDefinition
是某些配置(通常是外部的ComponentDefinition
)的支撑部分。 -
ROLE_INFRASTRUCTURE
:bean
的角色指示,指示该BeanDefinition
完全提供后台角色,与终端用户无关。
方法
-
setParentName
、getParentName
:设置和获取父BeanDefinition
名称的方法,为了描述bean
之间的继承关系,BeanDefinition
也有父子关系,之后会介绍到合并BeanDefinition
的概念。 -
setBeanClassName
、getBeanClassName
:设置和获取bean
的类名。 -
setScope
、getScope
:设置和获取bean
的作用域。 -
setLazyInit
、isLazyInit
:设置bean
为懒加载、判断bean
是否为懒加载。 -
setDependsOn
、getDependsOn
:设置和获取bean
所依赖的bean
的名称数组(保证首先初始化这些bean
)。 -
setAutowireCandidate
、isAutowireCandidate
:AutowireCandidate
表示bean
是否是自动注入到其他bean
的候选。仅影响基于类型(byType
)的自动注入。它不会影响按名称(byName
)的显式引用,即使指定的bean
未标记为autowire
候选,也会解析为显式引用。因此,如果名称匹配,会按名称自动注入bean
。 -
setPrimary
、isPrimary
:设置和判断bean
是否是自动注入到其他bean
的首选。 -
setFactoryBeanName
、getFactoryBeanName
:FactoryBean
和BeanFactory
是不一样的概念,FactoryBean
也是bean
,不过它可以用于创建某一类型的bean
(所有是一个factory
,也是一个bean
),因此借助FactoryBean
可以定制化创建bean
的过程。这两个方法就是设置和获取bean
的FactoryBeanName
(可以为null
)。 -
setFactoryMethodName
、getFactoryMethodName
:FactoryBean
通过FactoryMethod
来创建某一类型的bean
。这两个方法就是设置和获取bean
的FactoryMethod
(可以为null
)。 -
getConstructorArgumentValues
、hasConstructorArgumentValues
:获取bean
的构造器参数值、判断bean
是否有构造器参数值。 -
getPropertyValues
、hasPropertyValues
:获取要应用于bean
的新实例的属性值、判断是否有要应用于bean
的新实例的属性值。 -
setInitMethodName
、getInitMethodName
:设置和获取bean
初始化方法的名称。 -
setDestroyMethodName
、getDestroyMethodName
:设置和获取bean
销毁方法的名称。 -
setRole
、getRole
:设置和获取bean
的角色。 -
setDescription
、getDescription
:设置和获取BeanDefinition
的human-readable description
(便于人类阅读的描述)。 -
getResolvableType
:基于BeanDefinition
或其他特定元数据,返回该BeanDefinition
的可解析类型。这通常在运行时合并的BeanDefinition
(下面会进行介绍)上完全解析,但不一定在配置时定义的实例上完全解析。 -
isSingleton
、isPrototype
:判断bean
是否是单例、原型bean
。 -
isAbstract
:判断bean
是否是abstract
,如果是abstract
就不需要实例化了。 -
getResourceDescription
:获取BeanDefinition
来自的Resource
的描述(用于在出现错误时显示上下文)。 -
getOriginatingBeanDefinition
:返回原始的BeanDefinition
,如果没有,则返回null
。
BeanDefinition
接口还继承了AttributeAccessor
接口和BeanMetadataElement
接口。
-
AttributeAccessor
接口:定义了通用的接口,用于向任意对象附加元数据或从任意对象访问元数据。 -
BeanMetadataElement
接口:由携带配置源对象的bean
元数据元素实现的接口。
使用这些定义来描述bean
实例,而具体实现下放到子类中,比如AbstractBeanDefinition
、ChildBeanDefinition
、RootBeanDefinition
以及GenericBeanDefinition
,接下来博主会详细介绍它们的作用。
AbstractBeanDefinition
之前介绍过BeanDefinition
的设计模式是模板模式,AbstractBeanDefinition
抽象类实现了BeanDefinition
接口中的通用方法。
@SuppressWarnings("serial")
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
...
}
AbstractBeanDefinition
是具体、完备的BeanDefinition
基类,并且分解出了GenericBeanDefinition
、RootBeanDefinition
和ChildBeanDefinition
的公共属性。
通用方法的实现:
/**
* 指定bean定义的bean类名
*/
@Override
public void setBeanClassName(@Nullable String beanClassName) {
this.beanClass = beanClassName;
}
/**
* 返回bean定义的bean类名
*/
@Override
@Nullable
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
}
/**
* 设置bean的作用域
*/
@Override
public void setScope(@Nullable String scope) {
this.scope = scope;
}
/**
* 返回bean的作用域名称
*/
@Override
@Nullable
public String getScope() {
return this.scope;
}
/**
* 是否是单例bean
*/
@Override
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(this.scope) || SCOPE_DEFAULT.equals(this.scope);
}
/**
*是否是原型bean
*/
@Override
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(this.scope);
}
/**
* 是否是abstract,如果是就不会进行实例化
*/
@Override
public boolean isAbstract() {
return this.abstractFlag;
}
/**
* 设置bean的加载方式为懒加载
*/
@Override
public void setLazyInit(boolean lazyInit) {
this.lazyInit = lazyInit;
}
/**
* 判断bean是否设置懒加载
*/
@Override
public boolean isLazyInit() {
return (this.lazyInit != null && this.lazyInit.booleanValue());
}
...
也添加了新的属性和方法,涉及到autowire
(装配bean
的属性):
/**
* 表示没有自动装配的常量
*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
/**
* 表示按名称自动装配bean属性的常量
*/
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
/**
* 表示按类型自动装配bean属性的常量
*/
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
/**
* 表示通过构造函数自动装配bean属性的常量
*/
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
* 表示通过bean类的内部检测来确定适当的自动装配策略的常量
*/
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
/**
* 设置自动装配模式
*/
public void setAutowireMode(int autowireMode) {
this.autowireMode = autowireMode;
}
/**
* 返回自动装配模式
*/
public int getAutowireMode() {
return this.autowireMode;
}
/**
* 返回已解析的自动装配模式编码
*/
public int getResolvedAutowireMode() {
if (this.autowireMode == AUTOWIRE_AUTODETECT) {
// 确定是应用setter自动装配还是构造函数自动装配
// 如果它有一个无参数构造函数,则被视为setter自动装配
// 否则将尝试构造函数自动装配
Constructor<?>[] constructors = getBeanClass().getConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 0) {
return AUTOWIRE_BY_TYPE;
}
}
return AUTOWIRE_CONSTRUCTOR;
}
else {
return this.autowireMode;
}
}
...
涉及到dependency check
(依赖项检查):
/**
* 表示没有依赖项检查的常量
*/
public static final int DEPENDENCY_CHECK_NONE = 0;
/**
* 表示对象引用的依赖项检查的常量
*/
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
/**
* 表示“简单”属性的依赖项检查的常量
*/
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
/**
* 表示所有属性的依赖项检查的常量
*/
public static final int DEPENDENCY_CHECK_ALL = 3;
...
/**
* 设置依赖项检查的编码,就是上面的0、1、2以及3
*/
public void setDependencyCheck(int dependencyCheck) {
this.dependencyCheck = dependencyCheck;
}
/**
* 返回当前依赖项检查的编码
*/
public int getDependencyCheck() {
return this.dependencyCheck;
}
涉及到qualifier
(限定符):
/**
* 注册一个用于autowire候选解析的限定符。
*/
public void addQualifier(AutowireCandidateQualifier qualifier) {
this.qualifiers.put(qualifier.getTypeName(), qualifier);
}
/**
* 返回bean是否具有指定的限定符
*/
public boolean hasQualifier(String typeName) {
return this.qualifiers.containsKey(typeName);
}
/**
* 返回映射到提供的类型名称的限定符
*/
@Nullable
public AutowireCandidateQualifier getQualifier(String typeName) {
return this.qualifiers.get(typeName);
}
/**
* 返回所有的限定符。
*/
public Set<AutowireCandidateQualifier> getQualifiers() {
return new LinkedHashSet<>(this.qualifiers.values());
}
/**
* 将限定符从提供的AbstractBeanDefinition复制到此AbstractBeanDefinition
*/
public void copyQualifiersFrom(AbstractBeanDefinition source) {
Assert.notNull(source, "Source must not be null");
this.qualifiers.putAll(source.qualifiers);
}
这些都是AbstractBeanDefinition
中新增加的内容(基于特定业务的抽象),当然这些还不是AbstractBeanDefinition
的全貌,大家可以自己去探索一下。接下来会介绍AbstractBeanDefinition
三个比较重要的子类ChildBeanDefinition
、RootBeanDefinition
以及GenericBeanDefinition
。
ChildBeanDefinition
子Bean
(继承了父Bean
)的BeanDefinition
。子BeanDefinition
对父BeanDefinition
有固定的依赖关系。
子BeanDefinition
将从父BeanDefinition
继承构造函数参数值、属性值和方法重写,并具有添加新值的选项。如果指定了init method
、destroy method
或static factory method
,它们将覆盖相应父BeanDefinition
的设置。其余设置将始终取自子BeanDefinition
:depends on
、autowire mode
、dependency check
、singleton
以及lazy init
。
自Spring2.5
以来,以编程方式注册BeanDefinition
的首选方法是GenericBeanDefinition
类,它允许通过setParentName
方法动态定义父依赖项。对于大多数用例,这有效地取代了ChildBeanDefinition
类。因此这里不会详细地介绍ChildBeanDefinition
,它的源码也比较短,大家可以自己去看看。
RootBeanDefinition
RootBeanDefinition
表示在运行时支持Spring BeanFactory
中特定bean
的合并BeanDefinition
。它可能是从相互继承的多个原始BeanDefinition
创建的(通常注册为GenericBeanDefinition
)。RootBeanDefinition
本质上是运行时的统一BeanDefinition
视图。
RootBeanDefinition
也可用于在配置阶段注册单个BeanDefinition
。然而,自Spring2.5
以来,以编程方式注册BeanDefinition
的首选方法是GenericBeanDefinition
类。GenericBeanDefinition
的优点是它允许动态定义父依赖项,而不是将角色硬编码(hard-coding
)为RootBeanDefinition
。
GenericBeanDefinition
GenericBeanDefinition
是标准BeanDefinition
的一站式服务。与任何BeanDefinition
一样,它允许指定类以及可选的构造函数参数值和属性值。可以灵活地配置parentName
属性,以便从父BeanDefinition
中进行派生。通常,使用GenericBeanDefinition
类注册用户可见的BeanDefinition
。在父子关系恰好是预先确定的情况下,使用RootBeanDefinition
和ChildBeanDefinition
。
代码也很短:
创建module
先在Spring Framework
源码中增加一个application module
,这在之前的博文中已经介绍过了,这里就不再赘述:
- 编译 Spring Framework 5.2.17源码 & 在源码中使用 ApplicationContext 获取定义的Bean
IMessageService
接口:
package com.kaven.service;
/**
* @Author: ITKaven
* @Date: 2021/09/25 14:04
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
public interface IMessageService {
String getMessage();
}
MessageServiceImpl
实现类:
package com.kaven.service.impl;
import com.kaven.service.IMessageService;
import org.springframework.stereotype.Service;
/**
* @Author: ITKaven
* @Date: 2021/09/25 14:05
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@Service("message")
public class MessageServiceImpl implements IMessageService {
@Override
public String getMessage() {
return "Hello Kaven";
}
}
Application
启动类:
package com.kaven;
import com.kaven.service.IMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @Author: ITKaven
* @Date: 2021/09/25 13:54
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@ComponentScan({"com.kaven"})
public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);
IMessageService messageServiceBean = (IMessageService) applicationContext.getBean("message");
System.out.println(messageServiceBean.getMessage());
Test test = (Test) applicationContext.getBean("test");
System.out.println("message bean: " + (test.messageService == messageServiceBean));
Test test2 = (Test) applicationContext.getBean("test");
System.out.println("message bean: " + (test2.messageService == messageServiceBean));
System.out.println("test bean: " + (test == test2));
System.out.println(applicationContext.getBeanDefinitionCount());
Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
}
@Component("test")
@Scope("prototype")
static class Test {
@Autowired
private IMessageService messageService;
}
}
运行输出:
> Task :application:Application.main()
Hello Kaven
message bean: true
message bean: true
test bean: false
7
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
test
message
BUILD SUCCESSFUL in 19s
61 actionable tasks: 2 executed, 59 up-to-date
源码分析 - 注册BeanDefinition
上下文中有7
个BeanDefinition
,而test bean
被获取了两次,为什么没有两个test BeanDefinition
?因为每个BeanDefinition
描述了一类bean
,并且BeanDefinition
是根据beanName
获取的,BeanDefinition
类似于类(对象定义),而bean
类似于对象,所以beanName
就类似于className
,类描述了该类所有对象的行为和属性,BeanDefinition
也是如此。从输出结果上来看,bean
默认是单例(除非使用@Scope
注解改变其作用域),其实在AbstractBeanDefinition
的源码中也可以发现作用域的默认值。
@SuppressWarnings("serial")
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
/**
* 默认作用域名称的常量:"",等同于单例状态(会被替换为单例,在相关源码的注释中有解释)
*/
public static final String SCOPE_DEFAULT = "";
@Nullable
private String scope = SCOPE_DEFAULT;
...
}
AbstractBeanDefinition
的源码中还有一些比较常见配置的默认值,比如bean
默认不是abstract
的(因此需要被实例化)、lazyInit
为null
(因此不会被懒加载)、没有自动装配、依赖项检查为DEPENDENCY_CHECK_NONE
(没有依赖项检查)、是自动注入的候选bean
和不是首选bean
(primary
):
private boolean abstractFlag = false;
@Nullable
private Boolean lazyInit;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
private boolean autowireCandidate = true;
private boolean primary = false;
很显然下面这4
个BeanDefinition
是Spring
定义的:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
它们在AnnotationConfigUtils
抽象类的registerAnnotationConfigProcessors
方法中出现:
public abstract class AnnotationConfigUtils {
/**
* 内部管理Configuration注解的处理器的bean名称
*/
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
/**
* 内部管理Autowired注解的处理器的bean名称
*/
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
/**
* 内部管理JSR-250注解的处理器的bean名称
*/
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
/**
* 内部管理JPA注解的处理器的bean名称
*/
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
/**
* 内部管理EventListener注解的处理器的bean名称
*/
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
"org.springframework.context.event.internalEventListenerProcessor";
/**
* 内部管理EventListenerFactory的bean名称
*/
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";
/**
* 在给定registry中注册所有相关的注解post processors
* @param registry 要在其上操作的registry
* @param source 触发此注册的配置源元素(已提取),可能为null
* @return Set<BeanDefinitionHolder>,其中包含此调用实际注册的所有BeanDefinition
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
...
}
其实这个BeanDefinitionRegistry registry
参数就是博主在Application
类中创建的AnnotationConfigApplicationContext
实例。并且这里定义的BeanDefinition
是RootBeanDefinition
实例(RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
,博主在后面会进行讨论)。
AnnotationConfigApplicationContext
类的父类GenericApplicationContext
实现了BeanDefinitionRegistry
接口。
下一步调用了AnnotationConfigUtils
抽象类的的registerPostProcessor
方法(可以看见role
设置为ROLE_INFRASTRUCTURE
):
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
之后又调用了GenericApplicationContext
类的registerBeanDefinition
方法,很显然是AnnotationConfigApplicationContext
类继承了父类GenericApplicationContext
的registerBeanDefinition
方法。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
GenericApplicationContext
类的beanFactory
属性是DefaultListableBeanFactory
类的实例。
private final DefaultListableBeanFactory beanFactory;
DefaultListableBeanFactory
类是Spring
默认实现的ConfigurableListableBeanFactory
和BeanDefinitionRegistry
接口:一个基于bean definition
元数据的成熟bean factory
。
先不纠结这些类的作用,类太多了,无法把所有类的作用和原理都理解的一清二楚,需要关注的是DefaultListableBeanFactory
类中的beanDefinitionMap
和beanDefinitionNames
属性,很显然它们存储了beanName
以及相关BeanDefinition
实例的信息。
/** BeanDefinition对象的映射,bean名称为key */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** 按注册顺序列出BeanDefinition名称 */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
下一步调用了DefaultListableBeanFactory
类中的registerBeanDefinition
方法,在该方法中,将beanName
和beanDefinition
信息存储到了beanDefinitionMap
和beanDefinitionNames
属性中:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
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);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
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();
}
}
这4
个内置bean
的BeanDefinition
就完成了注册。
为什么会注册这些内置bean
?可以看一下调用链:
先是在main
方法中调用了AnnotationConfigApplicationContext
类的构造函数:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
又接着调用了AnnotationConfigApplicationContext
类的无参构造函数:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
然后连续调用了AnnotatedBeanDefinitionReader
类的两个构造函数:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
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.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
从这里就开始注册内置bean
的BeanDefinition
了。
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
接着会注册application bean
的BeanDefinition
,调用链如下图所示:
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
在调用链的doRegisterBean
方法中可以发现application bean
的BeanDefinition
是AnnotatedGenericBeanDefinition
(GenericBeanDefinition
的子类)实例,明显和内置bean
的RootBeanDefinition
实例不一样。
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
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);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
可以回顾一下博主对RootBeanDefinition
的介绍:
RootBeanDefinition
表示在运行时支持Spring BeanFactory
中特定bean
的合并BeanDefinition
。RootBeanDefinition
本质上是运行时的统一BeanDefinition
视图。
RootBeanDefinition
也可用于在配置阶段注册单个BeanDefinition
。然而,自Spring2.5
以来,以编程方式注册BeanDefinition
的首选方法是GenericBeanDefinition
类。
博主的理解:因为内置bean
没有父bean
,继承关系是明确的,因此内置bean
的BeanDefinition
也不会有父BeanDefinition
,也就不需要进行合并BeanDefinition
的操作,此时的BeanDefinition
就是内置bean
的统一BeanDefinition
视图,所以可以直接是RootBeanDefinition
实例。
而application bean
是用户自定义的bean
,继承关系并不明确,是有可能存在继承关系的,因此有可能需要进行合并BeanDefinition
的操作,此时的BeanDefinition
就不一定是application bean
的统一BeanDefinition
视图,因此定义为AnnotatedGenericBeanDefinition
实例,以便之后可以进行合并BeanDefinition
的操作(通过设置parentName
)。而什么时候会进行合并BeanDefinition
的操作,下面会进行介绍。
test
以及message bean
的BeanDefinition
都是在如下图所示的调用链中被定义:
现在所有bean
的BeanDefinition
都被注册了,下面介绍合并BeanDefinition
。
源码分析 - 合并BeanDefinition
合并BeanDefinition
的操作,在bean
需要实例化之前会被执行,如AbstractBeanFactory
抽象类的doGetBean
方法(删除了不相关的代码):
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
}
接着调用了AbstractBeanFactory
抽象类的getMergedLocalBeanDefinition
方法:
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
AbstractBeanFactory
抽象类的mergedBeanDefinitions
属性是一个ConcurrentHashMap
实例,存储了以bean
名称为key
,合并的RootBeanDefinition
为value
的键值对。
/** 从bean名称映射到合并的RootBeanDefinition */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
RootBeanDefinition
类中的stale
属性,使用volatile
修饰符修饰,保证了可见性。
/** 确定是否需要重新合并BeanDefinition */
volatile boolean stale;
如果之前没有合并过,或者需要重新合并,就会调用AbstractBeanFactory
抽象类的getMergedBeanDefinition
方法,而先会调用DefaultListableBeanFactory
类的getBeanDefinition
方法获取beanName
对应的BeanDefinition
:
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
通过源码,其实可以发现该this
(DefaultListableBeanFactory
实例)就是之前说的在main
方法中创建的AnnotationConfigApplicationContext
实例的beanFactory
属性。
在调用AbstractApplicationContext
类的refresh
方法时,将AnnotationConfigApplicationContext
实例的beanFactory
属性传进去了(删除了部分代码):
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
}
}
因此调用DefaultListableBeanFactory
类的getBeanDefinition
方法就是获取之前定义的BeanDefinition
(通过beanName
,内置bean
对应RootBeanDefinition
实例,而自定义bean
对应GenericBeanDefinition
实例)。
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
获取beanName
对应的BeanDefinition
后,返回到AbstractBeanFactory
抽象类的getMergedBeanDefinition
方法(方法命名相同,和之前不是一样的方法):
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
又继续调用AbstractBeanFactory
抽象类的getMergedBeanDefinition
方法(方法命名相同,和之前不是一样的方法):
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
// 合并BeanDefinition时需要上锁,避免发生线程安全问题
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 没有合并过或者需要重新合并BeanDefinition
if (mbd == null || mbd.stale) {
previous = mbd;
// 没有父BeanDefinition,不需要合并,将原有的BeanDefinition拷贝即可
if (bd.getParentName() == null) {
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
// 非RootBeanDefinition实例,可能是GenericBeanDefinition类或其子类的实例
else {
mbd = new RootBeanDefinition(bd);
}
}
// 有父BeanDefinition,需要合并
else {
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 合并父BeanDefinition
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
// 合并父BeanDefinition
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// 将合并的父BeanDefinition转换成RootBeanDefinition实例
mbd = new RootBeanDefinition(pbd);
// 子BeanDefinition重写合并的父BeanDefinition得到合并的子BeanDefinition
mbd.overrideFrom(bd);
}
// 作用域为""时(默认),会被替代为SCOPE_SINGLETON(单例),和上面说的对应起来了
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 非单例bean中包含的bean本身不能是单例bean
// 更正这个问题,因为这可能是外部bean的父子合并,在这种情况下,原始内部BeanDefinition将不会继承合并的外部bean的单例状态。
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// 暂时缓存合并的BeanDefinition
// 以后可能会重新合并,以获取元数据更改
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
可见合并的BeanDefinition
默认就是RootBeanDefinition
实例,这也就是为什么说RootBeanDefinition
本质上是运行时的统一BeanDefinition
视图的原因了。该方法通过递归调用的形式合并BeanDefinition
,这也符合bean
之间的继承关系图。
合并BeanDefinition
之后,就能知道bean
的所有配置信息,就可以进行bean
的实例化了。
阅读源码需要耐心,一步步进行Debug
,每个人的理解不同,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。