前言
createBean進(jìn)行了一些創(chuàng)建Bean實例前的工作:
- 檢查當(dāng)前BeanDefinition的Class是否可以被解析.
- 檢查當(dāng)前BeanDefinition的Lookup method是否存在,并且確認(rèn)重載狀態(tài).
- 激活Bean實例化前的后置處理器.
隨后,進(jìn)行
doCreateBean的調(diào)用.那么本文就來分析doCreateBean的代碼邏輯.
doCreateBean的總體流程
- 根據(jù)當(dāng)前Bean的構(gòu)造策略進(jìn)行實例化,此時的bean未進(jìn)行依賴注入: createBeanInstance.
-
解析Bean中被Spring注解標(biāo)記的成員變量,如
@AutoWired、@Value、Resource: applyMergedBeanDefinitionPostProcessors. - 判斷是否要暴露早期引用的bean,為了解決循環(huán)依賴: addSingletonFactory.
- 填充bean實例屬性: populateBean.
- 生命周期函數(shù)回調(diào): initializeBean.
- 判斷在循環(huán)依賴的情況下Bean的引用是否一致: allowRawInjectionDespiteWrapping
- 注冊銷毀方法: registerDisposableBeanIfNecessary
1. 根據(jù)當(dāng)前Bean的構(gòu)造策略進(jìn)行實例化
在講Bean的實例化前,需要簡單了解一下什么是
BeanWrapper.
1.1 BeanWrapper
JavaDoc: 提供用于分析和操作標(biāo)準(zhǔn)JavaBean的操作:獲得和設(shè)置屬性值(單獨或批量),獲取屬性描述符以及查詢屬性的可讀性/可寫性的能力。
此接口支持嵌套屬性,使子屬性上的屬性設(shè)置達(dá)到無限深度.
來看看接口清單.
public interface BeanWrapper extends ConfigurablePropertyAccessor {
// 指定數(shù)組和集合自動增長的限制。默認(rèn)不限制,即無限.
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
// 返回數(shù)組和集合自動增長的限制.
int getAutoGrowCollectionLimit();
// 返回當(dāng)前BeanWrapper包裝的Bean實例
Object getWrappedInstance();
// 返回當(dāng)前BeanWrapper包裝的Bean類型-Class
Class<?> getWrappedClass();
// 獲取包裝對象的PropertyDescriptors(由標(biāo)準(zhǔn)JavaBean自省確定)
PropertyDescriptor[] getPropertyDescriptors();
// 獲取包裝對象的PropertyDescriptor
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
}
簡單來說,通過這個接口視圖,可以獲取Bean的信息.例如:對象實例、Class、Property.
OK,簡單了解過后,我們來看看實例化Bean的第一步-createBeanInstance,調(diào)用構(gòu)造函數(shù)獲取一個對象實例。注意,這個對象實例并未是完整的Bean.
- AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// bean實例化包裝類
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 從未完成創(chuàng)建的包裝bean緩存中清理并獲取相關(guān)的包裝bean實例,單例,不可以重復(fù)
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 創(chuàng)建bean的方式有三種:
// 1.Factory method 2.constructor 3. supplier
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 獲取被包裝的Bean,后續(xù)對bean的改動等于對wrapper進(jìn)行改動,即對wrapper的改動也會改動bean
Object bean = instanceWrapper.getWrappedInstance();
// 獲取實例化對象的類型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
舉例說明: 假設(shè)有一個Bean是這樣定義的.
@Controller
public class HelloController {
@Autowired
private HelloService helloService;
public void hello(){
System.out.println(helloService.hello()+",this is controller");
}
}
那么當(dāng)我們getBean("helloController"),我們是希望
HelloController中的helloService是被實例化的(依賴注入).這時,我們才認(rèn)為這是一個完整的Bean.而createBeanInstance執(zhí)行完后,僅僅是new HelloController而已,此時并未將helloService注入進(jìn)來.(便于理解,其實Spring會做較為復(fù)雜的推斷.)
- AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 獲取Class對象,前面在createBean已經(jīng)進(jìn)行過解析了,這里會直接從mbd.getBeanClass()返回
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 檢查是否可以破環(huán)private的保護(hù)進(jìn)行反射創(chuàng)建實例
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());
}
// 是否通過lambda的方式進(jìn)行創(chuàng)建.在AbstractBeanDefinition中存儲了此值.
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 通過工廠方法創(chuàng)建,factory-method
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
// 空參構(gòu)造
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 如果已緩存的解析構(gòu)造函數(shù)或者factoryMethod不為空
// 那么可以利用構(gòu)造函數(shù)解析
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 自動注入,調(diào)用構(gòu)造函數(shù)自動注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默認(rèn)的構(gòu)造函數(shù)構(gòu)造
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 根據(jù)參數(shù)解析確定構(gòu)造函數(shù)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 解析的構(gòu)造器不為空 | 注入類型為AUTOWIRE_CONSTRUCTOR | 有參 | 傳入的參數(shù)不為空
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 進(jìn)行對象實例化
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 如果沒有推斷出特殊的構(gòu)造方法,使用這個默認(rèn)的模式
// 無參的默認(rèn)構(gòu)造方法,內(nèi)部使用JDK的反射.
return instantiateBean(beanName, mbd);
}
這里的邏輯在依賴注入概覽的時候大概講過,現(xiàn)在來重溫一篇:
- 獲取Class對象,校驗是否為public、如果不是再判斷是否為可以無視
private的,也就是能否獲取private的授權(quán).- 推斷構(gòu)造方法.查看BeanDefinition是否提供了類初始化的
Supplier(lambda).如果提供,按照此方法進(jìn)行實例化.- 查看BeanDefinition是否需要工廠方法進(jìn)行初始化,如果是,使用
factory-method進(jìn)行初始化.- 查看BeanDefinition是否已經(jīng)解析過構(gòu)造方法,如果
constructorArgumentsResolved為true,那么直接使用解析好的構(gòu)造方法進(jìn)行實例化.- 如果都沒有,那么看看構(gòu)造注入策略是否為構(gòu)造注入,并且是有參的形式.如果符合.進(jìn)行自動注入
autowireConstructor(beanName, mbd, ctors, args)- 如果以上條件都不符合,那么使用默認(rèn)的JDK無參構(gòu)造方法-
instantiateBean
- AbstractAutowireCapableBeanFactory#instantiateBean
根據(jù)初始化策略獲取實例進(jìn)行初始化,默認(rèn)為
SimpleInstantiationStrategy
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 從這里開始調(diào)用反射,獲取當(dāng)前的初始化策略,進(jìn)行初始化.
// 默認(rèn)使用 SimpleInstantiationStrategy.instantiate
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
- SimpleInstantiationStrategy#instantiate
通常我們的Bean都會進(jìn)入這種加載策略模式.在這里Spring獲取當(dāng)前BeanDefinition的構(gòu)造函數(shù),然后調(diào)用
BeanUtils.instantiateClass(constructorToUse);,這里其實就是使用反射獲取實例了。
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果Bean中的方法沒有重寫,則不需要CGLIB來重寫
// 通常這種情況會在 lookup method 和 replace method中
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 獲取對象的構(gòu)造方法或者工廠方法
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(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
// 獲取默認(rèn)的構(gòu)造方法
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// newInstance
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// 使用CGLIB進(jìn)行動態(tài)代理
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
2. 解析Bean中被Spring注解標(biāo)記的成員變量
進(jìn)行對象初始化的步驟后,Spring開始解析當(dāng)前Bean中被
@Autowired注解標(biāo)記的成員變量,這個工作交由applyMergedBeanDefinitionPostProcessors中調(diào)用的MergedBeanDefinitionPostProcessor來完成.
// 調(diào)用BeanDefinition屬性合并后完成的BeanPostProcessor->MergedBeanDefinitionPostProcessor
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// @Value、@Autowired的注解解析入口
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
- AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
applyMergedBeanDefinitionPostProcessors主要工作是通過MergedBeanDefinitionPostProcessor接口的實現(xiàn)類來記錄一些Spring需要識別的成員變量.
例如:
AutowiredAnnotationBeanPostProcessor負(fù)責(zé)找到被@Autowired、Value所標(biāo)注的成員變量.
CommonAnnotationBeanPostProcessor負(fù)責(zé)找到被@Resource、@PostConstruct、@PreDestroy標(biāo)記的成員變量.
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// AutowiredAnnotationBeanPostProcessor實現(xiàn)了MergedBeanDefinitionPostProcessor接口.
// 該PostPorcessor會將被@Autowired、@Value標(biāo)記的成員變量進(jìn)行記錄.
// CommonAnnotationBeanPostProcessor也是MergedBeanDefinitionPostProcessor的一個實現(xiàn).
// 該類負(fù)責(zé)記錄@Resource、@PostConstruct、@PreDestroy.
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
2.1 Spring中的責(zé)任鏈模式
這里由于篇幅原因,就不對
CommonAnnotationBeanPostProcessor做詳細(xì)介紹了,Spring在applyMergedBeanDefinitionPostProcessors中使用了責(zé)任鏈模式,對實現(xiàn)了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor發(fā)送請求,每個BeanPostProcessor接收到參數(shù)后,執(zhí)行自己的專屬任務(wù).
2.2 AutowiredAnnotationBeanPostProcessor
- 構(gòu)造函數(shù)
在構(gòu)造函數(shù)中,AutowiredAnnotationBeanPostProcessor在
autowiredAnnotationTypes中加入了需要識別的注解類型-@Autowired、@Value、@Inject.
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} annotation.
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.<br>
* 為Spring的標(biāo)準(zhǔn)@Autowired注解創(chuàng)建一個新的AutowiredAnnotationBeanPostProcessor。<br>
* 還支持JSR-330的@Inject注解。
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
- AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
findAutowiringMetadata:掃描找出被
@Autowired和@Vaule注解標(biāo)記的成員,并使用InjectionMetadata進(jìn)行封裝,最后將Spring容器需要用默認(rèn)策略注入的metadata保存到checkedElements中.
下面我們來了解一下什么是InjectionMetadata.
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
2.3 InjectionMetadata
InjectionMetadata是Spring的一個內(nèi)部框架使用的類,用于管理注入元數(shù)據(jù)。不適用于直接在應(yīng)用程序中使用。
- InjectionMetadata的核心成員變量
targetClass-被解析的目標(biāo)Class.
injectedElements-裝載被@Value和@Autowired注解標(biāo)記的成員集合.
checkedElements-和injectedElements一樣,僅保存Spring默認(rèn)處理的屬性或者方法.
public class InjectionMetadata {
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
/**
* 目標(biāo)class
*/
private final Class<?> targetClass;
/**
* <p>當(dāng)postProcessor處理bean時,會解析bean class的所有屬性.</p>
* <p>在解析時會判斷屬性上是否標(biāo)記:@Value、@Autowired</p>
* <p>如果有,那么對該屬性值進(jìn)行解析,將解析結(jié)果放入injectedElements中</p>
* <p>可以說這是被注入元素的集合</p>
*/
private final Collection<InjectedElement> injectedElements;
/**
* 和injectedElements一樣,僅保存Spring默認(rèn)處理的屬性或者方法
*/
@Nullable
private volatile Set<InjectedElement> checkedElements;
- InjectedElement
InjectedElement-用于裝載被解析的Member,其中
Member是Java中Field和Method的上層接口.
isField-布爾值,用于標(biāo)記當(dāng)前Member是否為Field類型.
/**
* A single injected element.<br>
* 單個注入元素。
*/
public abstract static class InjectedElement {
/**
* 被注解標(biāo)記的成員,Field還是Method.<br>
* Member類是Field和Method的上層抽象.<br>
*/
protected final Member member;
/**
* 是否為Field
*/
protected final boolean isField;
/**
* 屬性描述,JavaBean中的接口
*/
@Nullable
protected final PropertyDescriptor pd;
@Nullable
protected volatile Boolean skip;
}
- AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
OK,繼續(xù)回到解析依賴注入的成員變量邏輯中.看看這個方法的代碼邏輯
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 獲取類名---------例如:UserService<->userService
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 首先以最小的鎖定快速檢查并發(fā)映射。從容器中查找是否有給定類的autowired相關(guān)注解元信息.
// 此處又見雙重檢測鎖機制
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 檢查當(dāng)前注解元數(shù)據(jù)是否需要重新獲取,內(nèi)部進(jìn)行判空邏輯
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
// 如果需要重新解析,先清空metadata
metadata.clear(pvs);
}
// 重新解析被@Autowired、@Value標(biāo)記的成員
metadata = buildAutowiringMetadata(clazz);
// 重新將注解元數(shù)據(jù)放入緩存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
- 首先獲取當(dāng)前class的類名,規(guī)則為小寫開頭的駝峰.
- 從被解析過的注解元數(shù)據(jù)緩存中獲取當(dāng)前類的
metedata(這里又又又用了雙重檢查鎖機制保證線程安全和盡可能的使鎖覆蓋的代碼塊更小,因為多線程環(huán)境下,可能會同時解析同一個類).- 如果可以找到元數(shù)據(jù),則直接return.
- 如果需要重新解析元數(shù)據(jù),那么使用雙重檢查鎖保證線程安全,同時清空緩存中的
metedata,進(jìn)入buildAutowiringMetadata中解析類得到metadata.- 將解析后的
metadata回種到緩存中.
- AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
/**
* 解析當(dāng)前Class被@Autowired標(biāo)記的成員
* @param clazz
* @return
*/
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
// 遞歸遍歷當(dāng)前類及其所有基類,解析全部注解元信息
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 收集被@Autowired、@Value標(biāo)記的Field.
// 利用反射機制獲取給定類中所有的聲明字段,獲取字段上的注解信息
// doWithLocalFields->獲取當(dāng)前類的所有Field,每個field執(zhí)行l(wèi)ambda內(nèi)的邏輯.
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 此處邏輯較為復(fù)雜,通過debug發(fā)現(xiàn)如果為被標(biāo)注的屬性,會返回required:true.
// 大致的意思是這個field是否被特定的注解標(biāo)記?這里留一個疑問
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
// 如果是static屬性的成員,Spring不提供支持
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判斷required的狀態(tài)
boolean required = determineRequiredStatus(ann);
// 將當(dāng)前成員添加進(jìn)currElements
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 上面是尋找被@Autowired和@Value標(biāo)記的field,這里是尋找method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// 如果方法不包含參數(shù),打印警告信息
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
// 找到方法內(nèi)的屬性
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
// 遞歸父類
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
這里的方法較長,其實核心為尋找出當(dāng)前類被
@Autowired和@Value標(biāo)記的成員-Member.而JDK中的Member又可以分為Field和Method,所以你會看到ReflectionUtils.doWithLocalFields和ReflectionUtils.doWithLocalMethods,它們負(fù)責(zé)判斷出當(dāng)前的成員是否被標(biāo)記,如果被標(biāo)記,那么加入element集合中.其中邏輯在findAutowiredAnnotation中,這里不做展開。值得一提的是,Spring在5.2的版本中,對此處做了一些重構(gòu).
掃描完后,會將目標(biāo)類與收集到的被注解標(biāo)記的成員通過構(gòu)造函數(shù)進(jìn)行裝配,返回InjectionMetadata.
3. 檢測是否需要提交暴露早期引用的Bean-addSingletonFactory
Spring是默認(rèn)支持循環(huán)依賴的,但是循環(huán)依賴僅僅支持單例Bean的屬性注入.
// 向容器中緩存單例模式的Bean對象,以防止循環(huán)引用
// 判斷是否要暴露早期引用的bean
// 1. 是否為單例.
// 2. 是否允許循環(huán)引用
// 3. 是否在創(chuàng)建中的bean
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 匿名內(nèi)部類,防止循環(huán)引用,盡早只有對象的引用
// 注意,此時的addSingletonFactory僅僅是注冊了一個lambda代碼塊.
// getEarlyBeanReference實現(xiàn)的是ObjectFactory的getObject方法.
// 真正調(diào)用getObject的地方在doGetBean中的getSingleton中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
這里Spring判斷了三個條件來決定是否提前暴露早期引用的Bean.
- 是否為單例
- 是否允許循環(huán)引用
- 是否在創(chuàng)建中的bean.
如果條件成立,那么此時會往三級緩存中注冊一個lambda代碼塊,該代碼塊其實是實現(xiàn)
ObjectFactory中的getObject方法,getEarlyBeanReference方法會判斷是否需要對Bean進(jìn)行增強,然后返回早期的bean引用。注意,注冊代碼塊,而不是調(diào)用。也就是說這里只是注冊一個回調(diào)的方法,真正回調(diào)的地方其實在前面已經(jīng)講過的doGetBean中的getSingleton中.熟悉函數(shù)式編程的朋友應(yīng)該可以理解.
- DefaultSingletonBeanRegistry#addSingletonFactory
注意一個細(xì)節(jié),三級緩存中,同一個Bean只會存在唯一一份引用.
也就是說,如果這個引用在三級緩存中,一級、二級緩存就不會存在這份引用.
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 往三級緩存中添加
this.singletonFactories.put(beanName, singletonFactory);
// 從二級緩存中移除
this.earlySingletonObjects.remove(beanName);
// 記錄注冊單例的順序
this.registeredSingletons.add(beanName);
}
}
}
4. 填充Bean實例的屬性-populateBean
一個重量級方法,經(jīng)過populateBean處理過后的bean即為完備的bean了。
什么是完備的Bean?
例如HelloController聲明了@AutoWired需要注入HelloService依賴,那么執(zhí)行完populateBean就會將HelloService這個Bean注入到HelloController中,此時擁有了完整的依賴的HelloController便為一個完備的Bean.
這里留個坑位,以后再補充populateBean的邏輯.
5. 生命周期函數(shù)回調(diào)-initializeBean
這里也是一個重量級方法,關(guān)于Spring的生命周期回調(diào)函數(shù)這里簡單介紹一下:
- 激活部分的Aware接口:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware.
- 激活BeanPostProcessor的postProcessBeforeInitialization方法.
- 激活I(lǐng)nitializingBean的afterPropertiesSet方法、
@Bean時指定的initMethod.- 激活BeanPostProcessor的postProcessAfterInitialization方法
下面貼出源碼作為佐證.
5.1 initializeBean入口-doCreateBean
try {
// 填充bean實例屬性
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean,過程:
// 1. 判斷是否實現(xiàn)了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware.
// 如果有,將相關(guān)屬性進(jìn)行傳遞.
// 2. 調(diào)用BeanPostProcessor的前置操作:例如->@PostConstruct
// 3. 調(diào)用bean初始化的前置操作,即生命周期回調(diào)函數(shù).
// 實現(xiàn)InitializingBean#afterPropertiesSet、具有依賴注入的自定義方法
// 4. 調(diào)用BeanPostProcessor的后置操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
5.2 AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 激活BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 激活BeanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 激活I(lǐng)nitializingBean的afterPropertiesSet方法、initMethod
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 激活BeanPostProcessor的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
關(guān)于BeanPostProcessor,在我前面的文章中已經(jīng)介紹過了.
這里我們來關(guān)注幾個平時可能會用到的Lifecycle Callback:
- @PostConstruct.
- InitializingBean#afterPropertiesSet.
- initMethod.
執(zhí)行順序為:1->2->3
Spring官方推薦使用@PostConstruct注解的方式來觸發(fā)生命周期回調(diào).
下面推薦兩個鏈接,希望深入的朋友可以點擊前往:
Spring官網(wǎng)關(guān)于生命周期回調(diào)的說明.
執(zhí)行解析@PostConstruct.
6. 檢測循環(huán)依賴,防止Bean出現(xiàn)不一樣的引用.
// 如果容器允許循環(huán)依賴,則進(jìn)行相應(yīng)處理
if (earlySingletonExposure) {
// 獲取指定名稱的已注冊單例Bean對象.
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 如果經(jīng)過initializeBean后獲取到的Bean還是同一個(沒有被增強)
if (exposedObject == bean) {
// 確保byName獲取到的Bean和正在實例化的Bean是同一個
exposedObject = earlySingletonReference;
}
// 如果上面的判斷沒通過,則表明引用的bean和注入的bean不一致
// 此時有兩個判斷條件:
// 1. 在循環(huán)引用的情況下是否要求注入原始bean實例,即使注入的bean最終被增強(AOP處理)也是如此.
// 意思就是說,只認(rèn)原始類型,如果在initializeBean中對bean進(jìn)行了替換,Spring會認(rèn)為是異常.
// 2. 當(dāng)前是否觸發(fā)了循環(huán)依賴: dependentBeanMap記錄著每個依賴于此Bean的Bean實例集合
// 當(dāng)發(fā)生循環(huán)依賴的時候不允許新創(chuàng)建實例對象
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
// 獲取依賴于當(dāng)前bean的bean實例
for (String dependentBean : dependentBeans) {
// 移除掉只是用來進(jìn)行類型檢查的單例bean
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 因為bean創(chuàng)建后其依賴的bean一定是已經(jīng)創(chuàng)建的
// actualDependentBeans不為空則表示當(dāng)前bean創(chuàng)建后其依賴的bean卻沒有完全創(chuàng)建完
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
這里Spring主要是考慮Bean在鉤子方法中被用戶自定義的BeanPostProcessor或者某個生命周期回調(diào)中進(jìn)行替換了,如此一來,之前如果有別的Bean依賴了當(dāng)前創(chuàng)建的Bean,那么就會觸發(fā)
BeanCurrentlyInCreationException,因為引用的Bean對象不一致了.
7. 注冊銷毀邏輯-registerDisposableBeanIfNecessary
主要是注冊實現(xiàn)了
DisposableBean或者@Bean時指定了destroyMethod的方法,在Bean銷毀時進(jìn)行回調(diào).
doCreateBean流程圖
