死磕Spring原始碼-依賴注入
我們分析了IOC容器的初始化,可以看出初始化其實就是在IoC容器中建立BeanDefinition資料對映,但並沒有對Bean的依賴關係進行注入,依賴注入是使用者第一次向IoC容器索要Bean的時候觸發的,呼叫BeanFactory的getBean方法將觸發依賴注入,這個時候才會建立物件例項,也可以透過設定bean的lazy-init屬性來讓bean的例項化過程在容器初始化的過程就完成,如果透過設定Bean的lazy-init屬性,那麼在容器初始化這個bean的時候就會呼叫getBean去觸發依賴注入。
如果doGetBean方法在當前的IoC容器中找不到Bean,會到雙親BeanFactory中去取,如果當前的雙親容器找不到那就再順著雙親BeanFactory鏈一直向上尋找。
get某一個Bean的時候會依賴注入其所依賴的所有的Bean,觸發getBean的遞迴呼叫,直到取到一個沒有任何依賴的bean為止。
依賴注入實現過程圖:
依賴注入比較重要的兩個方法:createBeanInstance和populateBean
createBeanInstance例項化Bean物件
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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
createBeanInstance中生成了Bean所包含的Java物件,Spring中用SimpleInstantiationStrategy類來生成Bean物件的例項,例項化Java物件的方法有兩種:
1、透過BeanUtils,它使用了JVM的反射功能來生成Java物件例項
2、用CGLIB來生成,CGLIB是一種常用的位元組碼生成器的類庫
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
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(new PrivilegedExceptionAction>() {
@Override
public Constructor> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//透過BeanUtils進行例項化,從這個方法中可以看到具體呼叫了ctor.newInstance()方法
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 使用CGLIB來例項化物件
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
Bean物件生成好了之後,Spring用BeanWrapper來持有建立出來的Bean物件,接下來Spring透過populateBean方法來把這些Bean物件的依賴關係設定好,以完成整個依賴注入的過程。
依賴注入的發生是在BeanWrapper的setPropertyValues中,具體的實現過程在其子類BeanWrapperImpl;createBeanInstance方法返回值就是一個BeanWrapper物件。再把BeanWrapper物件作為一個形參傳入populateBean中。populateBean是對Bean的初始化,依賴注入就發生在這裡。
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
//這裡透過解析BeanDefinition來獲取property值
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
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的名字或型別來完成Bean的autowire
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
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) {
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);
}
populateBean解析BeanDefinition中設定的property值,獲取到Bean的依賴資訊並設定Bean的依賴關係。透過使用BeanDefinitionResolver對BeanDefinition進行解析,然後注入到property中。
resolveValueIfNecessary方法包含了對所有的注入型別的處理,裡面包含各種instanceof的判斷,比如RuntimeBeanReference,Array,List,Map等資料型別,RuntimeBeanReference是在對BeanDefinition進行解析時生成的資料物件,是在載入BeanDefinition時根據配置生成的,如果RuntimeBeanReference是在雙親容器中則從雙親容器中去獲取Bean(透過getBean方法)。
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
MutablePropertyValues mpvs = null;
List original;
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
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;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List 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();
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);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
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();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
完成解析過程後就已經是為依賴注入做好了準備條件,依賴注入的發生是在BeanWrapper的setPropertyValues中,具體的實現過程在其子類BeanWrapperImpl。
setPropertyValue的方法呼叫棧:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/854/viewspace-2799156/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Spring原始碼解析——依賴注入(二)Spring原始碼依賴注入
- Spring原始碼系列:依賴注入-引言Spring原始碼依賴注入
- Spring原始碼系列:依賴注入(三)-屬性注入Spring原始碼依賴注入
- Spring原始碼系列:依賴注入(二)createBeanSpring原始碼依賴注入Bean
- Spring原始碼系列:依賴注入(一)getBeanSpring原始碼依賴注入Bean
- Spring原始碼系列:依賴注入(四)-總結Spring原始碼依賴注入
- Spring 原始碼分析之 bean 依賴注入原理(注入屬性)Spring原始碼Bean依賴注入
- Laravel 依賴注入原始碼解析Laravel依賴注入原始碼
- spring原始碼解析之IOC容器(三)——依賴注入Spring原始碼依賴注入
- Spring依賴注入Spring依賴注入
- Spring依賴注入---Spring依賴注入
- Spring IOC——依賴注入Spring依賴注入
- Spring 依賴注入 DISpring依賴注入
- spring 的依賴注入Spring依賴注入
- React 原始碼中的依賴注入方法React原始碼依賴注入
- Spring系列.依賴注入配置Spring依賴注入
- Spring.Net 依賴注入Spring依賴注入
- 大白話spring依賴注入Spring依賴注入
- Spring 依賴注入的理解Spring依賴注入
- Spring原始碼--debug分析迴圈依賴--構造器注入Spring原始碼
- .NET 透過原始碼深究依賴注入原理原始碼依賴注入
- 死磕Spring之IoC篇 - 單例 Bean 的迴圈依賴處理Spring單例Bean
- Spring原始碼分析(二)bean的例項化和IOC依賴注入Spring原始碼Bean依賴注入
- spring框架學習 依賴注入Spring框架依賴注入
- Spring的依賴注入的方式Spring依賴注入
- spring 依賴注入的學習Spring依賴注入
- Spring依賴注入原理學習Spring依賴注入
- Spring學習(三)依賴注入Spring依賴注入
- 小白都能看懂的 Spring 原始碼揭祕之依賴注入(DI)原始碼分析Spring原始碼依賴注入
- Spring Ioc原始碼分析系列--自動注入迴圈依賴的處理Spring原始碼
- Spring 控制反轉和依賴注入Spring依賴注入
- 分解uber依賴注入庫dig-原始碼分析依賴注入原始碼
- .net core 原始碼分析(9) 依賴注入(DI)-Dependency Injection原始碼依賴注入
- Spring系列第八講 依賴注入之手動注入Spring依賴注入
- 死磕 jdk原始碼之HashMap原始碼分析JDK原始碼HashMap
- angular依賴注入Angular依賴注入
- XUnit 依賴注入依賴注入
- Struts 依賴注入依賴注入