【Spring原始碼閱讀】populateBean實現 依賴注入原始碼解析
阿新 • • 發佈:2018-12-27
在完成Bean例項化後,Spring容器會給這個Bean注入相關的依賴Bean,在原始碼中,這一步通過類AbstractAutowireCapableBeanFactory中的populateBean
方法完成。
測試程式碼
下面開始進入原始碼分析之前,先基於以下例項進行:
// 基礎屬性類
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
}
// 需要進行依賴注入的類
public class TestBean {
private Student student;
public void echo() {
System. out.println("I'm a student : " + student);
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
配置程式碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="com.jeanheo.model.Student" id="student">
<constructor-arg index="0" value="test"/>
</bean>
<bean class="com.jeanheo.model.TestBean2" id="testBean">
<property name="student" ref="student"/>
</bean>
</beans>
具體測試程式碼:
public class BaseTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
TestBean testBean = context.getBean("testBean", TestBean.class);
testBean.echo();
}
}
原始碼分析
下面基於TestBean的依賴注入進行分析相關原始碼:
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// pvs是一個MutablePropertyValues例項,裡面實現了PropertyValues介面,提供屬性的讀寫操作實現,同時可以通過呼叫建構函式實現深拷貝
// 在本例中,裡面存在一個propertyValueList,裡面只有一個propertyValue:key->value="student"->RuntimeBeanReference("<student>")
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// 空物件直接返回
return;
}
}
// 給InstantiationAwareBeanPostProcessors最後一次機會在屬性注入前修改Bean的屬性值
// 具體通過呼叫postProcessAfterInstantiation方法,如果呼叫返回false,表示不必繼續進行依賴注入,直接返回
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;
}
// 根據Bean配置的依賴注入方式完成注入,預設是0,即不走以下邏輯,所有的依賴注入都需要在xml檔案中有顯式的配置
// 如果設定了相關的依賴裝配方式,會遍歷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) {
// 過濾出所有需要進行依賴檢查的屬性編輯器
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) {
// 檢查是否滿足相關依賴關係,對應的depends-on屬性,需要確保所有依賴的Bean先完成初始化
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 將pvs上所有的屬性填充到BeanWrapper對應的Bean例項中,注意到這一步,TestBean的student屬性還是RuntimeBeanReference,即還未解析實際的Student例項
applyPropertyValues(beanName, mbd, bw, pvs);
}
在具體分析原始碼如何將將pvs上所有的屬性填充到BeanWrapper對應的Bean例項中之前,先看看autowireByName和autowireByType這兩步是怎麼實現的:
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 根據bw的PropertyDescriptors,遍歷出所有可寫的(即set方法存在),存在於BeanDefinition裡的PropertyValues,且不是簡單屬性的屬性名
// 簡單屬性的判定參照下面方法,主要涵蓋基本型別及其包裝類,Number,Date等
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 遞迴初始化相關Bean
Object bean = getBean(propertyName);
// 根據名稱新增到pvs中
pvs.add(propertyName, bean);
// 註冊依賴關係
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("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");
}
}
}
}
// 簡單型別判定
public static boolean isSimpleValueType(Class<?> clazz) {
return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
CharSequence.class.isAssignableFrom(clazz) ||
Number.class.isAssignableFrom(clazz) ||
Date.class.isAssignableFrom(clazz) ||
clazz.equals(URI.class) || clazz.equals(URL.class) ||
clazz.equals(Locale.class) || clazz.equals(Class.class);
}
類似的,下面再看看autowireByType的實現
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 獲取型別轉換器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
// 類似的,過濾出滿足裝配條件的Bean屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
如果是Object型別不進行裝配
if (!Object.class.equals(pd.getPropertyType())) {
// 獲取相關的寫方法引數
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// 定義是否允許懶載入。
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
//
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 這裡會根據傳入desc裡的入參型別,作為依賴裝配的型別
// 再根據這個型別在BeanFacoty中查詢所有類或其父類相同的BeanName
// 最後根據BeanName獲取或初始化相應的類,然後將所有滿足條件的BeanName填充到autowiredBeanNames中。
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 註冊依賴
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("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);
}
}
}
具體pvs上所有的屬性填充到BeanWrapper對應的Bean例項中實現如下:
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) {
((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;
}
// 建立BeanDefinitionValueResolver解析器,用來解析未被解析的PropertyValue。
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// 開始遍歷檢查original中的屬性,對未被解析的先解析/已解析的直接加入deepCopy中,最後再填充到具體的Bean例項中
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();
// 核心邏輯,解析獲取實際的值
// 對於RuntimeReference,會解析拿到具體的beanName,最終通過getBean(beanName)拿到具體的物件
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);
}
}
上面大致的描述了Spring完成依賴注入的流程,中間具體還有很多細緻的複雜處理細節,但通過上述的原始碼解讀,我們大致瞭解了整個Spring容器的依賴注入實現基礎流程。