bean的創建過程
1.入口
這個是接着bean的加載過程進行分析
return createBean(beanName, mbd, args);
2.使用bean的定義mbd和傳入參數beanName來獲取class,這塊可以參考一下AbstractBeanDefinition,這個對象中提供了獲取class的方法getBeanClass(),完成參數的設置。
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
3.這個方法就是獲取該方法下所有overied方法,然後獲取所有的接口和父類的方法,如果方法名大於1的該方法的overloaded屬性就是true,進行記錄。
mbdToUse.prepareMethodOverrides();
4.實例化前後處理程序已啓動 對beanDefinition的一些參數進行處理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
上面4步可以總結爲就是對該beanDefnition的一些預處理操作:如覆蓋方法的屬性標誌,創建實例化前處理器屬性的標誌。
5.進行實際創建步驟
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
6.首先是要從緩存中進行獲取
// 實例化bean。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//未完成FactoryBean實例的緩存:將FactoryBean名稱緩存到BeanWrapper{清除緩存}
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
這裏面要解釋一下BeanWrapper{Spring底層javabean基礎設施的核心接口。 }
7.實例化一個bean的實例,實例化bean的實例基本上有三種方式:
第一種:使用該bean的工廠
第二種:帶有參數的構造方法{這個比較麻煩,需要進行參數的解析和構造函數的解析和匹配}
第三種:默認參數的構造
/**
* 使用適當的實例化策略爲指定的bean創建一個新實例:
* 工廠方法、構造函數自動連接或簡單實例化。
* @param beanName bean的名字
* @param mbd bean的定義
* @param args 用於構造函數或工廠方法調用的顯式參數
* @return 新實例的BeanWrapper
* @see #obtainFromSupplier
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 確保bean類在這一點上得到了實際的解析。解析beanName獲取到beanClass
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//獲取bean創建的回調如果有的話
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果工廠方式不爲空則用工廠方式創建
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 重新創建相同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)) {
//構造函數自動注入
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);
}
8.合併bean的定義
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//將MergedBeanDefinitionPostProcessors應用於指定的bean定義
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
9.是否添加到單例工廠
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
10.屬性的注入,分爲兩種,一種是按名稱注入,一種是按類型注入
populateBean(beanName, mbd, instanceWrapper);
①按名稱注入
/**
* 在傳入的參數中找到該bean並實例化初始化屬性參數
* 用引用填充任何缺失的屬性值
* *如果autowire設置爲“byName”,則此工廠中的其他bean。
* @param beanName 我們正在連接的bean的名稱。
* Useful for debugging messages; not used functionally.
* @param mbd 通過自動連接更新bean定義
* @param bw 我們可以從中獲取關於bean的信息的bean包裝器
* @param pvs 用於註冊連接對象的PropertyValues
*/
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
②按類型注入
/**
* 抽象方法定義“按類型自動連接”(按類型定義bean屬性)行爲。
* 這類似於PicoContainer默認值,其中必須只有一個bean
* *表示bean工廠中的屬性類型。這使得bean工廠非常簡單
* *配置小的名稱空間,但不能像標準Spring那樣工作
* *大型應用程序的行爲。
* @param beanName the name of the bean to autowire by type
* @param mbd the merged bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//尋找bw中需要進行依賴注入的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
//探測指定屬性的set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// 在優先級後處理器的情況下,不允許立即初始化進行類型匹配。
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
// 解析指定 beanName 的屬性所匹配的值,並把解析到的屬性名稱存儲在
// autowireBeanNames 中,當屬性存在多個封裝 bean 時,如:
// @Autowired private List<A> aList; 將會找到所有匹配 A 類型
// 的 bean 並將其注入
if (autowiredArgument != null) {
//將bean中屬性匹配類型添加進去
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//註冊依賴
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
①根據名稱注入,首先獲取該bean所需要進行注入的所有屬性
然後根據getBean方法循環遞歸實例化並加入到pvs中
②根據類型注入,首先獲取該bean所需要進行注入的所有屬性
然後循環獲取每個屬性的解釋器
然後根據解釋器探測每個屬性的setter方法
解析指定 beanName 的屬性所匹配的值,並把解析到的屬性名稱存儲在autowireBeanNames,並加入到pvs中
最終會設置到beanWapper的properties參數中去。
11.bean的創建,這個過程會有初始化方法和一些後處理器的作用
exposedObject = initializeBean(beanName, exposedObject, mbd);
12.如果該bean存在早起的應用需要進行依賴的檢測
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//如果該bean沒有被增強
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
//如果沒增強,則獲取它所有的依賴處理
//在循環引用時是否採用注入生bean實例;確定是否爲給定名稱註冊了依賴bean
//不允許注入原生的bean,併爲給定名稱註冊依賴bean
//進行的則是依賴檢測
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 " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
13.就是將disposableBeans添加一個記錄
// 將bean按照scope進行註冊
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();