自我感覺spring在面試當(dāng)中很常見,仔細(xì)整理了一下:
1 BeanDefinition的Resource定位
2 BeanDefinition的載入
3 向IoC容器注冊BeanDefinition
Spring IoC 容器初始化的關(guān)鍵環(huán)節(jié)就在 AbstractApplicationContext的refresh() ?法中
1.主流程
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 第?步:刷新前的預(yù)處理
prepareRefresh();
/*
第?步:
獲取BeanFactory;默認(rèn)實(shí)現(xiàn)是DefaultListableBeanFactory
加載BeanDefinition 并注冊到 BeanDefitionRegistry
*/ ConfigurableListableBeanFactory beanFactory =
obtainFreshBeanFactory();
// 第三步:BeanFactory的預(yù)準(zhǔn)備?作(BeanFactory進(jìn)??些設(shè)置,?如context的類加載器等)
prepareBeanFactory(beanFactory);
try {
// 第四步:BeanFactory準(zhǔn)備?作完成后進(jìn)?的后置處理?作
postProcessBeanFactory(beanFactory);
// 第五步:實(shí)例化并調(diào)?實(shí)現(xiàn)了BeanFactoryPostProcessor接?的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 第六步:注冊BeanPostProcessor(Bean的后置處理器),在創(chuàng)建bean的前后等執(zhí)?
registerBeanPostProcessors(beanFactory);
// 第七步:初始化MessageSource組件(做國際化功能;消息綁定,消息解析);
initMessageSource();
// 第?步:初始化事件派發(fā)器
initApplicationEventMulticaster();
// 第九步:?類重寫這個(gè)?法,在容器刷新的時(shí)候可以?定義邏輯
onRefresh();
// 第?步:注冊應(yīng)?的監(jiān)聽器。就是注冊實(shí)現(xiàn)了ApplicationListener接?的監(jiān)聽器bean
registerListeners();
/*
第??步:
初始化所有剩下的?懶加載的單例bean
初始化創(chuàng)建?懶加載?式的單例Bean實(shí)例(未設(shè)置屬性)
填充屬性
初始化?法調(diào)?(?如調(diào)?afterPropertiesSet?法、init-method?法)
調(diào)?BeanPostProcessor(后置處理器)對實(shí)例bean進(jìn)?后置處
*/
finishBeanFactoryInitialization(beanFactory);
/*
第??步:
完成context的刷新。主要是調(diào)?LifecycleProcessor的onRefresh()?法,并且發(fā)布事件(ContextRefreshedEvent)
*/
finishRefresh();
}
.......
}
}
2.BeanFactory創(chuàng)建流程
2.1獲取BeanFactory子流程

上面流程中的第二步的方法: obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
refreshBeanFactory()在AbstractRefreshableApplicationContext類中
protected final void refreshBeanFactory() throws BeansException {
// 判斷是否已有bean factory
if (hasBeanFactory()) {
// 銷毀beans
destroyBeans();
// 關(guān)閉bean factory
closeBeanFactory();
}
try {
// 實(shí)例化DefaultListableBeanFactory 劃重點(diǎn):創(chuàng)建了beanFacory:DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 設(shè)置序列化id
beanFactory.setSerializationId(getId());
// 自定義bean工廠的一些屬性(如多個(gè)xml中的bean的id相同時(shí)是否覆蓋,是否允許循環(huán)依賴)
customizeBeanFactory(beanFactory);
// 加載應(yīng)用中的BeanDefinitions 劃重點(diǎn):加載所有bean的BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 賦值當(dāng)前beanFactory
this.beanFactory = beanFactory;
}
}
....
}

2.2加載解析BeanDefinition以及其注冊
上面代碼中AbstractRefreshableApplicationContext中的loadBeanDefinitions()方法加載
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//給指定的beanFactory創(chuàng)建一個(gè)XmlBeanDefinitionReader讀取器對象,用于讀取解析xml對象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//給XmlBeanDefinitionReader對象設(shè)置一些context上下文中的環(huán)境屬性
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//提供給子類實(shí)現(xiàn),提供一些自定義的初始化策略
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) {
//跳轉(zhuǎn)至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!執(zhí)行加載邏輯
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對象并進(jìn)行注冊
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
......
}
我們重點(diǎn)觀察XmlBeanDefinitionReader類的registerBeanDefinitions方法,期間產(chǎn)生了多次重載調(diào)用,我們定位到最后一個(gè)
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 獲取已有BeanDefinition的數(shù)量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注冊BeanDefinition(createReaderContex()首先完成了NamespaceHandlerResolver的初始化。)
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回新注冊的BeanDefinition數(shù)量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
進(jìn)入registerBeanDefinitions,再進(jìn)入DefaultBeanDefinitionDocumentReader類中的doRegisterBeanDefinitions()方法
protected void doRegisterBeanDefinitions(Element root) {
......
preProcessXml(root);
// 解析BeanDefinition
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
查看parseBeanDefinitions()方法,解析xml中的<bean>等標(biāo)簽
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)) {
// 解析默認(rèn)標(biāo)簽元素
parseDefaultElement(ele, delegate);
}
else {
// 解析自定義標(biāo)簽元素
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,但是此時(shí)使用BeanDefinitionHoler 又包裝成了BeanDefinitionHoler對象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 如果有自定義標(biāo)簽,則處理自定義標(biāo)簽
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方法直到下面這個(gè)方法中看到this.beanDefinitionMap.put(beanName, beanDefinition);將他放入beanDefinitionMap(是一個(gè) ConcurrentHashMap),完成注冊。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
......
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
......
// 劃重點(diǎn):將beanDefinition存入map集合
this.beanDefinitionMap.put(beanName, beanDefinition);
}
...
}
至此,注冊流程結(jié)束,我們發(fā)現(xiàn),所謂的注冊就是把封裝的XML中定義的Bean信息封裝為BeanDefinition對象之后放入-個(gè)Map中, BeanFactory 是以Map的結(jié)構(gòu)存放這些BeanDefinition的。
BeanDefinition和BeanDefinitionHolder的結(jié)構(gòu)


3.Bean創(chuàng)建流程
?流程??在AbstractApplicationContext#refresh()?finishBeanFactoryInitialization(beanFactory) 處
進(jìn)入方法,還在當(dāng)前類中:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// 實(shí)例化所有立即加載的單例bean
beanFactory.preInstantiateSingletons();
}
繼續(xù)進(jìn)?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獲取實(shí)例
getBean(beanName);
}
}
else {
//通過getbean獲取實(shí)例
getBean(beanName);
}
}
}
}
}
可以看出不管是工廠bean還是普通bean都是通過getBean獲取實(shí)例
進(jìn)入getBean(),只是轉(zhuǎn)發(fā)調(diào)用,最終進(jìn)入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);
}
}
//劃重點(diǎn) Create bean instance.創(chuàng)建單例bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
//劃重點(diǎn) 創(chuàng)建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);
}
}
進(jìn)?到AbstractAutowireCapableBeanFactory類的?法,找到以下代碼部分

進(jìn)?doCreateBean?法
if (instanceWrapper == null) {
//創(chuàng)建bean實(shí)例,但是尚未設(shè)置屬性
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);
}
});
}
// 重點(diǎn):給Bean填充屬性,調(diào)?初始化?法,應(yīng)?BeanPostProcessor后置處理器
Object exposedObject = bean;
try {
//bean屬性填充
populateBean(beanName, mbd, instanceWrapper);
//掉用初始化方法,應(yīng)用BeanPostprocessor后置處理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
......
bean實(shí)例化的時(shí)候如果存在bean之間互相依賴,使用三級緩存解決非構(gòu)造單例bean循環(huán)依賴問題,具體請看下一篇文章
4. lazy-init 延遲加載機(jī)制原理
普通 Bean 的初始化是在容器啟動(dòng)初始化階段執(zhí)?的,?被lazy-init=true修飾的 bean 則是在從容器?
第?次進(jìn)?context.getBean() 時(shí)進(jìn)?觸發(fā)。Spring 啟動(dòng)的時(shí)候會(huì)把所有bean信息(包括XML和注解)解
析轉(zhuǎn)化成Spring能夠識(shí)別的BeanDefinition并存到Hashmap?供下?的初始化時(shí)?,然后對每個(gè)
BeanDefinition 進(jìn)?處理,如果是懶加載的則在容器初始化階段不處理,其他的則在容器初始化階段進(jìn)
?初始化并依賴注?
public void preInstantiateSingletons() throws BeansException {
// 所有beanDefinition集合
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 觸發(fā)所有?懶加載單例bean的初始化
for (String beanName : beanNames) {
// 獲取bean 定義
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判斷是否是懶加載單例bean,如果是單例的并且不是懶加載的則在容器創(chuàng)建時(shí)初始化
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 {
/*
劃重點(diǎn)
如果是普通bean則進(jìn)?初始化并依賴注?,此 getBean(beanName)接下來觸發(fā)的邏輯
和懶加載時(shí) context.getBean("beanName") 所觸發(fā)的邏輯是?樣的
*/
getBean(beanName);
}
}
}
}
總結(jié)
對于被修飾為lazy-init的bean Spring 容器初始化階段不會(huì)進(jìn)? init 并且依賴注?,當(dāng)?shù)?次
進(jìn)?getBean時(shí)候才進(jìn)?初始化并依賴注?
對于?懶加載的bean,getBean的時(shí)候會(huì)從緩存?頭獲取,因?yàn)槿萜鞒跏蓟A段 Bean 已經(jīng)
初始化完成并緩存了起來