自我感觉spring在面试当中很常见,仔细整理了一下:
1 BeanDefinition的Resource定位
2 BeanDefinition的载入
3 向IoC容器注册BeanDefinition
Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext的refresh() ⽅法中
1.主流程
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 第⼀步:刷新前的预处理
prepareRefresh();
/*
第⼆步:
获取BeanFactory;默认实现是DefaultListableBeanFactory
加载BeanDefinition 并注册到 BeanDefitionRegistry
*/ ConfigurableListableBeanFactory beanFactory =
obtainFreshBeanFactory();
// 第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等)
prepareBeanFactory(beanFactory);
try {
// 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
postProcessBeanFactory(beanFactory);
// 第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏
registerBeanPostProcessors(beanFactory);
// 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
// 第⼋步:初始化事件派发器
initApplicationEventMulticaster();
// 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
onRefresh();
// 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
registerListeners();
/*
第⼗⼀步:
初始化所有剩下的⾮懒加载的单例bean
初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性)
填充属性
初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)
调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处
*/
finishBeanFactoryInitialization(beanFactory);
/*
第⼗⼆步:
完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件(ContextRefreshedEvent)
*/
finishRefresh();
}
.......
}
}
2.BeanFactory创建流程
2.1获取BeanFactory子流程
上面流程中的第二步的方法: obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
refreshBeanFactory()在AbstractRefreshableApplicationContext类中
protected final void refreshBeanFactory() throws BeansException {
// 判断是否已有bean factory
if (hasBeanFactory()) {
// 销毁beans
destroyBeans();
// 关闭bean factory
closeBeanFactory();
}
try {
// 实例化DefaultListableBeanFactory 划重点:创建了beanFacory:DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化id
beanFactory.setSerializationId(getId());
// 自定义bean工厂的一些属性(如多个xml中的bean的id相同时是否覆盖,是否允许循环依赖)
customizeBeanFactory(beanFactory);
// 加载应用中的BeanDefinitions 划重点:加载所有bean的BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 赋值当前beanFactory
this.beanFactory = beanFactory;
}
}
....
}
2.2加载解析BeanDefinition以及其注册
上面代码中AbstractRefreshableApplicationContext中的loadBeanDefinitions()方法加载
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//给指定的beanFactory创建一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//给XmlBeanDefinitionReader对象设置一些context上下文中的环境属性
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//提供给子类实现,提供一些自定义的初始化策略
initBeanDefinitionReader(beanDefinitionReader);
// 真正的去加载BeanDefinition
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 从Resource资源对象加载BeanDefinitions
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
// 从xml配置文件加载BeanDefinition对象
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//跳转至XmlBeanDefinitionReader中去加载
reader.loadBeanDefinitions(configLocations);
}
}
XmlBeanDefinitionReader类中加载代码
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
......
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 把xml文件流封装为InputSource对象
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// do!执行加载逻辑
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
......
doLoadBeanDefinitions:真正加载的方法:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 读取xml信息,将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;
}
......
}
我们重点观察XmlBeanDefinitionReader类的registerBeanDefinitions方法,期间产生了多次重载调用,我们定位到最后一个
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 获取已有BeanDefinition的数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册BeanDefinition(createReaderContex()首先完成了NamespaceHandlerResolver的初始化。)
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回新注册的BeanDefinition数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
进入registerBeanDefinitions,再进入DefaultBeanDefinitionDocumentReader类中的doRegisterBeanDefinitions()方法
protected void doRegisterBeanDefinitions(Element root) {
......
preProcessXml(root);
// 解析BeanDefinition
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
查看parseBeanDefinitions()方法,解析xml中的<bean>等标签
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
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);
......
}
查看分类处理方法parseDefaultElement(ele, delegate);
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);
}
// 嵌套beans处理
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
具体解析注册bean的方法:processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析bean元素为BeanDefinition,但是此时使用BeanDefinitionHoler 又包装成了BeanDefinitionHoler对象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 如果有自定义标签,则处理自定义标签
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 完成BeanDefinition的注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
.....
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
查看BeanDefinitionReaderUtils的registerBeanDefinition()方法,然后一直跟踪registerBeanDefinition方法直到下面这个方法中看到this.beanDefinitionMap.put(beanName, beanDefinition);将他放入beanDefinitionMap(是一个 ConcurrentHashMap),完成注册。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
......
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
......
// 划重点:将beanDefinition存入map集合
this.beanDefinitionMap.put(beanName, beanDefinition);
}
...
}
至此,注册流程结束,我们发现,所谓的注册就是把封装的XML中定义的Bean信息封装为BeanDefinition对象之后放入-个Map中, BeanFactory 是以Map的结构存放这些BeanDefinition的。
BeanDefinition和BeanDefinitionHolder的结构
3.Bean创建流程
⼦流程⼊⼝在AbstractApplicationContext#refresh()⽅finishBeanFactoryInitialization(beanFactory) 处
进入方法,还在当前类中:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// 实例化所有立即加载的单例bean
beanFactory.preInstantiateSingletons();
}
继续进⼊DefaultListableBeanFactory类的preInstantiateSingletons⽅法
public void preInstantiateSingletons() throws BeansException {
......
synchronized (this.beanDefinitionMap) {
for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
String beanName = (String) it.next();
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断是否是工厂bean
if (isFactoryBean(beanName)) {
FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {
//通过getbean获取实例
getBean(beanName);
}
}
else {
//通过getbean获取实例
getBean(beanName);
}
}
}
}
}
可以看出不管是工厂bean还是普通bean都是通过getBean获取实例
进入getBean(),只是转发调用,最终进入AbstractBeanFactory类的doGetBean
protected Object doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
......
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (int i = 0; i < dependsOn.length; i++) {
String dependsOnBean = dependsOn[i];
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
//划重点 Create bean instance.创建单例bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
//划重点 创建bean
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);
}
}
进⼊到AbstractAutowireCapableBeanFactory类的⽅法,找到以下代码部分
进⼊doCreateBean⽅法
if (instanceWrapper == null) {
//创建bean实例,但是尚未设置属性
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//判断二级缓存
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 重点:给Bean填充属性,调⽤初始化⽅法,应⽤BeanPostProcessor后置处理器
Object exposedObject = bean;
try {
//bean属性填充
populateBean(beanName, mbd, instanceWrapper);
//掉用初始化方法,应用BeanPostprocessor后置处理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
......
bean实例化的时候如果存在bean之间互相依赖,使用三级缓存解决非构造单例bean循环依赖问题,具体请看下一篇文章
4. lazy-init 延迟加载机制原理
普通 Bean 的初始化是在容器启动初始化阶段执⾏的,⽽被lazy-init=true修饰的 bean 则是在从容器⾥
第⼀次进⾏context.getBean() 时进⾏触发。Spring 启动的时候会把所有bean信息(包括XML和注解)解
析转化成Spring能够识别的BeanDefinition并存到Hashmap⾥供下⾯的初始化时⽤,然后对每个
BeanDefinition 进⾏处理,如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进
⾏初始化并依赖注⼊
public void preInstantiateSingletons() throws BeansException {
// 所有beanDefinition集合
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 触发所有⾮懒加载单例bean的初始化
for (String beanName : beanNames) {
// 获取bean 定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是否是懒加载单例bean,如果是单例的并且不是懒加载的则在容器创建时初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是 FactoryBean
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>)
getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof
SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new
PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
} else {
/*
划重点
如果是普通bean则进⾏初始化并依赖注⼊,此 getBean(beanName)接下来触发的逻辑
和懒加载时 context.getBean("beanName") 所触发的逻辑是⼀样的
*/
getBean(beanName);
}
}
}
}
总结
对于被修饰为lazy-init的bean Spring 容器初始化阶段不会进⾏ init 并且依赖注⼊,当第⼀次
进⾏getBean时候才进⾏初始化并依赖注⼊
对于⾮懒加载的bean,getBean的时候会从缓存⾥头获取,因为容器初始化阶段 Bean 已经
初始化完成并缓存了起来