Spring ioc 初始化流程(源码)
Spring ioc 初始化流程(源码)
- 一 主体流程分析
-
- 1.1 源码时序图
- 1.2 源码分析
-
- 入口Test
- ClassPathXmlApplicationContext
- AbstractApplicationContext
- 1.3 流程小结
- 二 refresh()中 obtainFreshBeanFactory()分析
-
- 2.1 源码时序图
- 2.2 源码分析
-
- 【AbstractApplicationContext-obtainFreshBeanFactory】
- 【AbstractRefreshableApplicationContext-refreshBeanFactory】
- 【AbstractRefreshableApplicationContext-customizeBeanFactory】
- 【AbstractXmlApplicationContext-loadBeanDefinitions】
- 【AbstractRefreshableApplicationContext-getBeanFactory】
- 2.3 源码debug
- 三 obtainFreshBeanFactory()中loadBeanDefinitions()分析
-
- 3.1 源码时序图
- 3.2 前置内容
-
- 【BeanDefinition】
- 【DefaultBeanDefinitionDocumentReader】
- 【BeanDefinitionParserDelegate】
- 3.3 源码分析
-
- 【AbstractBeanDefinitionReader-loadBeanDefinitions】
- 【XmlBeanDefinitionReader-loadBeanDefinitions】
- 【XmlBeanDefinitionReader-doLoadBeanDefinitions】
- 【DefaultDocumentLoader-loadDocument】
- 【XmlBeanDefinitionReader-registerBeanDefinitions】
- 【DefaultBeanDefinitionDocumentReader-registerBeanDefinitions】
- 【DefaultBeanDefinitionDocumentReader-doRegisterBeanDefinitions】
- 【DefaultBeanDefinitionDocumentReader-parseBeanDefinitions】
- 【DefaultBeanDefinitionDocumentReader-parseDefaultElement】
- 【BeanDefinitionParserDelegate-parseBeanDefinitionElement】
- 【DefaultBeanDefinitionDocumentReader-processBeanDefinition】
- 【BeanDefinitionReaderUtils-registerBeanDefinition】
- 3.4 源码debug
- 3.5 流程小结
- 四 refresh()中 finishBeanFactoryInitialization()分析
-
- 4.1 源码时序图
- 4.2 源码分析
-
- 【AbstractApplicationContext-finishBeanFactoryInitialization】
- 4.3 源码debug
- 4.4 流程小结
- 五 面试题链接
一 主体流程分析
1.1 源码时序图
#描述:1.从项目应用中的使用入口:// 创建IoC容器,并进行初始化ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");2.找到工厂实现类【ClassPathXmlApplicationContext】中对应的构造方法,执行ioc容器初始化:public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {...............................if (refresh) {// 【核心方法】:该方法表示初始化(或者重建)ioc容器。即可以把原来的ApplicationContext销毁,重新执行初始化创建refresh();}}3.找到工厂抽象父类【AbstractApplicationContext】中的【refresh】方法:3.1.该方法实现解析xml配置文件内容,封装成BeanDefinition对象,注册到BeanFactory中3.2.该方法实现一些基础组件的注册:bean后置处理器组件、监听器组件、国际化资源组件3.3.该方法实现bean对象的真正实例化。细节:初始化全部【singleton】单例对象,标记为【lazy-init】延迟加载的对象除外
1.2 源码分析
入口Test
/* Ioc 容器源码分析基础案例*/@Testpublic void testIoC() {// ApplicationContext是容器的高级接口,BeanFacotry(顶级容器/根容器,规范了/定义了容器的基础行为)// Spring应用上下文,官方称之为 IoC容器(错误的认识:容器就是map而已;准确来说,map是ioc容器的一个成员,// 叫做单例池, singletonObjects,容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等以及之间的协作流程)/* Ioc容器创建管理Bean对象的,Spring Bean是有生命周期的* 构造器执行、初始化方法执行、Bean后置处理器的before/after方法、:AbstractApplicationContext#refresh#finishBeanFactoryInitialization* Bean工厂后置处理器初始化、方法执行:AbstractApplicationContext#refresh#invokeBeanFactoryPostProcessors* Bean后置处理器初始化:AbstractApplicationContext#refresh#registerBeanPostProcessors*/ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");LagouBean lagouBean = applicationContext.getBean(LagouBean.class);System.out.println(lagouBean);}
ClassPathXmlApplicationContext
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { // 资源配置文件成员变量,是一个数组,支持多个spring的配置文件@Nullableprivate Resource[] configResources;// 默认构造方法public ClassPathXmlApplicationContext() {}// 如果已经存在一个ioc容器,可以在构造的时候设置【父】容器public ClassPathXmlApplicationContext(ApplicationContext parent) {super(parent);}// 【重点跟踪】根据xxx.xml配置文件,创建ioc容器public ClassPathXmlApplicationContext(String configLocation) throws BeansException {this(new String[]{configLocation}, true, (ApplicationContext)null);
}
........................................../*【重点跟踪】方法说明:* 根据xml文件的定义,以及父容器,创建一个新的ClassPathXmlApplicationContext参数说明:* configLocations:xml配置文件数组* refresh:是否要重新创建ioc容器。加载全部bean的定义和创建所有的单例对象* parent:父容器*/public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {super(parent);// 设置父容器// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)this.setConfigLocations(configLocations);if (refresh) {this.refresh();// 【核心方法】:该方法表示初始化(或者重建)ioc容器。即可以把原来的ApplicationContext销毁,重新执行初始化创建}}
..........................................
}
AbstractApplicationContext
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { ........................................../* 【重点跟踪】方法说明:* 【核心方法】:该方法表示初始化(或者重建)ioc容器。即可以把原来的ApplicationContext销毁,重新执行初始化创建*/@Overridepublic void refresh() throws BeansException, IllegalStateException {// 创建ioc容器,同步加锁,保障线程安全synchronized (this.startupShutdownMonitor) {/* 1.刷新预处理* 准备工作:记录容器启动的时间,和状态标记*/prepareRefresh();/* 2.阅读XML中的信息,注册BeanDefinition(重点)* obtainFreshBeanFactory 获取 beanFactory 实例并且完成BeanDefinition的注册工作* // 关键步骤:* // 1.根据配置文件中配置内容,解析成一个个Bean实例(BeanDefinition)* // 2.将一个个Bean实例,注册到BeanFactory中* // 3.细节:这里的Bean实例仅仅是描述Bean的相关信息,此时还没有真正创建对应的bean对象*/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();/* 3.beanFactory 预装工作,* // 设置BeanFactory:* // 1.设置类加载器* // 2.设置BeanPostProcessor(bean后置处理器)* // 3.注册特殊的bean(框架内部使用的bean)*/prepareBeanFactory(beanFactory);try {// 4.设置BeanFactoryPostProcessorpostProcessBeanFactory(beanFactory);/* 5.执行bean后场处理器,执行完毕* 解析BeanDefinition对象,put到map里* 再次执行bean后置工厂处理器*/invokeBeanFactoryPostProcessors(beanFactory);// 6.注册BeanPostProcessor的实现类:// 1.该接口有两个方法:// postProcessBeforeInitialization(),在init-method属性指定的方法前调用// postProcessAfterInitialization(),在init-method属性指定的方法后调用registerBeanPostProcessors(beanFactory);// 7.初始化国际化支持的资源文件initMessageSource();// 8.初始化ApplicationContext事件广播器initApplicationEventMulticaster();// 9.模板方法:用于特殊bean的初始化,默认是空实现// (在api中如果预留了一些方法实现是空,表示该方法是留给子类自我实现。那么这些方法称为:钩子方法)onRefresh();// 10.注册事件监听器:监听器需要实现ApplicationListener接口registerListeners();// 11.创建单实例业务Bean(非懒加载单例bean)// 服务启动的时候,就会初始化所有的单例beanfinishBeanFactoryInitialization(beanFactory);// 【最后一步】:// 12.发布广播事件。ApplicationContext初始化完成finishRefresh();} catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// 如果发生异常,需要销毁已经创建的singleton对象destroyBeans();// 将active状态设置为falsecancelRefresh(ex);// Propagate exception to caller.throw ex;} finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}
}
1.3 流程小结
#主体流程小结:1.在应用程序中,通过调用ClassPathXmlApplicationContext工厂实现类构造方法,初始化创建ioc容器入口2.在ClassPathXmlApplicationContext构造方法中,调用refresh方法:2.1.方法名称很特别,不是init,而是refresh。refresh表示不仅仅是初始化创建ioc容器,还有可能是已经有了一个ioc容器,需要更新的意思2.2.spring框架在处理过程中,会考虑先释放已经存在的ioc容器,再重新创建一个新的ioc容器3.spring框架允许在一个应用中,可以存在多个ioc容器,并且可以建立它们之间的父子关系。比如在ssm框架整合中,就有两个ioc容器:3.1.通过ContextLoaderListener监听器,加载spring配置文件,创建的父容器3.2.通过DispatcherServlet前端控制器,加载springmvc主配置文件,创建的子容器4.spring框架在创建ioc容器时,主体流程:4.1.设置容器的初始化状态。比如容器的启动时间,容器的激活状态4.2.【重点】解析bean.xml配置文件,将xml配置文件中的配置信息,比如<bean id="" class=""/>标签的配置信息,解析封装成BeanDefinition对象4.3.将BeanDefinition对象,注册到BeanFactory容器中。需要注意:此时还没有创建真正的bean对象,只是解析封装xml配置文件内容4.4.设置一些公共资源。比如bean的后置处理器、类加载器、监听器、国际化资源等4.5.【重点】根据BeanDefinition对象,真正创建bean对象。需要注意:此时创建的是全部单例【singleton】、且不是延迟加载【lazy-init】的对象4.6.最后一步广播事件,进行善后处理
二 refresh()中 obtainFreshBeanFactory()分析
创建Bean容器,注册bean对象
2.1 源码时序图
#描述流程:1.调用【AbstractApplicationContext】refresh()方法:初始化创建Bean容器入口2.调用【AbstractApplicationContext】obtainFreshBeanFactory()方法3.调用【AbstractRefreshableApplicationContext】refreshBeanFactory()方法:创建Bean容器,加载并注册bean4.调用【AbstractRefreshableApplicationContext】customizeBeanFactory()方法:4.1.设置bean覆盖。如果在配置文件中通过bean标签配置时,有id或者name属性值相同的bean标签配置。spring框架默认在同一个配置文件中出现重复,则报错。在不同配置文件中出现,则进行覆盖4.2.设置bean循环引用。循环引用是指:A依赖B、B依赖C、C依赖A5.调用【AbstractXmlApplicationContext】loadBeanDefinitions()方法:加载解析xxx.xml配置文件,根据xml配置文件内容,将bean标签的定义,解析成BeanDefinition实例。并且注册到beanFactory中6.调用【AbstractRefreshableApplicationContext】getBeanFactory()方法:返回Bean容器
2.2 源码分析
【AbstractApplicationContext-obtainFreshBeanFactory】
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {/* 刷新或创建BeanFactory*/refreshBeanFactory();/* 将刚生成的BeanFactory返回*/return getBeanFactory();}
【AbstractRefreshableApplicationContext-refreshBeanFactory】
/* This implementation performs an actual refresh of this context's underlying* bean factory, shutting down the previous bean factory (if any) and* initializing a fresh bean factory for the next phase of the context's lifecycle.* 方法说明:* 1.创建Bean容器,加载并且注册bean* 2.首先关闭上一次创建的bean factory,如果还存在的话* 3.初始化创建一个新的bean factory*/@Overrideprotected final void refreshBeanFactory() throws BeansException {// 判断是否存在bean factory,如果存在需要执行释放操作if (hasBeanFactory()) {// 判断是否存在bean factory,如果存在需要执行释放操作destroyBeans();// 销毁当前Bean容器closeBeanFactory();}try {// 实例化DefaultListableBeanFactory 创建一个新的Bean容器DefaultListableBeanFactory beanFactory = createBeanFactory();//设置序列化idbeanFactory.setSerializationId(getId());//自定义bean工厂的一些属性(允许覆盖和循环依赖)// 【重点跟踪】定制化设置beanFactory// 1.设置bean覆盖。如果在配置文件中通过bean标签配置时,有id或者name属性值相同的bean标签配置。// spring框架默认在同一个配置文件中出现重复,则报错。在不同配置文件中出现,则进行覆盖// 2.设置bean循环引用。循环引用是指:// A依赖B、B依赖C、C依赖AcustomizeBeanFactory(beanFactory);// 【重点跟踪】加载解析xxx.xml配置文件,根据xml配置文件内容,将bean标签的定义,// 解析成BeanDefinition实例。并且注册到beanFactory中loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {//赋值当前的beanFactorythis.beanFactory = beanFactory;}} catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}
【AbstractRefreshableApplicationContext-customizeBeanFactory】
/*定制化设置beanFactory*/protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {if (this.allowBeanDefinitionOverriding != null) {// 1.设置bean覆盖。如果在配置文件中通过bean标签配置时,有id或者name属性值相同的bean标签配置。// spring框架默认在同一个配置文件中出现重复,则报错。在不同配置文件中出现,则进行覆盖beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}if (this.allowCircularReferences != null) {// 2.设置bean循环引用。循环引用是指:// A依赖B、B依赖C、C依赖AbeanFactory.setAllowCircularReferences(this.allowCircularReferences);}}
【AbstractXmlApplicationContext-loadBeanDefinitions】
/* Loads the bean definitions via an XmlBeanDefinitionReader.* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader* @see #initBeanDefinitionReader* @see #loadBeanDefinitions*方法说明:* 通过xml配置文件,读取解析内容,封装到BeanDefinition中*/@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.// 创建XMLBeanDefinition阅读器// 注解的是AnnotatedBeanDefinitionReaderXmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);// 加载并注册BeanDefinition信息集合loadBeanDefinitions(beanDefinitionReader);}
【AbstractRefreshableApplicationContext-getBeanFactory】
@Overridepublic final ConfigurableListableBeanFactory getBeanFactory() {synchronized (this.beanFactoryMonitor) {if (this.beanFactory == null) {throw new IllegalStateException("BeanFactory not initialized or already closed - " +"call 'refresh' before accessing beans via the ApplicationContext");}return this.beanFactory;}}
2.3 源码debug
第一步:
第二步:
第三步:
第四步:
第五步:
第六步:
第七步:
第八步:
第九步:
第十步:
三 obtainFreshBeanFactory()中loadBeanDefinitions()分析
解析xml配置文件流程
3.1 源码时序图
#流程描述:1.调用【AbstractBeanDefinitionReader】loadBeanDefinitions方法:解析xml文档入口2.调用【XmlBeanDefinitionReader】loadBeanDefinitions方法:加载xml配置文件内容,获取InputStream流对象3.调用【XmlBeanDefinitionReader】doLoadBeanDefinitions方法:根据InputStream流,获取Document文档对象4.调用【DefaultDocumentLoader】loadDocument方法:工具类,通过DocumentBuilder构建器,将InputStream流,转换成Document文档对象5.调用【XmlBeanDefinitionReader】registerBeanDefinitions方法:根据Document文档对象,完成解析成BeanDefinition对象6.调用【DefaultBeanDefinitionDocumentReader】registerBeanDefinitions方法:从Document文档根元素开始解析,转换成BeanDefinition对象7.调用【DefaultBeanDefinitionDocumentReader】doRegisterBeanDefinitions方法:从根元素root开始解析,注册每一个BeanDefinition对象8.调用【DefaultBeanDefinitionDocumentReader】parseBeanDefinitions方法:解析beans根标签的的具体子标签。比如:bean/alias/import9.调用【DefaultBeanDefinitionDocumentReader】parseDefaultElement方法:私有方法,解析beans标签的具体子元素标签。比如<bean/>、<import/>等10.调用【BeanDefinitionParserDelegate】parseBeanDefinitionElement方法:解析<bean id="" class=""/>标签。转换成BeanDefinition对象11.调用【DefaultBeanDefinitionDocumentReader】processBeanDefinition方法:将BeanDefinition对象,注册到BeanFactory中12.调用【BeanDefinitionReaderUtils】registerBeanDefinition方法:将BeanDefinition对象,注册到BeanDefinitionRegistry中。此处的BeanDefinitionRegistry就是BeanFactory容器
第一部分:
第二部分:
3.2 前置内容
#描述:通过完成xml配置文件解析,将xml中的<bean>标签配置内容,转换成BeanDefinition对象,并且注册到BeanFactory中。关于解析xml和BeanDefinition对象,主要有以下api:BeanDefinition:存储Bean相关信息。比如bean对应的类、是否是单例、是否是延迟加载等XmlBeanDefinitionReader:加载读取xml配置文件,获取xml对应的Document文档对象DefaultBeanDefinitionDocumentReader:根据Document文档对象,从根元素开始解析子标签配置(重点是bean标签),转换成对应的BeanDefinition对象,注册到BeanFactoryBeanDefinitionParserDelegate:spring的xml配置文件内容,以及BeanDefinition委派类。是人大代表。
【BeanDefinition】
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {/* 单例作用范围*/String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;/* 多例作用范围*/String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;................................................./* 设置bean类名称*/void setBeanClassName(@Nullable String beanClassName);/* 获取bean类名称*/@NullableString getBeanClassName();/* 设置bean作用范围*/void setScope(@Nullable String scope);/* 获取bean作用范围*/@NullableString getScope();/* 设置延迟加载*/void setLazyInit(boolean lazyInit);/* 获取bean是否延迟加载*/boolean isLazyInit();/* 设置bean的依赖(在bean标签中的depend-on属性)*/void setDependsOn(@Nullable String... dependsOn);/* 获取bean的依赖*/@NullableString[] getDependsOn();................................................. /* 对于通过工厂方法实例化的bean。设置工厂名称*/void setFactoryBeanName(@Nullable String factoryBeanName);/*对于通过工厂方法实例化的bean。获取工厂名称*/@NullableString getFactoryBeanName();/* 对于通过工厂方法实例化的bean。设置工厂方法名称*/void setFactoryMethodName(@Nullable String factoryMethodName);/* 对于通过工厂方法实例化的bean。获取工厂方法名称*/@NullableString getFactoryMethodName();/* 获取构造方法参数(构造方法注入)*/ConstructorArgumentValues getConstructorArgumentValues();/* set方法注入*/MutablePropertyValues getPropertyValues();/* 是否是单例*/boolean isSingleton();/* 是否是多例*/boolean isPrototype();................................................. }
【DefaultBeanDefinitionDocumentReader】
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;// 嵌套的beans标签public static final String NESTED_BEANS_ELEMENT = "beans";// alias标签public static final String ALIAS_ELEMENT = "alias";// name属性public static final String NAME_ATTRIBUTE = "name";// alias属性public static final String ALIAS_ATTRIBUTE = "alias";// import标签public static final String IMPORT_ELEMENT = "import";// resource属性public static final String RESOURCE_ATTRIBUTE = "resource";// profile属性public static final String PROFILE_ATTRIBUTE = "profile";..........................................
}
【BeanDefinitionParserDelegate】
public class BeanDefinitionParserDelegate {public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";/* Value of a T/F attribute that represents true.* Anything else represents false. Case seNsItive.*/public static final String TRUE_VALUE = "true";public static final String FALSE_VALUE = "false";public static final String DEFAULT_VALUE = "default";public static final String DESCRIPTION_ELEMENT = "description";public static final String AUTOWIRE_NO_VALUE = "no";public static final String AUTOWIRE_BY_NAME_VALUE = "byName";public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";public static final String NAME_ATTRIBUTE = "name";public static final String BEAN_ELEMENT = "bean";public static final String META_ELEMENT = "meta";public static final String ID_ATTRIBUTE = "id";public static final String PARENT_ATTRIBUTE = "parent";public static final String CLASS_ATTRIBUTE = "class";public static final String ABSTRACT_ATTRIBUTE = "abstract";public static final String SCOPE_ATTRIBUTE = "scope";private static final String SINGLETON_ATTRIBUTE = "singleton";public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";public static final String AUTOWIRE_ATTRIBUTE = "autowire";public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";public static final String PRIMARY_ATTRIBUTE = "primary";public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";public static final String INIT_METHOD_ATTRIBUTE = "init-method";public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";public static final String CONSTRUCTOR_ARG_ELEMENT = "constructor-arg";public static final String INDEX_ATTRIBUTE = "index";public static final String TYPE_ATTRIBUTE = "type";public static final String VALUE_TYPE_ATTRIBUTE = "value-type";public static final String KEY_TYPE_ATTRIBUTE = "key-type";public static final String PROPERTY_ELEMENT = "property";public static final String REF_ATTRIBUTE = "ref";public static final String VALUE_ATTRIBUTE = "value";public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";public static final String REPLACED_METHOD_ELEMENT = "replaced-method";public static final String REPLACER_ATTRIBUTE = "replacer";public static final String ARG_TYPE_ELEMENT = "arg-type";public static final String ARG_TYPE_MATCH_ATTRIBUTE = "match";public static final String REF_ELEMENT = "ref";public static final String IDREF_ELEMENT = "idref";public static final String BEAN_REF_ATTRIBUTE = "bean";public static final String PARENT_REF_ATTRIBUTE = "parent";public static final String VALUE_ELEMENT = "value";public static final String NULL_ELEMENT = "null";public static final String ARRAY_ELEMENT = "array";public static final String LIST_ELEMENT = "list";public static final String SET_ELEMENT = "set";public static final String MAP_ELEMENT = "map";public static final String ENTRY_ELEMENT = "entry";public static final String KEY_ELEMENT = "key";public static final String KEY_ATTRIBUTE = "key";public static final String KEY_REF_ATTRIBUTE = "key-ref";public static final String VALUE_REF_ATTRIBUTE = "value-ref";public static final String PROPS_ELEMENT = "props";public static final String PROP_ELEMENT = "prop";public static final String MERGE_ATTRIBUTE = "merge";public static final String QUALIFIER_ELEMENT = "qualifier";public static final String QUALIFIER_ATTRIBUTE_ELEMENT = "attribute";public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates";public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method";
................................................
}
3.3 源码分析
【AbstractBeanDefinitionReader-loadBeanDefinitions】
/*方法说明:* 加载xml配置文件,转换BeanDefinition对象,注册到BeanFactory中。【入口方法】*/public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {Assert.notNull(locations, "Location array must not be null");int counter = 0;for (String location : locations) {//【重点跟踪】counter += loadBeanDefinitions(location);}return counter;}
【XmlBeanDefinitionReader-loadBeanDefinitions】
/* Load bean definitions from the specified XML file.* @param encodedResource the resource descriptor for the XML file,* allowing to specify an encoding to use for parsing the file* @return the number of bean definitions found* @throws BeanDefinitionStoreException in case of loading or parsing errors* *方法说明:* * 加载xml配置文件内容,获取InputStream流对象*/public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {Assert.notNull(encodedResource, "EncodedResource must not be null");if (logger.isTraceEnabled()) {logger.trace("Loading XML bean definitions from " + encodedResource);}Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet<>(4);this.resourcesCurrentlyBeingLoaded.set(currentResources);}if (!currentResources.add(encodedResource)) {throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");}try {// 将资源文件转为InputStream的IO流InputStream inputStream = encodedResource.getResource().getInputStream();try {// 从InputStream中得到XML的解析源InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {// 设置字符集编码inputSource.setEncoding(encodedResource.getEncoding());}//具体的读取过程 真正加载xml配置文件,转换成Document对象return doLoadBeanDefinitions(inputSource, encodedResource.getResource());}finally {// 释放io流资源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();}}}
【XmlBeanDefinitionReader-doLoadBeanDefinitions】
/* Actually load bean definitions from the specified XML file.* @param inputSource the SAX InputSource to read from* @param resource the resource descriptor for the XML file* @return the number of bean definitions found* @throws BeanDefinitionStoreException in case of loading or parsing errors* @see #doLoadDocument* @see #registerBeanDefinitions* 方法说明:* * 根据InputStream流,获取Document文档对象*///此方法和5.0.7版本有差别protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {// 通过java自带的dom解析工具加载解析XML文件,最终形成Document对象Document doc = doLoadDocument(inputSource, resource);//解析document对象,封装BeanDefinition对象并进行注册int count = registerBeanDefinitions(doc, resource);if (logger.isDebugEnabled()) {logger.debug("Loaded " + count + " bean definitions from " + resource);}return count;}catch (BeanDefinitionStoreException ex) {throw ex;}catch (SAXParseException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);}catch (SAXException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"XML document from " + resource + " is invalid", ex);}catch (ParserConfigurationException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Parser configuration exception parsing XML from " + resource, ex);}catch (IOException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"IOException parsing XML document from " + resource, ex);}catch (Throwable ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Unexpected exception parsing XML document from " + resource, ex);}}
【DefaultDocumentLoader-loadDocument】
/* Load the {@link Document} at the supplied {@link InputSource} using the standard JAXP-configured* XML parser.* *方法说明:* * 工具类,通过DocumentBuilder构建器,将InputStream流,转换成Document文档对象*/@Overridepublic Document loadDocument(InputSource inputSource, EntityResolver entityResolver,ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);if (logger.isTraceEnabled()) {logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");}// 通过DocumentBuilder构建器,解析xml配置文件内容,获取Document文档对象DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);return builder.parse(inputSource);}
【XmlBeanDefinitionReader-registerBeanDefinitions】
/* Register the bean definitions contained in the given DOM document.* Called by {@code loadBeanDefinitions}.* <p>Creates a new instance of the parser class and invokes* {@code registerBeanDefinitions} on it.* @param doc the DOM document* @param resource the resource descriptor (for context information)* @return the number of bean definitions found* @throws BeanDefinitionStoreException in case of parsing errors* @see #loadBeanDefinitions* @see #setDocumentReaderClass* @see BeanDefinitionDocumentReader#registerBeanDefinitions* *方法说明:* * 根据Document文档对象,完成解析成BeanDefinition对象*/public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// 创建BeanDefinitionDocumentReader来解析Document对象,完成BeanDefinition解析BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();// 获得容器中已经注册的BeanDefinition数量int countBefore = getRegistry().getBeanDefinitionCount();//解析过程入口,BeanDefinitionDocumentReader只是个接口,具体的实现过程在DefaultBeanDefinitionDocumentReader完成documentReader.registerBeanDefinitions(doc, createReaderContext(resource));// 统计新的的BeanDefinition数量return getRegistry().getBeanDefinitionCount() - countBefore;}
【DefaultBeanDefinitionDocumentReader-registerBeanDefinitions】
/* This implementation parses bean definitions according to the "spring-beans" XSD* (or DTD, historically).* <p>Opens a DOM Document; then initializes the default settings* specified at the {@code <beans/>} level; then parses the contained bean definitions.* *方法说明:* * 从Document文档根元素开始解析,转换成BeanDefinition对象*///此处和5.0.7版本有差别@Overridepublic void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;// 真正实现BeanDefinition解析和注册工作doRegisterBeanDefinitions(doc.getDocumentElement());}
【DefaultBeanDefinitionDocumentReader-doRegisterBeanDefinitions】
/* Register each bean definition within the given root {@code <beans/>} element.* *方法说明:* * 从根元素root开始解析,注册每一个BeanDefinition对象*/@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)protected void doRegisterBeanDefinitions(Element root) {// Any nested <beans> elements will cause recursion in this method. In// order to propagate and preserve <beans> default-* attributes correctly,// keep track of the current (parent) delegate, which may be null. Create// the new (child) delegate with a reference to the parent for fallback purposes,// then ultimately reset this.delegate back to its original (parent) reference.// this behavior emulates a stack of delegates without actually necessitating one.// 人大代表:代表spring配置文件中的标签和属性、以及最终转换成的BeanDefinition对象// 这里使用了委托模式,将具体的BeanDefinition解析工作交给了BeanDefinitionParserDelegate去完成BeanDefinitionParserDelegate parent = this.delegate;this.delegate = createDelegate(getReaderContext(), root, parent);// 此段代码不需要关心// 判断该根标签是否包含http://www.springframework.org/schema/beans默认命名空间if (this.delegate.isDefaultNamespace(root)) {String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if (StringUtils.hasText(profileSpec)) {String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);// We cannot use Profiles.of(...) since profile expressions are not supported// in XML config. See SPR-12458 for details.if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isDebugEnabled()) {logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}// 留给子类实现的钩子方法。此时不需要关心 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性 preProcessXml(root);// 【重点跟踪方法】:从根元素开始,解析配置文件内容// 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition的解析parseBeanDefinitions(root, this.delegate);// 留给子类实现的钩子方法。此时不需要关心 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性postProcessXml(root);this.delegate = parent;}
【DefaultBeanDefinitionDocumentReader-parseBeanDefinitions】
/* Parse the elements at the root level in the document:* "import", "alias", "bean". @param root the DOM root element of the document* 方法说明:* 解析beans根标签的的具体子标签。比如:bean/alias/import*/protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {// 加载的Document对象是否使用了Spring默认的XML命名空间(beans命名空间)if (delegate.isDefaultNamespace(root)) {// 获取Document对象根元素的所有子节点(bean标签、import标签、alias标签和其他自定义标签context、aop等)NodeList nl = root.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if (node instanceof Element) {// bean标签、import标签、alias标签,则使用默认解析规则Element ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);} else {//像context标签、aop标签、tx标签,则使用用户自定义的解析规则解析元素节点delegate.parseCustomElement(ele);}}}} else {// 如果不是默认的命名空间,则使用用户自定义的解析规则解析元素节点,此时不需要关心delegate.parseCustomElement(root);}}
【DefaultBeanDefinitionDocumentReader-parseDefaultElement】
/*方法说明:* 私有方法,解析beans标签的具体子元素标签*/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)) {// 解析<bean id="" class=""/>标签配置processBeanDefinition(ele, delegate);}// 解析内置<beans>标签else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recurse// 递归调用doRegisterBeanDefinitions(ele);}}
【BeanDefinitionParserDelegate-parseBeanDefinitionElement】
/* Parses the supplied {@code <bean>} element. May return {@code null}* if there were errors during parse. Errors are reported to the* {@link org.springframework.beans.factory.parsing.ProblemReporter}.* *方法说明:* * 1.解析<bean id="" class=""/>标签配置* * 2.转换成BeanDefinition对象*/@Nullablepublic BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {// 获取bean的idString id = ele.getAttribute(ID_ATTRIBUTE);// 获取bean的nameString nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// 别名处理,此时不需要关心List<String> aliases = new ArrayList<>();if (StringUtils.hasLength(nameAttr)) {String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);aliases.addAll(Arrays.asList(nameArr));}// 将id属性设置为bean的名称String beanName = id;if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {beanName = aliases.remove(0);if (logger.isTraceEnabled()) {logger.trace("No XML 'id' specified - using '" + beanName +"' as bean name and " + aliases + " as aliases");}}if (containingBean == null) {// 检查bean的id或者name是否唯一checkNameUniqueness(beanName, aliases, ele);}//【重点方法】解析bean标签,封装BeanDefinition对象AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {if (!StringUtils.hasText(beanName)) {try {if (containingBean != null) {beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);}else {beanName = this.readerContext.generateBeanName(beanDefinition);// Register an alias for the plain bean class name, if still possible,// if the generator returned the class name plus a suffix.// This is expected for Spring 1.2/2.0 backwards compatibility.String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null &&beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {aliases.add(beanClassName);}}if (logger.isTraceEnabled()) {logger.trace("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);// 【重点方法】创建BeanDefinitionHolder对象并返回。这里的BeanDefinitionHolder代表// 将BeanDefinition对象和BeanName封装到BeanDefinitionHolder对象中return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);}return null;}
【DefaultBeanDefinitionDocumentReader-processBeanDefinition】
/* Process the given bean element, parsing the bean definition* and registering it with the registry.* *方法说明:* * 1.解析<bean id="" class=""/>标签配置* * 2.转换成BeanDefinition对象*/protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {// 解析<bean>标签,获取BeanDefinitionBeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {// 如果需要,则装饰BeanDefinition对象bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance.// 注册最终的BeanDefinition到BeanDefinitionRegistry(DefaultListableBeanFactory)BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());} catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// Send registration event.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}
【BeanDefinitionReaderUtils-registerBeanDefinition】
/* Register the given bean definition with the given bean factory.* @param definitionHolder the bean definition including name and aliases* @param registry the bean factory to register with* @throws BeanDefinitionStoreException if registration failed*方法说明:* 1.将BeanDefinition对象,注册到BeanDefinitionRegistry中* 2.这里的BeanDefinitionRegistry,其实就是DefaultListableBeanFactory,也就是BeanFactory* 容器*/public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();// 将BeanDefinition对象,注册到BeanFactory中。它是一个Map。// key==beanName;value=BeanDefinitionregistry.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);}}}
3.4 源码debug
第一步:
第二步:
第三步:
第四步:
第五步:
第六步:
第七步:
第八步:
第九步:
第十步:
第十一步:
第十二步:
第十三步:
第十四步:
3.5 流程小结
#小结:1.解析bean.xml配置文件,获取配置文件内。比如:<bean id="customerService" class="com.itheima.service.impl.CustomerServiceImpl"/>2.将配置文件内容中,重点关注bean标签的配置。将bean标签的配置信息,封装成BeanDefinition对象3.将BeanDefinition对象,注册到BeanFactory容器中4.需要注意,到此处仅仅只是封装了xml配置文件信息到BeanDefinition中,还没有真正创建相关的bean对象5.在实现过程中,spring框架提供了一系列的api和api方法,实现过程比较复杂:这里大家可能会有一个疑问,不就是解析xml配置文件吗?为什么要这么复杂呢?6.答案是:6.1.spring框架需要尽可能的通用,一定的复杂度是必然的6.2.spring框架设计多api,是为了满足模块化,组件式开发。将各个组件模块之间进行解耦,在我们的项目中,用到哪一个模块,就只需要引入哪一个模块6.3.spring框架设计多api方法,是让一个方法只做一件事情,满足【单一职责】的设计原则。目的还是为了解耦
四 refresh()中 finishBeanFactoryInitialization()分析
初始化创建单例bean
#描述:1.到这一步,已经完成了spring配置文件的解析,将相关的配置信息封装成了BeanDefinition对象2.同时将BeanDefinition对象,注册到了BeanFactory中3.需要注意:此时还只是解析配置了配置文件信息,真正的Bean实例对象还没有创建。4.接下来重点关注,创建实例化bean的流程:finishBeanFactoryInitialization(beanFactory);
4.1 源码时序图
#流程描述:1.调用【AbstractApplicationContext】finishBeanFactoryInitialization方法:初始化创建全部单例【singleton】对象的入口方法2.调用【DefaultListableBeanFactory】preInstantiateSingletons方法:循环遍历创建所有(非抽象、非延迟加载、是单例)的bean对象入口方法3.调用【AbstractBeanFactory】getBean方法:直接调用本类中的doGetBean方法4.调用【AbstractBeanFactory】doGetBean方法:从容器中获取目标bean。如果目标bean已经存在,直接获取返回;如果目标bean不存在,则创建目标bean5.调用【AbstractAutowireCapableBeanFactory】createBean方法:加载目标bean字节码Class,创建bean对象6.调用【AbstractAutowireCapableBeanFactory】doCreateBean方法:实例化bean,设置依赖注入,进行后置回调处理7.调用【AbstractAutowireCapableBeanFactory】createBeanInstance方法:通过三种实例化bean方式实例化(工厂方法、构造方法依赖注入、无参数构造方法)8.调用【AbstractAutowireCapableBeanFactory】instantiateBean方法:使用无参数构造方法实例化bean9.调用【SimpleInstantiationStrategy】instantiate方法:通过反射技术实例化bean对象
第一部分:
第二部分:
4.2 源码分析
【AbstractApplicationContext-finishBeanFactoryInitialization】
/* Finish the initialization of this context's bean factory,* initializing all remaining singleton beans.* 方法说明:* 初始化创建全部单例【singleton】对象的入口方法*/protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// 织入第三方模块,此处不需要关心String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// 设置不使用临时类加载器,此处不需要关心beanFactory.setTempClassLoader(null);// 创建对象中,不允许再修改解析配置信息beanFactory.freezeConfiguration();/*点击进入 preInstantiateSingletons* 实例化所有的非单例 非lazy*/// 【重点】创建全部单例,且非延迟加载的bean对象beanFactory.preInstantiateSingletons();}
【DefaultListableBeanFactory-preInstantiateSingletons】
/*方法说明:* 获取全部目标bean对象的名称,循环遍历创建bean对象(创建条件:非抽象、是单例、非延迟加载)*/@Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.//得到所有的BeanDefinition的名字. 获取全部要创建的目标对象bean的名称(在bean.xml文件中配置)List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...//遍历所有的beanDefinition根据名字,继而验证 beanDefinitionfor (String beanName : beanNames) {// 合并父bean中的配置,相当于<bean id="" class="" parent=""/>不需要关心,用的不多RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 判断对象不是抽象、是单例、不是延迟加载即创建if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//是不是factoryBeanif (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {// 【重点】默认调用无参数构造方法实例化bean对象getBean(beanName);}}}// 回调处理实现了SmartInitializingSingleton接口的bean。此处不需要关心for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}
【AbstractBeanFactory-getBean】
public Object getBean(String name) throws BeansException {// 直接调用本类中的doGetBean方法return doGetBean(name, null, null, false);
}
【AbstractBeanFactory-doGetBean】
/* Return an instance, which may be shared or independent, of the specified bean.* @param name the name of the bean to retrieve* @param requiredType the required type of the bean to retrieve* @param args arguments to use when creating a bean instance using explicit arguments* (only applied when creating a new instance as opposed to retrieving an existing one)* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*方法说明:* 用于从容器中获取目标bean。如果目标bean已经存在,直接获取返回;如果目标bean不存在,则创建目标bean* 处理顺序:* 1.先从容器中获取bean,如果bean已经存在,直接返回* 2.如果bean不存在;则如果是单例bean,创建单例bean* 3.如果bean不存在;则如果是多例bean,创建多例bean* 4.如果bean不存在;且既不是单例,也不是多例,则由第三方来实例化* 5.最后检查判断目标类型是否匹配;如果匹配,直接返回目标bean对象*/@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取bean名称 理解验证bean的名字是否非法final String beanName = transformedBeanName(name);// 目标bean对象引用。返回值Object bean;// Eagerly check singleton cache for manually registered singletons.// 从缓存中获取单例bean//目前看来主要是用于在spring初始化bean的时候判断bean是否在容器当中;以及供程序员直接get某个bean。Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) { //如果获取到单例bean,则走下面代码if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}// 进一步处理bean对象:// 1.如果是普通的bean,直接获取返回// 2.如果FactoryBean(工厂方法实例化bean),则返回工厂方法创建的对象// 如果取出来的Bean实例是FactoryBean的Bean实例,则需要从FactoryBean实例中产生一个对象实例。bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {//如果没有获取到单例bean,则走下面代码// Fail if we're already creating this bean instance:// We're assumably within a circular reference.// 如果原型模式的Bean发生循环引用,则直接不处理,抛出异常if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.// 如果在当前容器中没有找到目标bean;那么再到父容器中进行查找,看父容器中是否存在BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}}// 将目标bean放入一个已经创建的Set集合中if (!typeCheckOnly) {markBeanAsCreated(beanName);}// 如果前面的步骤,没有找到目标bean,则准备创建try {// 获取要实例化的bean的BeanDefinition对象final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查该BeanDefinition对象对应的Bean是否是抽象的checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 优先初始化被依赖的bean。即通过depends-on属性定义指定的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.// 如果是单例的Bean,请下面的代码//创建scope="singleton"的bean(单例)if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {// 创建单例Bean的主要方法/* 点击 createBean 进入*/return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 创建scope="prototype"的bean(多例)else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}// 创建其他bean(既不是单例,也不是多例)。需要由第三方来创建的beanelse {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.// 检查bean类型是能够匹配if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}// 返回目标bean对象return (T) bean;}
【AbstractAutowireCapableBeanFactory-createBean】
/* Central method of this class: creates a bean instance,* populates the bean instance, applies post-processors, etc.* @see #doCreateBean*方法说明:* 创建bean对象入口:* 1.确保目标bean的Class字节码加载* 2.如果目标bean实现了后置处理器接口,则返回代理对象* 3.否则,创建目标bean对象,然后返回*/@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isDebugEnabled()) {logger.debug("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.// 【重点关心】确保目标bean对象的Class字节码,已经加载Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.// 处理方法覆盖try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 获取BeanPostProcessor代理对象// InstantiationAwareBeanPostProcessor接口对bean的实例化的干预处理// 如果目标bean有后置处理器,返回代理对象Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {// 【重点关心】真正创建bean对象的方法 完成Bean实例的创建(实例化、填充属性、初始化)//循环依赖进入Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}
【AbstractAutowireCapableBeanFactory-doCreateBean】
/* Actually create the specified bean. Pre-creation processing has already happened* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.* <p>Differentiates between default bean instantiation, use of a* factory method, and autowiring a constructor.* @param beanName the name of the bean* @param mbd the merged bean definition for the bean* @param args explicit arguments to use for constructor or factory method invocation* @return a new instance of the bean* @throws BeanCreationException if the bean could not be created* @see #instantiateBean* @see #instantiateUsingFactoryMethod* @see #autowireConstructor*方法说明:实例化创建bean* 1.创建bean实例* 2.设置依赖注入,给相关的属性赋值* 3.bean后置回调处理。比如init-method属性配置的初始化方法*/protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.// 这是bean的装饰器对象,相当于包装了bean对象BeanWrapper instanceWrapper = null;// 如果是单例bean,同时检查是否是FactoryBeanif (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// bean初始化第一步:默认调用无参构造实例化Bean// 构造参数依赖注入,就是发生在这一步if (instanceWrapper == null) {//【重点关心】再这个地方完成了对象的创建,推断创建构造方法 进入instanceWrapper = createBeanInstance(beanName, mbd, args);}// 实例化后的Bean对象,只是实例化并没有完成属性的注入final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {//处理合并后的BeanDefinitionapplyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.// 解决循环依赖的关键步骤,判断是否支持循环依赖 默认 turnboolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));// 如果需要提前暴露单例Bean,则将该Bean放入三级缓存中if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}// 将刚创建的bean放入三级缓存中singleFactories(key是beanName,value是FactoryBean)//如果支持则暴露一个工厂addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {// bean初始化第二步:填充属性(DI依赖注入发生在此步骤)// 调用反射和内省去进行属性设置//【重点关心】 属性值需要进行类型转换,判断属性注入是否需要populateBean(beanName, mbd, instanceWrapper);// 【重点关心】bean初始化第三步:调用初始化方法,比如init-method属性配置,比如实现了BeanPostProcessor后置处理接口exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}// 解决循环依赖问题的重点代码if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {//注册Bean的销毁方法,只是注册而以,但销毁方法是在我们容器关闭以后才调用的registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}// 返回实例化好的bean对象return exposedObject;}
【AbstractAutowireCapableBeanFactory-createBeanInstance】
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 检查class对象是否存在Class<?> beanClass = resolveBeanClass(mbd, beanName);// 如果不存在 或者无法访问 抛出异常if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}Supplier<?> instanceSupplier = mbd.getInstanceSupplier();// 通过实例工厂获取对象if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}// 通过工厂方法去创建Bean的实例if (mbd.getFactoryMethodName() != null) {//跟进instantiateUsingFactoryMethod方法// 检查通过后 查看是否有工厂方法 有工厂方法使用工厂方法创建对象return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...boolean resolved = false;boolean autowireNecessary = false;if (args == null) {//一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}//如果已经解析过则使用解析好的构造函数方法不需要再次锁定//一个类中有多个构造函数,判断使用哪个构造函数实例化过程比较耗性能,所以采用缓存机制,如果已经解析过则不需要//重复解析而是直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值去取,否则需要//再次解析,并将解析的结果添加至RootBeanDefinition中的属性if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {//如果没有推断出构造方法,则使用默认的构造方法return instantiateBean(beanName, mbd);}}// Need to determine the constructor...// TODO 如果是自动装配,则推断出各种构造方法Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {// 如果构造器为空 并且不包含构造器参数 采用默认构造器初始化return autowireConstructor(beanName, mbd, ctors, args);}// No special handling: simply use no-arg constructor.// 没有特殊处理的话,只需使用无参构造方法去创建Bean的实例//利用构造方法反射来实例化对象return instantiateBean(beanName, mbd);}
【AbstractAutowireCapableBeanFactory-instantiateBean】
/* Instantiate the given bean using its default constructor.* @param beanName the name of the bean* @param mbd the bean definition for the bean* @return a BeanWrapper for the new instance*方法说明:使用无参数构造方法创建对象*/protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {try {// 目标对象,返回结果Object beanInstance;final BeanFactory parent = this;// 安全控制,此处不需要关心if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->getInstantiationStrategy().instantiate(mbd, beanName, parent),getAccessControlContext());}else {// 实际实例化对象beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);}// 将对象进行包装Wrapper后,返回BeanWrapper bw = new BeanWrapperImpl(beanInstance);initBeanWrapper(bw);return bw;}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);}}
【SimpleInstantiationStrategy-instantiate】
/*方法说明:* 通过反射技术,实例化bean对象*/@Overridepublic Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.// 如果没有方法覆写,则通过反射技术进行实例化创建对象;否则通过cglib创建代理对象if (!bd.hasMethodOverrides()) {// 获取构造方法Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {// 获取bean的字节码Classfinal Class<?> clazz = bd.getBeanClass();// 如果是接口,直接抛出异常(因为接口不能实例化)if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {// 安全控制,此处不需要关心if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);}else {//得到默认的构造方法constructorToUse = clazz.getDeclaredConstructor();}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}// 通过反射技术,根据构造方法实例化对象return BeanUtils.instantiateClass(constructorToUse);}else {// 通过cglib创建代理对象return instantiateWithMethodInjection(bd, beanName, owner);}}
4.3 源码debug
第一步:
第二步:
第三步:
第四步:
第五步:
第六步:
第七步:
第八步:
第九步:
第十步:
第十一步:
4.4 流程小结
#描述流程:1.应用程序入口:1.1.加载spring配置文件,创建spring ioc容器,创建相关bean对象。是执行入口2.调用【AbstractApplicationContext】finishBeanFactoryInitialization方法:2.1.初始化创建全部单例【singleton】对象的入口方法3.调用【DefaultListableBeanFactory】preInstantiateSingletons方法:3.1.获取所有目标实例化bean的名称3.2.循环遍历创建所有(非抽象、非延迟加载、是单例)的bean对象4.调用【AbstractBeanFactory】getBean方法:4.1.直接调用本类中的doGetBean方法5.调用【AbstractBeanFactory】doGetBean方法:5.1.用于从容器中获取目标bean。如果目标bean已经存在,直接获取返回;如果目标bean不存在,则创建目标bean5.2.先从容器中获取bean,如果bean已经存在,直接返回5.3.如果bean不存在;则如果是单例bean,创建单例bean5.4.如果bean不存在;则如果是多例bean,创建多例bean5.5.如果bean不存在;且既不是单例,也不是多例,则由第三方来实例化5.6.最后检查判断目标类型是否匹配;如果匹配,直接返回目标bean对象6.调用【AbstractAutowireCapableBeanFactory】createBean方法:6.1.确保目标bean的Class字节码加载6.2.如果目标bean实现了后置处理器接口,则返回代理对象6.3.否则,创建目标bean对象,然后返回7.调用【AbstractAutowireCapableBeanFactory】doCreateBean方法:7.1.实例化创建bean7.2.设置依赖注入,给相关属性赋值7.3.进行bean的后置回调处理8.调用【AbstractAutowireCapableBeanFactory】createBeanInstance方法:8.1.实例化bean对象,三种方式8.2.使用工厂方法实例化bean8.3.使用带参数构造方法实例化bean8.4.使用无参数构造方法实例化bean9.调用【AbstractAutowireCapableBeanFactory】instantiateBean方法:9.1.使用无参数构造方法实例化bean10.调用【SimpleInstantiationStrategy】instantiate方法:10.1.通过反射技术实例化bean对象
五 面试题链接
Spring常见面试题总结(超详细回答)