在Spring源碼系列:依賴注入(一)(AbstractBeanFactory-getBean)最後說道getBean是依賴注入的起點,bean的建立都是經過createBean來完成具體的建立的。createBean的具體實現是在AbstractAutowireCapableBeanFactory中的。本篇就捋一捋這個方法看下bean的建立過程。java
這個方法是AbstractAutowireCapableBeanFactory這個類的中心方法,其做用就是建立一個bean實例,填充bean實例,後置處理等。spring
在createBean中主要作了三件事:緩存
具體來看方法:安全
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//判斷須要建立的Bean是否能夠實例化,這個類是否能夠經過類裝載器來載入
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
//異常:Validation of method overrides failed
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target
//bean instance.
//是否配置了後置處理器相關處理(若是配置了則返回一個代理)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
//異常:BeanPostProcessor before instantiation of bean failed
}
//建立Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
複製代碼
從上面的代碼中能夠看到,建立bean是交給doCreateBean方法來建立的。繼續看doCreateBean這個方法: (這裏面涉及到一個BeanWrapper這個接口,小夥伴能夠移步瞭解一下《Spring源碼系列:BeanWrapper》)bash
代碼 1:微信
// 用BeanWrapper來持有建立出來的Bean對象
BeanWrapper instanceWrapper = null;
//若是是單例的話,則先把緩存中的同名bean清除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//實際建立的交給createBeanInstance來完成,
//bean的生成,這裏會使用默認的類生成器,包裝成BeanWrapperImpl類,
//爲了下面的populateBean方法的屬性注入作準備
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
複製代碼
代碼 2:app
容許後處理器修改合併的bean定義。ide
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
//異常:Post-processing of merged bean definition failed
}
mbd.postProcessed = true;
}
}
複製代碼
代碼 3 :函數
即便被BeanFactoryAware等生命週期接口觸發,也要儘快地緩存singletons 以便可以解析循環引用。post
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<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
複製代碼
代碼 4:
這裏是對bean的初始化的地方,通常狀況下依賴注入就在這裏發生;這個exposedObject變量保存的是在初始化處理完之後返回的做爲依賴注入完成以後的bean。
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
//拋出
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)
ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
//異常:Initialization of bean failed
}
}
複製代碼
代碼 5:
這裏是註冊bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
//異常處理
}
//返回結果
return exposedObject;
複製代碼
上面的5個代碼段均是doCreateBean中的處理邏輯,有興趣的小夥伴能夠自行查閱源碼。從上面的代碼中咱們依然沒有獲得具體建立的過程,由於在doCreateBean中又依賴:createBeanInstance
和populateBean
兩個方法。
在createBeanInstance
中生成了Bean所包含的java對象。來看是怎麼生成的:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 確保bean類實際上已經解析過了,能夠實例化
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
//異常:Bean class isn't public, and non-public access not allowed:beanName
}
//1. 使用工廠方法來進行bean的實例化
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);
}
}
// 2.須要肯定構造函數...,使用構造函數進行bean實例化
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//3.沒有特殊的處理:只需使用無參數構造函數。(默認構造函數)
return instantiateBean(beanName, mbd);
}
複製代碼
從上面這段代碼能夠看出,對象的生成有許多不一樣的方式,有經過工廠的,也有經過容器的autowire特性生成的。固然這些生成方式都是由相關的BeanDefinition來指定的。
Spring中配置Bean的方式咱們經常使用的一種是經過xml文件來配置,還有就是經過註解的方式來配置。
<bean id="user" class="com.glmapper.test.User">
<property name="name" value="glmapper"></property>
</bean>
複製代碼
這種方式,經過class提供的權限定名,spring就能夠利用反射機制建立這個bean。
<bean id="user" class="com.glmapper.test.UserFactory" factory-method="getUser">
<constructor-arg value="glmapper"></constructor-arg>
</bean>
複製代碼
這種是利用靜態工廠方法來建立的,提供的class並不是是類的權限定名, 而是靜態工廠的全類名;除此以外還須要指定獲取bean的方法(此處是getUser)和參數(參數是glmapper)。
<bean id="userFactory" class="com.glmapper.test.UserInstanceFactory">
<!--用一個集合來保存我當前的對象實例-->
<property name="map">
<map>
<entry key="user1">
<bean class="com.glmapper.test.User">
<property name="name" value="glmapper1"></property>
</bean>
</entry>
<entry key="user2">
<bean class="com.glmapper.test.User">
<property name="name" value="glmapper2"></property>
</bean>
</entry>
</map>
</property>
</bean>
//實例1
<bean id="user1" factory-bean="userFactory" factory-method="getUserInstance">
<constructor-arg value="user1"></constructor-arg>
</bean>
//實例2
<bean id="user2" factory-bean="userFactory" factory-method="getUserInstance">
<constructor-arg value="user2"></constructor-arg>
</bean
複製代碼
這種方式和靜態工廠的區別在於咱們須要先實例化一個工廠對象,而後才能使用這個工廠對象來建立咱們的bean。getUserInstance經過key值來獲取咱們已經實例化好的對象(固然方式有不少,此處以map來舉個例子)。關於註解的和使用FactoryBean接口的這裏就暫時不說,後期再聊
OK,繼續來分鐘,上面說到的是以工廠方法建立bean,具體的源碼有點長,這裏就不放了,大概思路就如上面所提到的那幾種方式。接下來看下常見的使用instantiateBean方式(使用它的默認構造函數)來構建bean的代碼:
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
//獲取系統安全接口。
//若是已經爲當前應用程序創建了安全管理器,則返回該安全管理器;
//不然,返回null。
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
//異常:Instantiation of bean failed
}
}
複製代碼
能夠看出,上面的建立都是經過:
getInstantiationStrategy().instantiate(mbd, beanName, parent);
複製代碼
這樣一段代碼來完成的,是的,這裏已經快接近真相了。從語義上來分析,先是獲取了一種策略,而後利用當前獲取的策略再去執行實例化。OK,咱們看下getInstantiationStrategy()拿到的是什麼:
//返回實例化策略用於建立bean實例。
protected InstantiationStrategy getInstantiationStrategy() {
return this.instantiationStrategy;
}
//默認的實例化測試是使用CGLIB代理
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
複製代碼
看到這裏咱們清楚了,默認構造函數的狀況下,在spring中會使用Cglib來進行bean的實例化(關於cglib此處再也不贅述)。咱們看下CglibSubclassingInstantiationStrategy這個類的申明:
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy 複製代碼
它繼承自SimpleInstantiationStrategy ,這個又是什麼鬼呢?
SimpleInstantiationStrategy是Spring用來生成Bean對象的默認類,在這個類中提供了兩種實例化java對象的方法,一種是基於java自身反射機制的BeanUtils,還有一種就是基於Cglib
。
如何建立的就不說了;到這裏createBeanInstance就說完了(Bean已經建立了);可是僅僅是建立,spring尚未處理它們,好比說bean對象的屬性,依賴關係等等。這些就是上面提到的另一個方法populateBean;
這個方法其實就作了一件事:**使用bean定義中的屬性值在給定的BeanWrapper中填充bean實例。**分段來看: 下面這段代碼是先將BeanDefinition中設置的property值封裝成PropertyValues,而後檢測咱們的BeanWrapper是否爲Null,若是爲null則拋出異常或者跳過當前空實例賦值階段
//獲取到BeanDefinition中設置的property值,封裝成PropertyValues
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
//異常:Cannot apply property values to null instance
}
else {
// Skip property population phase for null instance.
return;
}
}
複製代碼
下面這段代碼的意思是給任何InstantiationAwareBeanPostProcessors提供在設置屬性以前修改bean狀態的機會。
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
複製代碼
下面就是對具體注入方式的處理:
//處理autowire的注入;能夠根據bean的名稱和類型來注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 則根據名稱添加基於自動裝配的屬性值。
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根據類型添加基於自動裝配的屬性值。
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
複製代碼
兩個判斷條件,在知足的狀況下作的處理分別是:
//返回這個工廠是否擁有一個InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//返回依賴檢查代碼。
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
//從給定的BeanWrapper中提取一組已過濾的PropertyDescriptors,
//不包括在被忽略的依賴性接口上定義的被忽略的依賴類型或屬性(譯註)。
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
複製代碼
最後是對屬性進行注入:
applyPropertyValues(beanName, mbd, bw, pvs);
複製代碼
這個方法描述的是對屬性進行解析而後注入的過程;先來分析下applyPropertyValues的申明:
protected void applyPropertyValues(String beanName , BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) 複製代碼
代碼分段來看:
if (pvs == null || pvs.isEmpty()) {
return;
}
複製代碼
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// 使用預先轉換後的值。
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
//異常:Error setting property values
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
複製代碼
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this, beanName, mbd, converter);
複製代碼
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
複製代碼
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
//返回此持有者是否已經包含轉換後的值(true),仍是須要轉換值(false)。
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
//看下面的註釋resolveValueIfNecessary
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// 可能將轉換的值存儲在合併的bean定義中,以免爲每一個建立的bean實例從新轉換。
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
複製代碼
resolveValueIfNecessary
給定一個PropertyValue,返回一個value,必要時解析對工廠中其餘bean的引用。value能夠是:
下面這段代碼時依賴注入發生的地方,其其實是在BeanWrapperImpl中來完成。
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
//異常:Error setting property values
}
複製代碼
上面說到spring是經過BeanDefinitionValueResolver來解析BeanDefinition的,而後再注入到property中,關於這個過程在下一篇中來講。
歡迎關注微信公衆號