目錄
一、總覽
二、源碼分析
(一)getBean觸發依賴注入
(1)getBean
(2)createBean
(3)createBeanInstance
(4)populateBean
(二)Bean的預執行個體化
一、總覽
通過前面的分析,我們知道了IOC容器在初始化過程中建立了BeanDefinition的資料結構,接下來就需要進行依賴注入,處理Bean之間的依賴關系。
通常,我們可以通過lazy-init屬性控制Bean的執行個體化(依賴注入)時機。
當lazy-init=true時,依賴注入會發生在第一次向容器擷取Bean時(getBean);當lazy-init=false時,會在容器初始化的過程中将所有的singleton bean提前進行執行個體化和依賴注入,是以singleton bean的依賴注入是容器初始化過程的一部分,這也是我們常用的ApplicationContext的預設配置。
二、源碼分析
(一)getBean觸發依賴注入
(1)getBean
getBean方法定義在BeanFactory接口中,以DefaultListableBeanFactory為例,其基類AbstractBeanFactory中實作了getBean方法,代碼如下:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
...
/**
* 向容器索要Bean,觸發Bean的依賴注入
*/
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 首先檢查是否存在緩存的singleton bean
// 這裡會涉及到單例緩存、提前曝光單例緩存和單例工廠緩存,後續會進一步解析這部分
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 如果sharedInstance是FactoryBean,則傳回其生産的Bean
// 否則傳回NullBean或sharedInstance本身
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 如果bean正在建立中則擷取失敗
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 檢查目前BeanFactory中是否存在以beanName為名的BeanDefinition
// 如果目前BeanFactory中沒有,則會順着其父BeanFactory查找
BeanFactory parentBeanFactory = getParentBeanFactory();
// 這裡的containsBeanDefinition是一個模闆方法,由DefaultListableBeanFactory實作
// 即在存儲BeanDefinition的Map中查找是否存在
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 目前BeanFactory未找到,開始在父BeanFactory中查找
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 根據beanName擷取BeanFactory中的BeanDefinition
// 這裡的RootBeanDefinition代表着在繼承關系下建立的BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 獲得目前Bean依賴的所有Bean,通過 depends-on="xxx" 屬性指定
// 表示初始化目前Bean需要先初始化其依賴的xxx
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
// 遞歸,直到取到沒有depends-on的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 建立bean執行個體
if (mbd.isSingleton()) { // 建立singleton作用域Bean執行個體
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) { // 建立prototype作用域Bean執行個體
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else { // 建立其他作用域Bean:request、session、global session
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
} // end of else
// 類型檢查
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 類型轉換
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
// 傳回類型轉換後的bean執行個體
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
}
(2)createBean
在前面的分析中,我們可以看到多處調用了createBean方法,這個方法是用來建立Bean執行個體的,并進行了一些其他處理。
createBean方法是一個模闆方法,由其子類AbstractAutowireCapableBeanFactory實作,代碼如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
...
/**
* 建立Bean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 根據class屬性或className解析beanClass
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 對override屬性(lookup-method、replace-method)進行處理
// 會檢測目前beanDefinition的class中是否是否包含相應方法,并将override方法标記為覆寫,防止進行重載參數檢查
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex);
}
try {
// 調用InstantiationAwareBeanPostProcessor
// 允許在執行個體化前後進行處理
// 如果傳回值不為空,表示配置了InstantiationAwareBeanPostProcessor,并且修改了bean
// 則傳回一個代理,而不是bean執行個體
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 建立bean執行個體
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
/**
* 真正開始建立Bean
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// 執行個體化bean
BeanWrapper instanceWrapper = null;
// 如果是單例bean,則先清除緩存
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 若不存在緩存,則建立bean執行個體
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 通過post-processors合并繼承關系下的beanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 提前曝光bean(利用緩存),用于支援循環bean的循環依賴
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, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化bean
Object exposedObject = bean;
try {
// 這裡開始進行依賴注入
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean,執行init-method和後置處理器
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);
}
}
// 檢查在提前曝光時,注入的bean是否為最終版本
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 " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// 給Bean注冊一些必要的銷毀操作,當容器shutdown時執行
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 傳回Bean執行個體,這裡已經完成了依賴注入
return exposedObject;
}
}
到這裡,我們就已經得到依賴注入後的Bean執行個體了,這個過程看起來十分簡單,但實際上有兩個要點需要我們格外關注:其一,建立Bean執行個體(createBeanInstance);其二,進行依賴注入(populateBean),下面讓我們繼續分析。
(3)createBeanInstance
createBeanInstance通過适當的執行個體化政策來建立一個Bean執行個體,這裡需要注意Spring5.0的新特性:通過設定Bean建立回調來覆寫工廠方法和構造函數。
在這個過程中,通過預設構造方法(無參構造)是基本的執行個體化政策,這個政策Spring的實作中提供了兩種建立Bean的方式:其一,通過JVM反射建立Bean執行個體;其二,通過cgLib動态代理建立Bean執行個體。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
...
/**
* 建立Bean執行個體
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 確定Bean類可以執行個體化
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());
}
// 5.0的新特性
// doc注釋:用作建立Bean的回調,設定該回調後會覆寫掉建立Bean的工廠方法和構造函數,
// 但不影響依賴注入過程
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 使用工廠方法執行個體化Bean
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 建立Bean時需要根據beanClass解析構造方法,并緩存在RootBeanDefinition中
// 這裡通過緩存直接進行處理,在建立相同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);
}
}
// 使用構造函數執行個體化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);
}
// 預設構造函數
// 這裡共有兩種方式建立Bean:其一,通過JVM反射;其二,通過cgLib的動态代理機制
return instantiateBean(beanName, mbd);
}
}
(4)populateBean
這裡就是依賴注入的核心了,在這裡,首先由InstantiationAwareBeanPostProcessors進行依賴注入前的處理,判斷是否對Bean的Property進行注入,接下來先處理autowire的注入,這裡的autowire指的是在配置檔案中通過autowire="byName"或者autowire="byType"等屬性配置的bean,最後處理Property屬性注入,代碼如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
...
/**
* 依賴處理
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// 不處理為空的Bean執行個體的依賴
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;
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 首先處理autowire依賴注入,根據Bean的名字或類型進行注入
// 我們可以在配置檔案中指定注入方式:autowire="byName"
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;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
// 在為Bean注入依賴前進行後置處理,比如檢查@Required是否滿足,添加或移除Property
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);
}
}
// 對屬性進行注入
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
/**
* 注入Property
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
// 注入的Property
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
// pvs是MutablePropertyValues執行個體,且可強制類型轉換,則可以直接設定為注入的Property
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// valueResolver用于解析BeanDefinition中的Property
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// 建立一個深拷貝副本,這個副本持有的Property會被注入到Bean中
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
// 利用valueResolver解析PropertyValue
// TODO 具體的解析待後續分析
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);
}
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));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// 将拷貝副本中的PropertyValues注入到Bean中
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
}
到這裡,我們發現最終的依賴注入實際上調用了BeanWrapper接口的setPropertyValues方法,這個方法由AbstractPropertyAccessor實作,在這個方法中,取得了所有的屬性,對每一個屬性進行注入,代碼如下:
public abstract class AbstractPropertyAccessor extends TypeConverterSupport implements ConfigurablePropertyAccessor {
...
@Override
public void setPropertyValues(PropertyValues pvs) throws BeansException {
setPropertyValues(pvs, false, false);
}
@Override
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException {
List<PropertyAccessException> propertyAccessExceptions = null;
// 取得屬性
List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
for (PropertyValue pv : propertyValues) {
try {
// 注入屬性
setPropertyValue(pv);
}
catch (NotWritablePropertyException ex) {
if (!ignoreUnknown) {
throw ex;
}
}
catch (NullValueInNestedPathException ex) {
if (!ignoreInvalid) {
throw ex;
}
}
catch (PropertyAccessException ex) {
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new LinkedList<>();
}
propertyAccessExceptions.add(ex);
}
}
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
throw new PropertyBatchUpdateException(paeArray);
}
}
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
setPropertyValue(pv.getName(), pv.getValue());
}
@Override
public abstract void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;
}
這裡的setPropertyValue(String, Object)是一個模闆方法,具體的實作在其子類AbstractNestablePropertyAccessor中,這是4.2版本加入的新特性,在更早的版本中,setProperty(String,Object)方法是由BeanWrapperImpl實作的,在新版本的實作中,BeanWrapperImpl繼承了AbstractNestablePropertyAccessor,但具體的實作原理還是一樣的,AbstractNestablePropertyAccessor代碼如下:
public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyAccessor {
...
@Override
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
AbstractNestablePropertyAccessor nestedPa;
try {
// 取得屬性通路器
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex);
}
// 将propertyName解析為PropertyTokenHolder,根據keys是否為空分為集合和非集合類型
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
/**
* 通過遞歸傳回一個嵌套屬性路徑的屬性通路器
*/
protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath) {
// 查找第一個嵌套屬性路徑分隔符,即".",的位置
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
// 包含分隔符
if (pos > -1) {
String nestedProperty = propertyPath.substring(0, pos);
String nestedPath = propertyPath.substring(pos + 1);
AbstractNestablePropertyAccessor nestedPa = getNestedPropertyAccessor(nestedProperty);
// 遞歸
return nestedPa.getPropertyAccessorForPropertyPath(nestedPath);
}
// 不包含分隔符,即找到了嵌套屬性路徑中最底層的屬性
// 比如嵌套的a.b,則會找到b這一個屬性通路器
else {
return this;
}
}
/**
* 解析propertyName
*/
private PropertyTokenHolder getPropertyNameTokens(String propertyName) {
String actualName = null;
List<String> keys = new ArrayList<>(2);
int searchIndex = 0;
while (searchIndex != -1) {
// 查找"["位置
int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex);
searchIndex = -1;
if (keyStart != -1) {
// 查找"]"位置
int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length());
if (keyEnd != -1) {
if (actualName == null) {
// 截取屬性名
actualName = propertyName.substring(0, keyStart);
}
// 這裡的key是"["和"]"之間的内容,比如a[3],那麼key就是3
String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd);
// 去掉key前後的單引号or雙引号
if (key.length() > 1 && (key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) {
key = key.substring(1, key.length() - 1);
}
keys.add(key);
searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length();
}
}
}
// 根據屬性名建立PropertyTokenHolder
PropertyTokenHolder tokens = new PropertyTokenHolder(actualName != null ? actualName : propertyName);
if (!keys.isEmpty()) {
tokens.canonicalName += PROPERTY_KEY_PREFIX + StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) + PROPERTY_KEY_SUFFIX;
tokens.keys = StringUtils.toStringArray(keys);
}
return tokens;
}
}
這段代碼裡我們可以看到,首先在嵌套屬性中取得嵌套最底層的屬性的通路器,然後将對屬性名進行解析,将解析結果封裝在PropertyTokenHolder中。
這裡需要對嵌套屬性和PropertyTokenHolder做一個解釋,在剛開始看源碼的時候就卡在了這裡,一直沒有搞懂這種解析發生在什麼情況下,下面我們來對這兩個概念做一下簡單的解析:
首先,嵌套屬性,例如我們在Spring配置檔案中有如下配置:
<beans>
<bean id="a" class="greedystar.entity.A" lazy-init="true">
<property name="name" value="Alvin"/>
<property name="id" value="123"/>
</bean>
<bean id="b" class="greedystar.entity.B" lazy-init="true">
<property name="a" ref="a"/>
<property name="a.name" value="李四"/>
</bean>
</beans>
這裡的 <property name="a.name" value="李四"/> 就是嵌套屬性,代碼中通過遞歸取得嵌套最底層的屬性的通路器,也就是a.name中name屬性的通路器。
其次,PropertyTokenHolder,例如我們在Spring配置檔案中有如下配置:
<beans>
<bean id="a" class="greedystar.entity.A" lazy-init="true">
<property name="name" value="Alvin"/>
<property name="id" value="123"/>
<property name="roles">
<list>
<value>USER</value>
<value>ADMIN</value>
</list>
</property>
</bean>
<bean id="b" class="greedystar.entity.B" lazy-init="true">
<property name="a" ref="a"/>
<property name="a.name" value="李四"/>
<property name="a.roles[0]" value="USER1"/>
<property name="a.roles[1]" value="ADMIN1"/>
</bean>
</beans>
當解析到a.roles[0]這個屬性時,會把這個屬性名解析到PropertyTokenHolder對象中,這個對象的屬性值如下:

可以看到,這裡的keys對應的就是通路集合屬性時的索引值,當keys不為空時認為這個屬性為集合取值屬性,為空則不為集合取值取值屬性,集合取值屬性這個名字是我為了差別于普通的注入集合屬性而随意寫下的,各位對這裡有所差別就好。
OK,對嵌套屬性和集合取值屬性有所了解後,我們繼續回到AbstractNestablePropertyAccessor這個類中,通過上面的分析,我們已經取得了PropertyTokenHolder對象,下面将通過該對象進行屬性的注入,代碼如下:
public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyAccessor {
...
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
if (tokens.keys != null) {
// 集合取值屬性,key的值代表取值的索引
processKeyedProperty(tokens, pv);
}
else { // 非集合取值屬性
processLocalProperty(tokens, pv);
}
}
/**
* 集合取值屬性注入
*/
private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
// 根據屬性名取得要注入的屬性,這裡使用了Java的内省機制,也就是通過setter和getter存取屬性
Object propValue = getPropertyHoldingValue(tokens);
// 這裡的PropertyHandler是對PropertyDescriptor的封裝,具體的實作在BeanWrapperImpl中
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
if (ph == null) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
}
Assert.state(tokens.keys != null, "No token keys");
// 取得要通路集合屬性值的索引
String lastKey = tokens.keys[tokens.keys.length - 1];
//這裡處理數組類型的集合取值屬性
if (propValue.getClass().isArray()) {
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(lastKey);
Object oldValue = null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
// 取得舊的值,比如上文分析中的“張三”
oldValue = Array.get(propValue, arrayIndex);
}
// 将舊值轉換為目前的實際值,比如上文中的“李四”
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(), requiredType, ph.nested(tokens.keys.length));
int length = Array.getLength(propValue);
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
Class<?> componentType = propValue.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
setPropertyValue(tokens.actualName, newArray);
propValue = getPropertyValue(tokens.actualName);
}
// 将轉換後的值set到索引指定的位置
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName, "Invalid array index in property path '" + tokens.canonicalName + "'", ex);
}
}
// 下面處理LIST和MAP,基本屬于同一個套路,這裡就不把代碼貼出來了
else if (propValue instanceof List) {
} else if (propValue instanceof Map) {
}
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName, "Property referenced in indexed property path '" + tokens.canonicalName + "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
}
/**
* 非集合取值屬性注入
*/
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
// 取得PropertyHandler,用于後續使用内省機制
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
if (ph == null || !ph.isWritable()) {
if (pv.isOptional()) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring optional value for property '" + tokens.actualName + "' - property not found on bean class [" + getRootClass().getName() + "]");
}
return;
}
else {
throw createNotWritablePropertyException(tokens.canonicalName);
}
}
Object oldValue = null;
try {
// 取得屬性舊值
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
if (pv.isConverted()) {
// 取得已轉換過的新值
valueToApply = pv.getConvertedValue();
}
else {
if (isExtractOldValueForEditor() && ph.isReadable()) {
try {
oldValue = ph.getValue();
}
catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" + this.nestedPath + tokens.canonicalName + "'", ex);
}
}
}
// 将舊值轉換為實際的新值
valueToApply = convertForProperty(tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
// 通過Java内省機制set新的屬性值,setValue方法的具體實作在BeanWrapperImpl中
ph.setValue(valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
}
else {
Throwable cause = ex.getTargetException();
if (cause instanceof UndeclaredThrowableException) {
// May happen e.g. with Groovy-generated methods
cause = cause.getCause();
}
throw new MethodInvocationException(propertyChangeEvent, cause);
}
}
catch (Exception ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
}
到這裡,我們發現最終調用了BeanWrapperImpl的setValue方法,通過Java的内省機制将Bean所依賴的屬性注入到Bean中,這樣Bean之間的依賴關系就處理完成了,接下來這些Bean就可以被我們直接使用了。
(二)Bean的預執行個體化
我們知道當為Bean配置了lazy-init=false屬性時,IOC容器會在初始化的時候對Bean進行預執行個體化,這時将會提前觸發Bean的依賴注入過程,我們回到AbstractApplicationContext的refresh方法中,這裡是IOC容器初始化的入口,在這個方法中我們可以看到調用了finishBeanFactoryInitialization方法,這個方法将會對非延遲加載的單例Bean進行預執行個體化,代碼如下:
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
// 預執行個體化非延遲加載的單例Bean
finishBeanFactoryInitialization(beanFactory);
...
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
...
// 預執行個體化非延遲加載的單例Bean
beanFactory.preInstantiateSingletons();
}
}
這裡調用了ConfigurableListableBeanFactory接口的preInstantiateSingletons()方法,具體由DefaultListableBeanFactory實作,代碼如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
...
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// 所有Bean的名稱
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 将非延遲加載的單例Bean預執行個體化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
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);
}
}
}
// 觸發單例執行個體化後的回調方法
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
}
分析到這裡我們發現,在預執行個體化的過程中調用了getBean方法來觸發Bean的依賴注入,後續的處理就與前面分析的過程一樣了,通過一系列的處理,Bean的預執行個體化過程就完成了。