上篇(spring源碼學習_bean工廠的初始化)有說到,bean工廠初始化的最後一步就是將所有剩下的,在beanDefinitionMap中註冊的,需要被實例化的bean全部實例化。其實例化過程最終是又 getBean 方法完成的,這裏我們就重點看看getBean方法。
1.bean的實例化過程
public<T> T getBean(String name,@Nullable Class<T> requiredType,@Nullable Object...args)throws BeansException{
return doGetBean(name,requiredType,args,false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//這裏去掉工廠bean的前綴或者將別名轉化爲規範名
final String beanName = transformedBeanName(name);
Object bean;
//這裏嘗試直接從singletonObjects(單例池)中獲取bean的實例
//最終被實例化的單例bean,都會被存放在singletonObjects中
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//如果是工廠bean,獲取工廠bean創建的bean,普通bean則直接返回
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//如果這個bean已經在創建了,則拋出異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//獲取父工廠
BeanFactory parentBeanFactory = getParentBeanFactory();
//當父工廠存在時,將實例化任務交給父工廠
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//......省略
//這裏調用了父工廠的getBean方法
}
if (!typeCheckOnly) {
//將這個bean標記爲已實例化狀態
markBeanAsCreated(beanName);
}
try {
//獲取到這個bean的 beanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//這裏檢查了這個bean是否是Abstract的,是則拋出異常
checkMergedBeanDefinition(mbd, beanName, args);
//獲取到這個bean的依賴信息
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 + "'");
}
//將依賴信息註冊到 dependenciesForBeanMap 中
//Map<String, Set<String>> dependenciesForBeanMap 用於存放bean的依賴信息
registerDependentBean(dep, beanName);
try {
//遞歸實例化依賴的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//當所有的依賴均被實例化後,開始創建這個bean的實例
//這裏是單例bean的初始化
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//......後面省略
return (T) bean;
}
1. getBean方法首先會調用getSingleton(beanName)方法,來判斷工廠中是否已經存在該bean的實例化對象,有則直接返回。
2. 沒有則會檢查是否存在父工廠,如果有,則將實例化bean的任務交給父工廠來完成。
3. 上面過程均失敗後,就會嘗試着創建一個bean的實例。這時會獲取到一個bean的beanDefinition,beanDefinition中包含了這個bean的相關信息。
4. spring通過beanDefinition獲取到他的依賴信息,並遞歸的將其所有的依賴實例化。需要注意的是,這裏的依賴(dependsOn)指的並不是我們bean中需要自動注入的bean。而是@DependsOn註解標註的bean,指明該bean必須優先於本bean被實例化。
5. 所有的依賴(dependsOn)均已被實例化後,調用createBean方法對bean進行實例化。
spring在做了一系列的準備工作後,最後調用了 createBean方法進行bean的實例化操作
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//這裏實例化了bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//......省略部分不重要代碼
// Initialize the bean instance.
Object exposedObject = bean;
try {
//這裏裝配了bean
populateBean(beanName, mbd, instanceWrapper);
//進行初始化操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
//。。。。。。省略
}
return exposedObject;
}
這裏可以看到,createBean調用了doCreateBean方法,主要完成了三個方面的工作,
1. 找到創建這個實例的構造法方法,並通過這個構造方法創建這個實例,我們不細說。
2. 調用populateBaen方法裝配bean,我們的@Autowried註解將會在這裏發揮作用。
3. 最後就是對裝配好的bean進行初始化操作。
2.bean的自動裝配
這裏只展示populateBean方法部分重要的代碼
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//......省略了部分參數檢查和裝配的前置操作代碼
//這裏獲取到 beanDefinition的 PropertyValues屬性
//PropertyValues是一個用來表示Bean屬性的對象,其中定義了屬性的名字和值等信息
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//這裏獲取到自動注入的類型 byName 或是 byType
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
//這裏通過byName 或是 byType的方式獲取到bean依賴的實例
//並將獲取到的依賴的實例註冊到 PropertyValues屬性中 也就是這裏的newPvs
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
//賦值給pvs
pvs = newPvs;
}
//這裏獲取到 BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//其中實現了 InstantiationAwareBeanPostProcessor接口的就有 AutowiredAnnotationBeanPostProcessor
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//關鍵的看這裏
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
這裏可以看到 spring已經獲取到了這個bean的所有依賴的實例,並將其註冊到 beanDefinition的PropertyValues中。最後調用了postProcessPropertyValues方法,完成最後的裝配工作。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//這裏獲取到bean 自動注入的元數據
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//進行注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
private InjectionMetadata findAutowiringMetadata(Class<?> clazz) {
// 先找緩存
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(clazz);
if (metadata == null) {
//緩存沒有,調用buildAutowiringMetadata方法構建
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(clazz, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//這裏處理所有需要被自動注入的屬性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//獲取到所有要被自動注入的屬性
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
//這裏排除靜態屬性
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
//註冊
currElements.add(new AutowiredFieldElement(field, required));
}
});
//......省略了方法的自動注入
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
//將註冊好的InjectionElement集合添加到InjectionMetadata中。
return InjectionMetadata.forElements(elements, clazz);
}
這裏的重點就是調用了 findAutowiredAnnotation 方法,找到了所有需要被自動注入的屬性,並將其封裝在InjectionMetadata對象中返回,最終由InjectionMetadata 的 inject進行注入。
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
//這裏匹配所有自動注入類型的註解
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
通過斷點可以看到,自動注入類型的註解 有兩個,分別是@Autowired和@value。也就是說,標註有這兩個註解的屬性就會被認爲是需要被自動注入的屬性,從而被返回。
到了這裏,bean的自動注入過程也就結束了。
最後通過一個圖,我們看看整體的流程