知识要点:
Spring启动流程概述
Spring启动流程详解
Spring启动流程概述
Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段:
- 容器启动阶段
- Bean实例化阶段
容器初始化
- 加载配置
- 分析配置信息
- 将Bean信息装配到BeanDefinition
- 将Bean信息注册到相应的BeanDefinitionRegistry
- 其他后续处理
容器实例化
- 根据策略实例化对象
- 装配依赖
- Bean初始化前处理
- 对象初始化
- 对象其他处理
- 注册回调接口
Spring启动流程详解
启动流程源码概览
ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
// 方法加锁避免多线程同时刷新Spring上下文
synchronized (this.startupShutdownMonitor) {
// 准备上下文刷新
prepareRefresh();
// 告诉子类刷新内部的beanFactory返回新的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 在当前上下文中准备要beanFactory
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对beanFactory进行后置处理
postProcessBeanFactory(beanFactory);
// 在上下文中将BeanFactory处理器注册为Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean处理器用于拦截Bean的创建
registerBeanPostProcessors(beanFactory);
// 在上下文中初始化国际化信息
initMessageSource();
// 在上下文中初始化event multicaster(事件多播器)
initApplicationEventMulticaster();
// 在指定的上下文子类中初始化其他指定的beans
onRefresh();
// 检查并注册事件监听
registerListeners();
// 实例化所有剩余的(非延迟初始化)单例
finishBeanFactoryInitialization(beanFactory);
// 最后一步:发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 如果出现异常则销毁已创建的单例
destroyBeans();
// 重置活动标志。
cancelRefresh(ex);
// 将异常传递给调用者
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
整个refresh()的代码都是同步的,而对应的同步对象是startupShutdownMonitor。startupShutdownMonitor只在refresh()和close()两个方法里被用到,而它是用来同步applicationContext的刷新和销毁。
面试题
Spring的registerShutdownHook和close有什么区别?
当close()
被调用时会立即关闭或者停止ApplicationContext;而调用registerShutdownHook()
将在稍后JVM关闭时关闭或停止ApplicationContext,该方法主要通过JVM ShutdownHook
来实现。
ShutdownHook
Java 语言提供一种 ShutdownHook(钩子)机制,当 JVM 接受到系统的关闭通知之后,调用 ShutdownHook 内的方法,用以完成清理操作,从而实现平滑退出应用。
第一步 刷新准备
protected void prepareRefresh() {
// 设置启动时间。当前毫秒数代表当前applicationContext的创建时间
this.startupDate = System.currentTimeMillis();
// 设置容器关闭标志
this.closed.set(false);
// 设置启动标志
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化属性资源
initPropertySources();
// 验证所有的属性是否都是可解析的
getEnvironment().validateRequiredProperties();
// ApplicationEvent初始化
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
第二步 获取BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
该方法对BeanFactory进行刷新。如果刷新前已经存在一个BeanFactory则需要先进行关闭操作,而后初始化一个新BeanFactory。
protected final void refreshBeanFactory() throws BeansException {
// 判断是否已经存在一个BeanFactory
if (hasBeanFactory()) {
// 销毁已经存在BeanFactory中的所有Bean
destroyBeans();
// 关闭BeanFactory
closeBeanFactory();
}
try {
// 创建新的BeanFactory对象(DefaultListableBeanFactory)
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 给BeanFactory设置Id
beanFactory.setSerializationId(getId());
// 该方法主要对2个标志进行设置:allowBeanDefinitionOverriding和allowCircularReferences
// allowBeanDefinitionOverriding:是否允许使用相同名称重新注册不同的bean(Spring默认true,SpringBoot默认false)
// allowCircularReferences:是否允许循环依赖
customizeBeanFactory(beanFactory);
// 加载配置文件
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 新创建的BeanFactory赋给成员变量beanFactory
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
DefaultSingletonBeanRegistry
// 当前这个单例是否正在被销毁
// true:表示单例已经执行了destroy方法,或者出现异常时执行了destroySingleton方法
private boolean singletonsCurrentlyInDestruction = false;
// 缓存两个Bean之间的包含关系。如:一个Bean中包含了一个内部Bean。
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>(16);
// 缓存Bean与其他依赖Bean的关系
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64);
// 缓存被依赖Bean与其他依赖Bean的关系
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64);
// 销毁所有的Bean实例
public void destroySingletons() {
if (logger.isDebugEnabled()) {
logger.debug("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
// 设置销毁标志
this.singletonsCurrentlyInDestruction = true;
}
// 销毁disposableBeans缓存中所有单例bean
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
// 清空包含关系
this.containedBeanMap.clear();
// 清空依赖和被依赖关系
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
// 清空缓存
clearSingletonCache();
}
加载配置
加载配置文件时序图AbstractXmlApplicationContext
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 以Resource方式加载配置
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 读取配置文件
reader.loadBeanDefinitions(configResources);
}
// 以String方式加载配置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 读取配置文件
reader.loadBeanDefinitions(configLocations);
}
}
AbstractBeanDefinitionReader
@Override
// 通过String数组参数locations加载Bean,并返回加载Bean的数量
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
for (String location : locations) {
// 加载BeanDefinintion
counter += loadBeanDefinitions(location);
}
// 返回加载Bean的数量
return counter;
}
@Override
// 通过Resource数组参数locations加载Bean,并返回加载Bean的数量
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
// 加载BeanDefinintion
counter += loadBeanDefinitions(resource);
}
// 返回加载Bean的数量
return counter;
}
XmlBeanDefinitionReader
// 从配置文件中加载Bean
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource);
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 将Resource资源转化为输入流InputStream
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 执行加载Bean的过程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
// 加载Bean的函数
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 加载XML文件,构造XML Document对象
Document doc = doLoadDocument(inputSource, resource);
// 注册Bean
return registerBeanDefinitions(doc, resource);
}
// 抛出各种异常
......
}
Bean的解析与注册
加载到解析时序图DefaultBeanDefinitionDocumentReader
// XML配置文件中beans元素
public static final String NESTED_BEANS_ELEMENT = "beans";
// XML配置文件中alias别名元素
public static final String ALIAS_ELEMENT = "alias";
// XML配置文件中name属性
public static final String NAME_ATTRIBUTE = "name";
// XML配置文件中alias属性
public static final String ALIAS_ATTRIBUTE = "alias";
// XML配置文件中import元素
public static final String IMPORT_ELEMENT = "import";
// XML配置文件中resource属性
public static final String RESOURCE_ATTRIBUTE = "resource";
// XML配置文件中profile属性
public static final String PROFILE_ATTRIBUTE = "profile";
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
// 创建Bean解析代理工具类
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
// 解析profile属性
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
// 解析XML并执行Bean注册
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// root根节点是默认标签
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
// 遍历XML Document的每个节点
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析默认标签
parseDefaultElement(ele, delegate);
}
else {
// 解析自定义标签
delegate.parseCustomElement(ele);
}
}
}
}
// root根节点是自定义标签
else {
delegate.parseCustomElement(root);
}
}
// 解析XML配置文件的节点元素
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 如果是Import元素
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// 如果是Alias别名元素
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 如果是Bean元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 如果是嵌套Bean元素(Beans)
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
Import解析
虽然每个单独的XML配置文件都代表体系结构中的逻辑层或模块,但我们可以从多个XML片段中加载Bean定义。如项目中有多个Resource位置,可以使用一个或多个<import />从另外的XML文件中加载Bean定义。
标签用法示例:
<import resource="applicationDao.xml" />
<import resource="applicationService.xml" />
解析标签的源码:
DefaultBeanDefinitionDocumentReader
protected void importBeanDefinitionResource(Element ele) {
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// 解析路径和占位符
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
// 解析好的资源要放到Set里面
Set<Resource> actualResources = new LinkedHashSet<Resource>(4);
// 解析location是相对路径还是绝对路径
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
// 如果是绝对路径
if (absoluteLocation) {
try {
// 直接根据路径加载相应的配置文件
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {
try {
int importCount;
// 如果是相对路径,则先根据路径得到Resource
Resource relativeResource = getReaderContext().getResource().createRelative(location);
// 如果Resource存在
if (relativeResource.exists()) {
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
else {
// Resource类解析不成功,在classpath路径中去加载。如果没有则抛出异常
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
Alias别名注册
每个bean具有一个或多个标识符。这些标识符在承载Bean的容器内必须是唯一的。 Bean通常只有一个标识符,但是如果需要多个标识符,则多余的标识符可以被视为别名。
标签用法示例:
<alias name="dataSource" alias="systemA-dataSource"/>
<alias name="dataSource" alias="systemB-dataSource"/>
在Bean定义中,可以通过使用id属性最多指定的一个名称,同时可以通过name属性中定义任意数量的其他名称来为Bean提供多个名称。但在定义Bean的地方指定所有别名可能并不能满足需求,有时需要在其他地方为Bean定义别名。
解析标签的源码:
SimpleAliasRegistry
// 存放别名的缓存
private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>
// 根据Bean的别名进行注册
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
synchronized (this.aliasMap) {
// 如果别名和名字相同
if (alias.equals(name)) {
this.aliasMap.remove(alias);
}
else {
// 如果别名和名字不相同,根据别名获取Bean名称
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
// 如果缓存中已经存在该别名,不需要注册到缓存
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
// 如果不允许相同的Bean使用不同的名称则抛出异常
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
}
// 对别名进行循环检查
checkForAliasCircle(name, alias);
// 把别名放入别名缓存
this.aliasMap.put(alias, name);
}
}
}
// 别名循环检查
public boolean hasAlias(String name, String alias) {
for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
// 获取Bean注册名
String registeredName = entry.getValue();
// 判断name参数和Bean注册名是否相同
if (registeredName.equals(name)) {
// 获取别名
String registeredAlias = entry.getKey();
// 判断别名是否相同
// 递归调用hasAlias
if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
return true;
}
}
}
return false;
}
别名循环检查:A为名称,B为A的别名,需要注册别名<B, A>
- 检查B是否有别名,如果没有则返回false
- 如果B有别名C,检查C是否与A相同。如果相同返回true,说明有别名循环。如果不相同递归hasAlias(C, B)方法
- 如果C无别名,返回false;如果C有别名D且等于A,返回true。如果不相同继续递归hasAlias(D, B)
Bean注册
Spring会自动检测构造型类,并向容器注册相应的BeanDefinition。
DefaultBeanDefinitionDocumentReader
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析XML中的BeanDefinition元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinitionParserDelegate
基于单一职责的缘故,BeanDefinitionParserDelegate专门负责解析XML元素的工作,而DefaultBeanDefinitionDocumentReader则主要负责读取XML配置文件的职责。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 获取id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
// 获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// 定义别名list
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
// 因为可以多个别名用,所以解析成别名数组
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// beanName默认为id
String beanName = id;
// 如果没有beanName,那么取出别名数组中的第一个作为beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// 生成Bean名
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 生成Bean名
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
// 解析Bean定义不考虑名称或别名。如果在Bean解析过程中产生异常,则返回null
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
// 解析Bean的class属性
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
// 解析parent属性
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 为指定的类名和Parent名称创建一个BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 解析Bean元素的属性并应用于Bean
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 设置Bean的描述信息
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 解析Bean定义的元数据信息(meta以键值对形式存在)
parseMetaElements(ele, bd);
// 解析lookup-method元素
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析replaced-method元素
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析构造函数参数
parseConstructorArgElements(ele, bd);
// 解析property元素
parsePropertyElements(ele, bd);
// 解析qualifier元素
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
BeanDefinitionReaderUtils
该类的主要职责用于生产新的BeanDefiniti实例,给Bean生成一个名称及调用BeanDefinitionRegistry进行Bean的注册。
public static String generateBeanName(
BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
throws BeanDefinitionStoreException {
String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
// 如果有父类,名称为:definition.getParentName() + “$child”
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";
}
// 如果有指定的工厂类,名称为:definition.getFactoryBeanName() + “$created”
else if (definition.getFactoryBeanName() != null) {
generatedBeanName = definition.getFactoryBeanName() + "$created";
}
}
if (!StringUtils.hasText(generatedBeanName)) {
throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
}
String id = generatedBeanName;
if (isInnerBean) {
// 如果是innerBean,名称为
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
}
else {
// 如果不是InnerBean则为顶层Bean,使用简单的类名。计数器加1
int counter = -1;
while (counter == -1 || registry.containsBeanDefinition(id)) {
counter++;
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
}
}
return id;
}
-
parent
Bean定义可以包含许多配置信息,包括容器相关的信息(比如初始化方法,静态工厂方法等等)以及构造函数参数和属性的值。子Bean可以定义从父Bean定义中继承配置数据,而后它可以根据需要覆盖某些值,或添加其他值。使用父子Bean可以节省很多输入工作。 -
lookup-method
lookup-method注入是容器重写Bean上的方法的一种能力,它可以在容器中根据一个Bean的名字返回查找结果。lookup-method通常涉及Prototype Bean。Spring框架通过使用CGLIB来覆盖该方法的子类以实现lookup-method的注入。该功能可用于在一些可插拔的功能上解除依赖。 -
replace-method
用于在运行时调用使用新的方法替换原有的方法,还能动态的改变原有方法的逻辑。
DefaultListableBeanFactory
// 手动注册的单例名称列表
private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
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属性中的methodOverrides校验
// 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 从缓存中根据beanName获取BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 如果BeanDefinition存在并且不允许同名覆盖,则抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + existingDefinition + "] bound.");
}
// Bean的角色检查
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isWarnEnabled()) {
logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
// 如果名字相同,但是BeanDefinition不同打印覆盖日志
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 在缓存中注册Bean
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 检查工厂的Bean创建阶段是否已经开始
if (hasBeanCreationStarted()) {
// 进入创建阶段,此时无法再修改启动时集合元素(为了稳定迭代)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// beanName在manualSingletonNames中,说明是手动注册
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 工厂还未到创建阶段,仍然在注册阶段
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 待注册的Bean的已经在beanDefinitionMap缓存中存在,或者已经存在于单例Bean缓存中
if (existingDefinition != null || containsSingleton(beanName)) {
// 重置给定Bean的所有BeanDefinition缓存,包括从其派生的Bean的缓存
resetBeanDefinition(beanName);
}
}
AbstractBeanFactory
// 保存在至少被创建过一次的beanName
// 如果这个集合中存在beanName,那么说明已经进入了Bean创建阶段
private final Set<String> alreadyCreated =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(256))
网友评论