如果對SpringIoc與Aop的原始碼感興趣,可以訪問參考:https://javadoop.com/,十分詳細。
Spring容器的啟動全流程
Spring容器的啟動流程如下,這是我在看原始碼過程中自己總結的流程圖,如有錯誤,還望評論區指點:
接下來附上原始碼:
為什麼是refresh方法命名,而不是init命名呢?
其實,在ApplicaitonContext建立起來之後,可以通過refresh進行重建,將原來的ac銷燬,重新執行一次初始化操作,用refresh更加貼切。
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//如果已經有application Context ,並需要配置成父子關係, 呼叫該構造方法
super(parent);
// 根據提供的路徑,處理成配置檔案陣列(以分號、逗號、空格、tab、換行符分割)
setConfigLocations(configLocations);
if (refresh) {
refresh();//核心!!!
}
}
雖然ApplicationContext
繼承自BeanFactory
,更確切地說是ApplicationContext
內部持有了一個例項化的BeanFactory(DefaultListableBeanFactory)
,BeanFactory
的相關操作其實是委託給這個例項來處理。
@Override
public void refresh() throws BeansException, IllegalStateException {
//保證容器啟動銷燬操作的併發安全
synchronized (this.startupShutdownMonitor) {
//準備工作, 記錄容器的啟動時間, 標記已啟動狀態, 處理配置檔案種的佔位符
prepareRefresh();
//這步用於將配置檔案解析成一個個bean definition,註冊到重建的beanFactory中,(只是提取了配置資訊,bean並沒有初始化),同時還設定兩個配置屬性:1、是否允許bean覆蓋2、是否允許迴圈引用
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//設定beanFactory的類載入器, 新增幾個beanPostProcessor ,手動註冊幾個特殊的bean
prepareBeanFactory(beanFactory);
try {
//如果bean實現了beanFactoryPostProcessor 將會執行postProcessBeanFactory方法 提供子類的擴充套件點,到這bean都載入、註冊完成,但沒有初始化,具體的子類可以在這步新增特殊bfpp實現類做事
postProcessBeanFactory(beanFactory);
//呼叫bfpp的各個實現類的ppbf方法
invokeBeanFactoryPostProcessors(beanFactory);
//註冊BeanPostProcessor的實現類,BeanPostProcessor將在bean初始化前後執行
registerBeanPostProcessors(beanFactory);
//初始化當前 ApplicationContext 的 MessageSource,國際化
initMessageSource();
//初始化當前 ApplicationContext 的事件廣播器
initApplicationEventMulticaster();
//模板方法(鉤子方法,具體的子類可以在這裡初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
//註冊事件監聽器,監聽器需要實現 ApplicationListener 介面。
registerListeners();
//例項化+初始化所有的非懶載入的單例bean
finishBeanFactoryInitialization(beanFactory);
//廣播事件,ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源
destroyBeans();
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
}
}
}
利用註解方式大致也是按照這個流程一步步下來,不同在於,AnnotationConfigApplicationContext在執行構造器的時候,已經通過scan(basePackages);
將beanDefination讀取到。
將bean的定義轉化為BeanDefination:
如果利用AnnotationConfigApplicationContext。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);//這個過程中配置已經被轉化為一個個的beanDefinition
refresh();
}
Spring容器關閉流程
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
//取消註冊上下文
if (!IN_NATIVE_IMAGE) {
LiveBeansView.unregisterApplicationContext(this);
}
// 釋出事件
publishEvent(new ContextClosedEvent(this));
// 停止所有Lifecycle bean,以避免在銷燬期間造成延遲。
if (this.lifecycleProcessor != null) {
this.lifecycleProcessor.onClose();
}
// 銷燬上下文的BeanFactory中所有快取的單例。
destroyBeans();
// 關閉此上下文字身的狀態。
closeBeanFactory();
// 讓子類善後
onClose();
// 充值本地應用堅硬其為pre-refresh狀態
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 切換為非活動狀態
this.active.set(false);
}
}
大概就是:先發布事件,再摧毀Factory中的bean,再摧毀Factory本身,最後設定一些狀態。
而Bean週期中的銷燬部分就存在於destroyBeans
中。當然,銷燬bean也是需要先銷燬它所依賴的bean。
Bean 的生命週期
在瞭解Bean的生命週期之前,我們必須要明確SpringBean和我們通常說的物件有什麼區別?
SpringBean是由SpringIoC容器管理的,是一個被例項化,組裝,並通過容器管理的物件,可通過getBean()獲取。容器通過讀取配置的後設資料,解析成BeanDefinition,註冊到BeanFactory中,加入到singletonObjects快取池中。
Bean的建立
在上面的流程中,只有到finishBeanFactoryInitialization(beanFactory);
這一步,才開始對非懶載入例項的例項化+ 初始化。
//例項化所有剩餘的非懶載入的單例bean
beanFactory.preInstantiateSingletons();
可以看一下這一步的具體實現:DefaultListableBeanFactory
public void preInstantiateSingletons() throws BeansException {
//擁有所有的beanNames
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 觸發所有非懶載入的singleton beans的例項化+初始化操作
for (String beanName : beanNames) {
//對bean繼承的處理,合併父bean 中的配置
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//非抽象,非懶載入的singletons
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//處理factoryBean
if (isFactoryBean(beanName)) {
//如果是factoryBean,在beanName錢加上&,再呼叫getBean方法
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
//判斷當前 FactoryBean 是否是 SmartFactoryBean 的實現
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 {
getBean(beanName);//普通的bean,直接呼叫getBean進行例項化
}
}
}
}
只有!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()
條件滿足的時候,這一步才會進行例項化,另外,Spring還對其是否為FactoryBean進行判斷,當然了,一般來說,最最普通的bean都會在最後一個else分支中進行例項化。
doGetBean全流程
這部分篇幅過長,我直接放上總結的流程圖:
createBean
那麼createBean又幹了什麼事呢,稍微看看就可以:
//省略許多異常處理的部分
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {//初始化階段的args == null
RootBeanDefinition mbdToUse = mbd;
// 確保 BeanDefinition 中的 Class 被載入
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 準備方法覆寫它來自於 bean 定義中的 <lookup-method /> 和 <replaced-method />
mbdToUse.prepareMethodOverrides();
// 讓 InstantiationAwareBeanPostProcessor 在這一步有機會返回代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
// 重頭戲,建立 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
我們的重點放在Object beanInstance = doCreateBean(beanName, mbdToUse, args);
這一步上,我們已經知道,Bean的例項化+初始化都在這一步中完成。
doCreateBean
在這個doCreateBean方法中,存在三個重要方法:
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();
}
//spring5.0 返回建立bean例項的回撥
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
//採用工廠方法例項化
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 如果是第二次建立 如prototype bean,這種情況下,我們可以從第一次建立知道,採用無參建構函式,還是建構函式依賴注入 來完成例項化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
//建構函式注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
//無參建構函式
return instantiateBean(beanName, mbd);
}
}
// 判斷是否採用有參建構函式
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//args!=null 的建構函式注入(有參)
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
//判斷是否採用首選的建構函式
return autowireConstructor(beanName, mbd, ctors, null);
}
// 呼叫無參建構函式
return instantiateBean(beanName, mbd);
}
以無參建構函式為例,例項化的過程在SimpleInstantiationStrategy中。
- 如果不存在方法重寫:可以直接使用Java的反射進行例項化。
- 否則使用CGLIB實現例項化。
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果不存在方法覆寫,就是用java的反射進行例項化, 否則使用CGLIB
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final 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來完成例項化,需要依賴於CGLIB生成子類
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
此時,Bean例項已經通過構造方法或者工廠方法建立,但是其中的屬性,如依賴注入的各種屬性尚未填充。
populateBean 填充屬性
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {//this.propertyValues bean例項的所有屬性
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
//在設定屬性之前,給所有InstantiationAwareBeanPostProcessor機會修改bean的狀態
// 【此時bean的狀態 = 已經通過工廠方法或者構造方法例項化,在屬性賦值之前】。例如,可以使用支援欄位注入的樣式。InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);//獲取PropertyValue物件
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {//獲取Autowire的模式 or 通過名字, or 通過型別
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 通過名字找到所有屬性值,如果是 bean 依賴,先初始化依賴的 bean。記錄依賴關係
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 通過型別裝配 記錄依賴關係
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//...省略
//設定bean例項的屬性值
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
initializeBean 回撥方法
屬性注入完成,處理各種回撥,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware等。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {//
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);//如果bean實現了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware介面, 回撥
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//BeanPostProcessor 的 postProcessBeforeInitialization 回撥
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);//處理bean中定義的init-method或 bean實現了InitializingBean ,呼叫afterPropertiesSet() 方法
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//BeanPostProcessor 的 postProcessAfterInitialization 回撥
}
return wrappedBean;
}
Bean的銷燬
DisposableBeanAdapter.java
@Override
public void destroy() {
//CommonAnnotationBeanPostProcessorc 處理@preDetroy
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {////DisposableBean的destroy方法
((DisposableBean) this.bean).destroy();
}
}
if (this.destroyMethod != null) {//destroy-method方法
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
參考資料: