正文 doCreateBean() 主要用於完成 bean 的創建和初始化工作,我們可以將其分為四個過程: 最全面的Java面試網站 createBeanInstance() 實例化 bean populateBean() 屬性填充 迴圈依賴的處理 initializeBean() 初始化 bean ...
正文
doCreateBean()
主要用於完成 bean 的創建和初始化工作,我們可以將其分為四個過程:
createBeanInstance()
實例化 beanpopulateBean()
屬性填充- 迴圈依賴的處理
initializeBean()
初始化 bean
第一個過程實例化 bean在前面一篇博客中已經分析完了,這篇博客開始分析 屬性填充,也就是 populateBean()
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
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;
//返回值為是否繼續填充bean
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//如果後處理器發出停止填充命令則終止後續的執行
if (!continueWithPropertyPopulation) {
return;
}
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) {
//依賴檢查,對應depends-on屬性,3.0已經棄用此屬性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
//將屬性應用到bean中
//將所有ProtertyValues中的屬性填充至BeanWrapper中。
applyPropertyValues(beanName, mbd, bw, pvs);
}
我們來分析下populateBean的流程:
(1)首先進行屬性是否為空的判斷
(2)通過調用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)方法來控製程序是否繼續進行屬性填充
(3)根據註入類型(byName/byType)提取依賴的bean,並統一存入PropertyValues中
(4)應用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName)方法,對屬性獲取完畢填充前的再次處理,典型的應用是RequiredAnnotationBeanPostProcesser類中對屬性的驗證
(5)將所有的PropertyValues中的屬性填充至BeanWrapper中
上面步驟中有幾個地方是我們比較感興趣的,它們分別是依賴註入(autowireByName/autowireByType)以及屬性填充,接下來進一步分析這幾個功能的實現細節
分享一份大彬精心整理的大廠面試手冊,包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等高頻面試題,非常實用,有小伙伴靠著這份手冊拿過位元組offer~
需要的小伙伴可以自行下載:
自動註入
Spring 會根據註入類型( byName / byType )的不同,調用不同的方法(autowireByName()
/ autowireByType()
)來註入屬性值。
autowireByName()
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 獲取 Bean 對象中非簡單屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// 如果容器中包含指定名稱的 bean,則將該 bean 註入到 bean中
if (containsBean(propertyName)) {
// 遞歸初始化相關 bean
Object bean = getBean(propertyName);
// 為指定名稱的屬性賦予屬性值
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");
}
}
}
}
該方法邏輯很簡單,獲取該 bean 的非簡單屬性,什麼叫做非簡單屬性呢?就是類型為對象類型的屬性,但是這裡並不是將所有的對象類型都都會找到,比如 8 個原始類型,String 類型 ,Number類型、Date類型、URL類型、URI類型等都會被忽略,如下:
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
這裡獲取的就是需要依賴註入的屬性。
autowireByName()函數的功能就是根據傳入的參數中的pvs中找出已經載入的bean,並遞歸實例化,然後加入到pvs中
autowireByType
autowireByType與autowireByName對於我們理解與使用來說複雜程度相似,但是實現功能的複雜度卻不一樣,我們看下方法代碼:
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);
//尋找bw中需要依賴註入的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (!Object.class.equals(pd.getPropertyType())) {
//探測指定屬性的set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//解析指定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);
}
}
}
根據名稱第一步與根據屬性第一步都是尋找bw中需要依賴註入的屬性,然後遍歷這些屬性並尋找類型匹配的bean,其中最複雜就是尋找類型匹配的bean。spring中提供了對集合的類型註入支持,如使用如下註解方式:
@Autowired
private List<Test> tests;
這種方式spring會把所有與Test匹配的類型找出來並註入到tests屬性中,正是由於這一因素,所以在autowireByType函數,新建了局部遍歷autowireBeanNames,用於存儲所有依賴的bean,如果只是對非集合類的屬性註入來說,此屬性並無用處。
對於尋找類型匹配的邏輯實現是封裝在了resolveDependency函數中,其實現如下:
public Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (descriptor.getDependencyType().equals(ObjectFactory.class)) {
//ObjectFactory類註入的特殊處理
return new DependencyObjectFactory(descriptor, beanName);
}
else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) {
//javaxInjectProviderClass類註入的特殊處理
return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
}
else {
//通用處理邏輯
return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter);
}
}
protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
/*
* 用於支持Spring中新增的註解@Value
*/
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//如果解析器沒有成功解析,則需要考慮各種情況
//屬性是數組類型
if (type.isArray()) {
Class<?> componentType = type.getComponentType();
//根據屬性類型找到beanFactory中所有類型的匹配bean,
//返回值的構成為:key=匹配的beanName,value=beanName對應的實例化後的bean(通過getBean(beanName)返回)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
if (matchingBeans.isEmpty()) {
//如果autowire的require屬性為true而找到的匹配項卻為空則只能拋出異常
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
//通過轉換器將bean的值轉換為對應的type類型
return converter.convertIfNecessary(matchingBeans.values(), type);
}
//屬性是Collection類型
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> elementType = descriptor.getCollectionType();
if (elementType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
}
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return converter.convertIfNecessary(matchingBeans.values(), type);
}
//屬性是Map類型
else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> keyType = descriptor.getMapKeyType();
if (keyType == null || !String.class.isAssignableFrom(keyType)) {
if (descriptor.isRequired()) {
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
"] must be assignable to [java.lang.String]");
}
return null;
}
Class<?> valueType = descriptor.getMapValueType();
if (valueType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
}
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, "", descriptor);
}
return null;
}
if (matchingBeans.size() > 1) {
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
}
return matchingBeans.get(primaryBeanName);
}
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
}
//已經確定只有一個匹配項
return entry.getValue();
}
}
主要就是通過Type從BeanFactory中找到對應的benaName,然後通過getBean獲取實例
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//在BeanFactory找到所有Type類型的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
//遍歷所有的beanName,通過getBean獲取
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
//
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
return result;
}
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
if (!(beanInstance instanceof NullBean)) {
candidates.put(candidateName, beanInstance);
}
}
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
//通過類型找到beanName,然後再找到其實例
return beanFactory.getBean(beanName);
}
applyPropertyValues
程式運行到這裡,已經完成了對所有註入屬性的獲取,但是獲取的屬性是以PropertyValues形式存在的,還並沒有應用到已經實例化的bean中,這一工作是在applyPropertyValues中。繼續跟蹤到方法體中:
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;
//如果mpvs中的值已經被轉換為對應的類型那麼可以直接設置到beanwapper中
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 {
//如果pvs並不是使用MutablePropertyValues封裝的類型,那麼直接使用原始的屬性獲取方法
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<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();
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);
}
}
我們來看看具體的屬性賦值過程
public class MyTestBean {
private String name ;
public MyTestBean(String name) {
this.name = name;
}
public MyTestBean() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<bean id="myTestBean" class="dabin.spring01.MyTestBean">
<property name="name" value="dabin"></property>
</bean>
如上 bw.setPropertyValues 最終都會走到如下方法
@Override
public void setValue(final @Nullable Object value) throws Exception {
//獲取writeMethod,也就是我們MyTestBean的setName方法
final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
ReflectionUtils.makeAccessible(writeMethod);
//通過反射調用方法進行賦值
writeMethod.invoke(getWrappedInstance(), value);
}
}
就是利用反射進行調用對象的set方法賦值
至此,doCreateBean()
第二個過程:屬性填充 已經分析完成了,下篇分析第三個過程:迴圈依賴的處理,其實迴圈依賴並不僅僅只是在 doCreateBean()
中處理,其實在整個載入 bean 的過程中都有涉及,所以下篇內容並不僅僅只局限於 doCreateBean()
。