springboot原始碼學習筆記系列一
- bean的注入裝配
- bean的流程原始碼分析
筆者大學剛畢業滿半年,雖然找到一份程式猿的作業,但了解到這個行業學習是永無止境,因此開始學習和解讀springboot的原始碼,并寫下該系列日記,以激勵和警醒自己并分享自己的學習內容,如有錯誤,歡迎各位大佬的批評指正,
bean的注入裝配
spring的核心可以分為IOC和AOP,IOC即為控制反轉,通過spring的IOC容器來創建物件,而不是通程序式員來創建,那么spring是怎么來幫你創建物件的呢?這部分我是通過網上的視頻課程進行學習的,剛上手可能都不知道從那里看起,于是,我便通過網上的一些視頻進行了了解,這些物件我們一般把它叫做bean,bean在springboot中的注入一般可以通過xml和注解注入的方式進行,@AutoWired和的形式我們都比較熟悉,無論是哪種方法,spring都會通過讀取檔案轉換為BeanDefinition,而從bean的檔案到BeanDefinition是通過BeanDefinitionReader來實作的,隨后BeanDefinition通過BeanFactoryPostProcessor,即bean工廠的后置處理器來進行處理,之后便是BeanPostProcessor的后置處理器,這兩個PostProcessor程式員都可以自己去實作介面來進行拓展,之后便是通過反射來創建bean,整個流程大概如下圖:
bean的流程原始碼分析
我們先寫個方法來注入一個bean
public static void main(String[] args) {
ApplicationContext context= new ClassPathXmlApplicationContext("syl.xml");
Object stud=context.getBean("student");
System.out.println();
}
隨后,寫一個對應的xml
<bean class="com.spring.demo.demo.student" name="student">
<property name="username" value="shenyili"/>
<property name="password" value="syl199746"/>
</bean>
之后通過debug的方式來一點點分析,spring在整個程序干了些什么
1.我們先看到它進入了ClassPathXmlApplicationContext的構造方法
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
通過查看上面的注釋,發現是通過父類ApplicationContext 創建一個ClassPathXmlApplicationContext,載入xml檔案讀取配置 ,其中呼叫了setConfigLocations和refresh兩個方法,我們傳進去的syl.xml便是configLocations的值,注釋中寫了see #refresh(),那我們進去看看>* _*<,
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(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();
contextRefresh.end();
}
}
}
然后,我們就找到了大寶貝,這個便是bean的處理的整個流程,閱讀英文注釋,我們便可以大概了解每個步驟干了些什么,
prepareRefresh():
準備好context,進去看了下,大概就是對context 一些引數賦初值,
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():
創建bean工廠
prepareBeanFactory(beanFactory):
對創建的bean工廠賦值引數
postProcessBeanFactory(beanFactory):
這部分就是提到的BeanFactory的后置處理器的介面,默認不做任何操作
invokeBeanFactoryPostProcessors(beanFactory):
呼叫BeanFactoryPostProcessor
registerBeanPostProcessors(beanFactory):
注冊BeanPostProcessors并中斷bean的創建
beanPostProcess.end():
結束BeanPostProcessors程序
initMessageSource():
這部分好像又是對context的一些資訊進行init
initApplicationEventMulticaster():
初始化事務多播器?先記在小本本上,之后再看
onRefresh():
好像是對一些特殊的beans進行init
registerListeners():
檢查和注冊監聽的bean
finishBeanFactoryInitialization(beanFactory):
完成不是懶加載的單例bean
finishRefresh():
發布對應的事件
這些暫時到現在我學的東西,請大家批評指正,之后我應該還會對每個流程進行詳細的學習,也會分享自己的學習筆記!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/260632.html
標籤:其他
