spring 原始碼解讀Spring IOC原理
//建立Bean的例項物件 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { //檢查確認Bean是可例項化的 Class beanClass = resolveBeanClass(mbd, beanName); //使用工廠方法對Bean進行例項化 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()); } if (mbd.getFactoryMethodName() != null) { //呼叫工廠方法例項化 return instantiateUsingFactoryMethod(beanName, mbd, args); } //使用容器的自動裝配方法進行例項化 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) { //配置了自動裝配屬性,使用容器的自動裝配例項化 //容器的自動裝配是根據引數型別匹配Bean的構造方法 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); } //使用預設的無參構造方法例項化 return instantiateBean(beanName, mbd); } //使用預設的無參構造方法例項化Bean物件 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; //獲取系統的安全管理介面,JDK標準的安全管理API if (System.getSecurityManager() != null) { //這裡是一個匿名內建類,根據例項化策略建立例項物件 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { 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) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
經過對上面的程式碼分析,我們可以看出,對使用工廠方法和自動裝配特性的Bean的例項化相當比較清楚,呼叫相應的工廠方法或者引數匹配的構造方法即可完成例項化物件的工作,但是對於我們最常使用的預設無參構造方法就需要使用相應的初始化策略(JDK的反射機制或者CGLIB)來進行初始化了,在方法getInstantiationStrategy().instantiate中就具體實現類使用初始策略例項化物件。
5、SimpleInstantiationStrategy類使用預設的無參構造方法建立Bean例項化物件:
在使用預設的無參構造方法建立Bean的例項化物件時,方法getInstantiationStrategy().instantiate呼叫了SimpleInstantiationStrategy類中的例項化Bean的方法,其原始碼如下:
//使用初始化策略例項化Bean物件 public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { //如果Bean定義中沒有方法覆蓋,則就不需要CGLIB父類類的方法 if (beanDefinition.getMethodOverrides().isEmpty()) { Constructor<?> constructorToUse; synchronized (beanDefinition.constructorArgumentLock) { //獲取物件的構造方法或工廠方法 constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod; //如果沒有構造方法且沒有工廠方法 if (constructorToUse == null) { //使用JDK的反射機制,判斷要例項化的Bean是否是介面 final Class clazz = beanDefinition.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { //這裡是一個匿名內建類,使用反射機制獲取Bean的構造方法 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() { public Constructor run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null); } }); } else { constructorToUse = clazz.getDeclaredConstructor((Class[]) null); } beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Exception ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } //使用BeanUtils例項化,通過反射機制呼叫”構造方法.newInstance(arg)”來進行例項化 return BeanUtils.instantiateClass(constructorToUse); } else { //使用CGLIB來例項化物件 return instantiateWithMethodInjection(beanDefinition, beanName, owner); } }
通過上面的程式碼分析,我們看到了如果Bean有方法被覆蓋了,則使用JDK的反射機制進行例項化,否則,使用CGLIB進行例項化。
instantiateWithMethodInjection方法呼叫SimpleInstantiationStrategy的子類CglibSubclassingInstantiationStrategy使用CGLIB來進行初始化,其原始碼如下:
//使用CGLIB進行Bean物件例項化
public Object instantiate(Constructor ctor, Object[] args) {
//CGLIB中的類
Enhancer enhancer = new Enhancer();
//將Bean本身作為其基類
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
enhancer.setCallbackFilter(new CallbackFilterImpl());
enhancer.setCallbacks(new Callback[] {
NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(),
new ReplaceOverrideMethodInterceptor()
});
//使用CGLIB的create方法生成例項物件
return (ctor == null) ?
enhancer.create() :
enhancer.create(ctor.getParameterTypes(), args);
}
CGLIB是一個常用的位元組碼生成器的類庫,它提供了一系列API實現java位元組碼的生成和轉換功能。我們在學習JDK的動態代理時都知道,JDK的動態代理只能針對介面,如果一個類沒有實現任何介面,要對其進行動態代理只能使用CGLIB。
6、populateBean方法對Bean屬性的依賴注入:
在第3步的分析中我們已經瞭解到Bean的依賴注入分為以下兩個過程:
(1).createBeanInstance:生成Bean所包含的java物件例項。
(2).populateBean :對Bean屬性的依賴注入進行處理。
第4、5步中我們已經分析了容器初始化生成Bean所包含的Java例項物件的過程,現在我們繼續分析生成物件後,Spring IoC容器是如何將Bean的屬性依賴關係注入Bean例項物件中並設定好的,屬性依賴注入的程式碼如下:
//將Bean屬性設定到生成的例項物件上
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
//獲取容器在解析Bean定義資源時為BeanDefiniton中設定的屬性值
PropertyValues pvs = mbd.getPropertyValues();
//例項物件為null
if (bw == null) {
//屬性值不為空
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
//例項物件為null,屬性值也為空,不需要設定屬性值,直接返回
return;
}
}
//在設定屬性之前呼叫Bean的PostProcessor後置處理器
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自動裝配的注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//對autowire自動裝配的處理,根據Bean名稱自動裝配注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根據Bean型別自動裝配注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//檢查容器是否持有用於處理單態模式Bean關閉時的後置處理器
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//Bean例項物件沒有依賴,即沒有繼承基類
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
//從例項物件中提取屬性描述符
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//使用BeanPostProcessor處理器處理屬性值
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
//為要設定的屬性進行依賴檢查
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
//對屬性進行注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
//解析並注入依賴屬性的過程
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
//封裝屬性值
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (System.getSecurityManager()!= null) {
if (bw instanceof BeanWrapperImpl) {
//設定安全上下文,JDK安全機制
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
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;
}
//建立一個Bean定義屬性值解析器,將Bean定義中的屬性值解析為Bean例項物件
//的實際值
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
//為屬性的解析值建立一個拷貝,將拷貝的資料注入到例項物件中
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
//屬性值不需要轉換
if (pv.isConverted()) {
deepCopy.add(pv);
}
//屬性值需要轉換
else {
String propertyName = pv.getName();
//原始的屬性值,即轉換之前的屬性值
Object originalValue = pv.getValue();
//轉換屬性值,例如將引用轉換為IoC容器中例項化物件引用
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();
}
//進行屬性依賴注入
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
分析上述程式碼,我們可以看出,對屬性的注入過程分以下兩種情況:
(1).屬性值型別不需要轉換時,不需要解析屬性值,直接準備進行依賴注入。
(2).屬性值需要進行型別轉換時,如對其他物件的引用等,首先需要解析屬性值,然後對解析後的屬性值進行依賴注入。
對屬性值的解析是在BeanDefinitionValueResolver類中的resolveValueIfNecessary方法中進行的,對屬性值的依賴注入是通過bw.setPropertyValues方法實現的,在分析屬性值的依賴注入之前,我們先分析一下對屬性值的解析過程。
7、BeanDefinitionValueResolver解析屬性值:
當容器在對屬性進行依賴注入時,如果發現屬性值需要進行型別轉換,如屬性值是容器中另一個Bean例項物件的引用,則容器首先需要根據屬性值解析出所引用的物件,然後才能將該引用物件注入到目標例項物件的屬性上去,對屬性進行解析的由resolveValueIfNecessary方法實現,其原始碼如下:
//解析屬性值,對注入型別進行轉換
public Object resolveValueIfNecessary(Object argName, Object value) {
//對引用型別的屬性進行解析
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//呼叫引用型別屬性的解析方法
return resolveReference(argName, ref);
}
//對屬性值是引用容器中另一個Bean名稱的解析
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(evaluate(refName));
//從容器中獲取指定名稱的Bean
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
//對Bean型別屬性的解析,主要是Bean中的內部類
else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd);
}
//對集合陣列型別的屬性解析
else if (value instanceof ManagedArray) {
ManagedArray array = (ManagedArray) value;
//獲取陣列的型別
Class elementType = array.resolvedElementType;
if (elementType == null) {
//獲取陣列元素的型別
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
//使用反射機制建立指定型別的物件
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
//沒有獲取到陣列的型別,也沒有獲取到陣列元素的型別,則直接設定數
//組的型別為Object
else {
elementType = Object.class;
}
}
//建立指定型別的陣列
return resolveManagedArray(argName, (List<?>) value, elementType);
}
//解析list型別的屬性值
else if (value instanceof ManagedList) {
return resolveManagedList(argName, (List<?>) value);
}
//解析set型別的屬性值
else if (value instanceof ManagedSet) {
return resolveManagedSet(argName, (Set<?>) value);
}
//解析map型別的屬性值
else if (value instanceof ManagedMap) {
return resolveManagedMap(argName, (Map<?, ?>) value);
}
//解析props型別的屬性值,props其實就是key和value均為字串的map
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
//建立一個拷貝,用於作為解析後的返回值
Properties copy = new Properties();
for (Map.Entry propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
copy.put(propKey, propValue);
}
return copy;
}
//解析字串型別的屬性值
else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
//獲取屬性的目標型別
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
//對目標型別的屬性進行解析,遞迴呼叫
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
//沒有獲取到屬性的目標物件,則按Object型別返回
else {
return valueObject;
}
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else {
return evaluate(value);
}
}
//解析引用型別的屬性值
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//獲取引用的Bean名稱
String refName = ref.getBeanName();
refName = String.valueOf(evaluate(refName));
//如果引用的物件在父類容器中,則從父類容器中獲取指定的引用物件
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
//從當前的容器中獲取指定的引用Bean物件,如果指定的Bean沒有被例項化
//則會遞迴觸發引用Bean的初始化和依賴注入
else {
Object bean = this.beanFactory.getBean(refName);
//將當前例項化物件的依賴引用物件
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
//解析array型別的屬性
private Object resolveManagedArray(Object argName, List<?> ml, Class elementType) {
//建立一個指定型別的陣列,用於存放和返回解析後的陣列
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
//遞迴解析array的每一個元素,並將解析後的值設定到resolved陣列中,索引為i
Array.set(resolved, i,
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
//解析list型別的屬性
private List resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
//遞迴解析list的每一個元素
resolved.add(
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
//解析set型別的屬性
private Set resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
int i = 0;
//遞迴解析set的每一個元素
for (Object m : ms) {
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));
i++;
}
return resolved;
}
//解析map型別的屬性
private Map resolveManagedMap(Object argName, Map<?, ?> mm) {
Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());
//遞迴解析map中每一個元素的key和value
for (Map.Entry entry : mm.entrySet()) {
Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
Object resolvedValue = resolveValueIfNecessary(
new KeyedArgName(argName, entry.getKey()), entry.getValue());
resolved.put(resolvedKey, resolvedValue);
}
return resolved;
}
通過上面的程式碼分析,我們明白了Spring是如何將引用型別,內部類以及集合型別等屬性進行解析的,屬性值解析完成後就可以進行依賴注入了,依賴注入的過程就是Bean物件例項設定到它所依賴的Bean物件屬性上去,在第7步中我們已經說過,依賴注入是通過bw.setPropertyValues方法實現的,該方法也使用了委託模式,在BeanWrapper介面中至少定義了方法宣告,依賴注入的具體實現交由其實現類BeanWrapperImpl來完成,下面我們就分析依BeanWrapperImpl中賴注入相關的原始碼。
8、BeanWrapperImpl對Bean屬性的依賴注入:
BeanWrapperImpl類主要是對容器中完成初始化的Bean例項物件進行屬性的依賴注入,即把Bean物件設定到它所依賴的另一個Bean的屬性中去,依賴注入的相關原始碼如下:
//實現屬性依賴注入功能
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
//PropertyTokenHolder主要儲存屬性的名稱、路徑,以及集合的size等資訊
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
//keys是用來儲存集合型別屬性的size
if (tokens.keys != null) {
//將屬性資訊拷貝
PropertyTokenHolder getterTokens = new PropertyTokenHolder();
getterTokens.canonicalName = tokens.canonicalName;
getterTokens.actualName = tokens.actualName;
getterTokens.keys = new String[tokens.keys.length - 1];
System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);
Object propValue;
try {
//獲取屬性值,該方法內部使用JDK的內省( Introspector)機制,呼叫屬性//的getter(readerMethod)方法,獲取屬性的值
propValue = getPropertyValue(getterTokens);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "'", ex);
}
//獲取集合型別屬性的長度
String key = tokens.keys[tokens.keys.length - 1];
if (propValue == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
}
//注入array型別的屬性值
else if (propValue.getClass().isArray()) {
//獲取屬性的描述符
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//獲取陣列的型別
Class requiredType = propValue.getClass().getComponentType();
//獲取陣列的長度
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
//獲取陣列以前初始化的值
if (isExtractOldValueForEditor()) {
oldValue = Array.get(propValue, arrayIndex);
}
//將屬性的值賦值給陣列中的元素
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid array index in property path '" + propertyName + "'", ex);
}
}
//注入list型別的屬性值
else if (propValue instanceof List) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//獲取list集合的型別
Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
pd.getReadMethod(), tokens.keys.length);
List list = (List) propValue;
//獲取list集合的size
int index = Integer.parseInt(key);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
//獲取list解析後的屬性值
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
if (index < list.size()) {
//為list屬性賦值
list.set(index, convertedValue);
}
//如果list的長度大於屬性值的長度,則多餘的元素賦值為null
else if (index >= list.size()) {
for (int i = list.size(); i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
list.size() + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
}
//注入map型別的屬性值
else if (propValue instanceof Map) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//獲取map集合key的型別
Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(
pd.getReadMethod(), tokens.keys.length);
//獲取map集合value的型別
Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
pd.getReadMethod(), tokens.keys.length);
Map map = (Map) propValue;
//解析map型別屬性key值
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
//解析map型別屬性value值
Object convertedMapValue = convertIfNecessary(
propertyName, oldValue, pv.getValue(), mapValueType,
new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));
//將解析後的key和value值賦值給map集合屬性
map.put(convertedMapKey, convertedMapValue);
}
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");
}
}
//對非集合型別的屬性注入
else {
PropertyDescriptor pd = pv.resolvedDescriptor;
if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {
pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//無法獲取到屬性名或者屬性沒有提供setter(寫方法)方法
if (pd == null || pd.getWriteMethod() == null) {
//如果屬性值是可選的,即不是必須的,則忽略該屬性值
if (pv.isOptional()) {
logger.debug("Ignoring optional value for property '" + actualName +
"' - property not found on bean class [" + getRootClass().getName() + "]");
return;
}
//如果屬性值是必須的,則丟擲無法給屬性賦值,因為每天提供setter方法異常
else {
PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());
throw new NotWritablePropertyException(
getRootClass(), this.nestedPath + propertyName,
matches.buildErrorMessage(), matches.getPossibleMatches());
}
}
pv.getOriginalPropertyValue().resolvedDescriptor = pd;
}
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() && pd.getReadMethod() != null) {
//獲取屬性的getter方法(讀方法),JDK內省機制
final Method readMethod = pd.getReadMethod();
//如果屬性的getter方法不是public訪問控制權限的,即訪問控制權限比較嚴格,
//則使用JDK的反射機制強行訪問非public的方法(暴力讀取屬性值)
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
!readMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
//匿名內部類,根據許可權修改屬性的讀取控制限制
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
}
else {
readMethod.setAccessible(true);
}
}
try {
//屬性沒有提供getter方法時,呼叫潛在的讀取屬性值//的方法,獲取屬性值
if (System.getSecurityManager() != null) {
oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return readMethod.invoke(object);
}
}, acc);
}
else {
oldValue = readMethod.invoke(object);
}
}
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 + propertyName + "'", ex);
}
}
}
//設定屬性的注入值
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
//根據JDK的內省機制,獲取屬性的setter(寫方法)方法
final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
pd.getWriteMethod());
//如果屬性的setter方法是非public,即訪問控制權限比較嚴格,則使用JDK的反射機制,
//強行設定setter方法可訪問(暴力為屬性賦值)
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
//如果使用了JDK的安全機制,則需要許可權驗證
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
writeMethod.setAccessible(true);
return null;
}
});
}
else {
writeMethod.setAccessible(true);
}
}
final Object value = valueToApply;
if (System.getSecurityManager() != null) {
try {
//將屬性值設定到屬性上去
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
writeMethod.invoke(object, value);
return null;
}
}, acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
writeMethod.invoke(this.object, value);
}
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
}
else {
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
}
}
catch (Exception ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
}
通過對上面注入依賴程式碼的分析,我們已經明白了Spring IoC容器是如何將屬性的值注入到Bean例項物件中去的:
(1).對於集合型別的屬性,將其屬性值解析為目標型別的集合後直接賦值給屬性。
(2).對於非集合型別的屬性,大量使用了JDK的反射和內省機制,通過屬性的getter方法(reader method)獲取指定屬性注入以前的值,同時呼叫屬性的setter方法(writer method)為屬性設定注入後的值。看到這裡相信很多人都明白了Spring的setter注入原理。
至此Spring IoC容器對Bean定義資原始檔的定位,載入、解析和依賴注入已經全部分析完畢,現在Spring IoC容器中管理了一系列靠依賴關係聯絡起來的Bean,程式不需要應用自己手動建立所需的物件,Spring IoC容器會在我們使用的時候自動為我們建立,並且為我們注入好相關的依賴,這就是Spring核心功能的控制反轉和依賴注入的相關功能。
1、介紹
通過前面4篇文章對Spring IoC容器的原始碼分析,我們已經基本上了解了Spring IoC容器對Bean定義資源的定位、讀入和解析過程,同時也清楚了當使用者通過getBean方法向IoC容器獲取被管理的Bean時,IoC容器對Bean進行的初始化和依賴注入過程,這些是Spring IoC容器的基本功能特性。Spring IoC容器還有一些高階特性,如使用lazy-init屬性對Bean預初始化、FactoryBean產生或者修飾Bean物件的生成、IoC容器初始化Bean過程中使用BeanPostProcessor後置處理器對Bean宣告週期事件管理和IoC容器的autowiring自動裝配功能等。
2、Spring IoC容器的lazy-init屬性實現預例項化:
通過前面我們對IoC容器的實現和工作原理分析,我們知道IoC容器的初始化過程就是對Bean定義資源的定位、載入和註冊,此時容器對Bean的依賴注入並沒有發生,依賴注入主要是在應用程式第一次向容器索取Bean時,通過getBean方法的呼叫完成。
當Bean定義資源的<Bean>元素中配置了lazy-init屬性時,容器將會在初始化的時候對所配置的Bean進行預例項化,Bean的依賴注入在容器初始化的時候就已經完成。這樣,當應用程式第一次向容器索取被管理的Bean時,就不用再初始化和對Bean進行依賴注入了,直接從容器中獲取已經完成依賴注入的現成Bean,可以提高應用第一次向容器獲取Bean的效能。
下面我們通過程式碼分析容器預例項化的實現過程:
(1).refresh()
先從IoC容器的初始會過程開始,通過前面文章分析,我們知道IoC容器讀入已經定位的Bean定義資源是從refresh方法開始的,我們首先從AbstractApplicationContext類的refresh方法入手分析,原始碼如下:
//容器初始化的過程,讀入Bean定義資源,並解析註冊
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//呼叫容器準備重新整理的方法,獲取容器的當時時間,同時給容器設定同步標識
prepareRefresh();
//告訴子類啟動refreshBeanFactory()方法,Bean定義資原始檔的載入從
//子類的refreshBeanFactory()方法啟動
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//為BeanFactory配置容器特性,例如類載入器、事件處理器等
prepareBeanFactory(beanFactory);
try {
//為容器的某些子類指定特殊的BeanPost事件處理器
postProcessBeanFactory(beanFactory);
//呼叫所有註冊的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
//為BeanFactory註冊BeanPost事件處理器.
//BeanPostProcessor是Bean後置處理器,用於監聽容器觸發的事件
registerBeanPostProcessors(beanFactory);
//初始化資訊源,和國際化相關.
initMessageSource();
//初始化容器事件傳播器.
initApplicationEventMulticaster();
//呼叫子類的某些特殊Bean初始化方法
onRefresh();
//為事件傳播器註冊事件監聽器.
registerListeners();
//這裡是對容器lazy-init屬性進行處理的入口方法
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命週期事件處理器,併發布容器的生命週期事件
finishRefresh();
}
catch (BeansException ex) {
//銷燬以建立的單態Bean
destroyBeans();
//取消refresh操作,重置容器的同步標識.
cancelRefresh(ex);
throw ex;
}
}
}
在refresh方法中ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();啟動了Bean定義資源的載入、註冊過程,而finishBeanFactoryInitialization方法是對註冊後的Bean定義中的預例項化(lazy-init=false,Spring預設就是預例項化,即為true)的Bean進行處理的地方。
(2).finishBeanFactoryInitialization處理預例項化Bean:
當Bean定義資源被載入IoC容器之後,容器將Bean定義資源解析為容器內部的資料結構BeanDefinition註冊到容器中,AbstractApplicationContext類中的finishBeanFactoryInitialization方法對配置了預例項化屬性的Bean進行預初始化過程,原始碼如下:
//對配置了lazy-init屬性的Bean進行預例項化處理
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//這是Spring3以後新加的程式碼,為容器指定一個轉換服務(ConversionService)
//在對某些Bean屬性進行轉換時使用
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
//為了型別匹配,停止使用臨時的類載入器
beanFactory.setTempClassLoader(null);
//快取容器中所有註冊的BeanDefinition元資料,以防被修改
beanFactory.freezeConfiguration();
//對配置了lazy-init屬性的單態模式Bean進行預例項化處理
beanFactory.preInstantiateSingletons();
}
ConfigurableListableBeanFactory是一個介面,其preInstantiateSingletons方法由其子類DefaultListableBeanFactory提供。
(3)、DefaultListableBeanFactory對配置lazy-init屬性單態Bean的預例項化:
1//對配置lazy-init屬性單態Bean的預例項化
2public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
//在對配置lazy-init屬性單態Bean的預例項化過程中,必須多執行緒同步,以確保資料一致性
synchronized (this.beanDefinitionMap) {
for (String beanName : this.beanDefinitionNames) {
//獲取指定名稱的Bean定義
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Bean不是抽象的,是單態模式的,且lazy-init屬性配置為false
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名稱的bean是建立容器的Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,當Bean名稱前面加”&”符號
//時,獲取的是產生容器物件本身,而不是容器產生的Bean.
//呼叫getBean方法,觸發容器對Bean例項化和依賴注入過程
final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
//標識是否需要預例項化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
//一個匿名內部類
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean) factory).isEagerInit();
}
}, getAccessControlContext());