記錄並分享一下本人學習spring原始碼的過程,有什麼問題或者補充會持續更新。歡迎大家指正!
環境: spring5.X + idea
建議:學習過程中要開著原始碼一步一步過
Spring根據BeanDefinition建立單例物件
DefaultSingletonBeanRegister
中getSingleton((String beanName, ObjectFactory<?> singletonFactory))
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, ...);
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
解析:
- getSingleton 方法中還是先要在單例池中獲取將要被建立的物件是不是存在,不存在了才去建立。this.singletonObjects.get(beanName); 如果不存在Spring還會效驗一下是不是正在被銷燬,是則拋異常。this.singletonsCurrentlyInDestruction
- 一系列效驗完成後開始正式建立物件的第一步
beforeSingletonCreation(beanName);
建立物件前要滿足倆個條件inCreationCheckExclusions
&&singletonsCurrentlyInCreation.add(beanName)
,當前這個Bean沒有被排除,並且這個bean正在建立中。 - 通過
singletonFactory.getObject();
回撥createBean(beanName, mbd, args);
建立物件時先獲取對應的BeanClass(通過反射建立物件),呼叫doCreateBean(beanName, mbdToUse, args);,這個方法中才是正兒八經的例項化物件
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
//....
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//.............
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
doCreateBean解析:
A. 建立物件:createBeanInstance(beanName, mbd, args);
- 通過工廠方法建立物件
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
- 通過預設的無參構造建立物件
instantiateBean(beanName, mbd);
B. 填充屬性:populateBean(beanName, mbd, instanceWrapper); 也是就是Set注入(構造注入已經在建立物件時執行了,自動注入可以忽略)
- 註解屬性賦值
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
解析:通過註解對屬性填充使用了AutowiredAnnotationBeanPostProcessor實現所有操作,在postProcessProperties(pvs, bw.getWrappedInstance(), beanName);方法中真正實現。
- 標籤方式屬性賦值
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
解析:從RootBeanDefinition中獲取屬性的List封裝到PropertyValues中。
遍歷ProperValues 把每個屬性的值進行型別轉換,最後再給bw設定得到的屬性值。-> BeanWrapper.setProperValues(new MutablePropertyValues(deepCopy))。
自定義型別會通過beanFactory.getBean() 獲取對應的物件,再走一遍doGetBean() -> createBean() -> doCreateBean()...
(JDK的型別會先封裝TypeStringValues。自定義的型別會封裝RuntimeBeanReference)
C. 初始化物件:initializeBean(beanName, exposedObject, mbd);
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
.......
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
......
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
解析:初始化分幾個功能
1. Aware -> invokeAwareMethods(String beanName, Object bean)。spring提供的幫助我們獲取Spring容器中對應的元件的相關資訊。
2. BeanPostProcessorsBefore -> applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);已經建立好的物件初始化之前再次加工。
3. 初始化 -> invokeInitMethods(beanName, wrappedBean, mbd);包含了介面初始化((InitializingBean) bean).afterPropertiesSet();和自定義方法初始化invokeCustomInitMethod(beanName, bean, mbd);
4. BeanPostProcessorsAfter -> applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);已經建立好的物件初始化之後再次加工。
最後
感謝您的閱讀,有什麼意見和問題歡迎評論區留言!書寫不易!
覺得文章對你有幫助記得給我點個贊,歡迎大家關注和轉發文章!