媽媽說,文章標題取得越長,文章閱讀量越高。hhhhhhtml
在AbstractBeanFactory#doGetBean
方法中會經過以下方法來建立單例Bean:java
if (mbd.isSingleton()) {
// 建立單例Bean
sharedInstance = getSingleton(beanName, () -> {
try {
// 建立Bean
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
複製代碼
讓咱們來看一下getSingleton
方法:git
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//判斷單例Bean是否已經存在,若是存在,則直接返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 建立單例以前調用該方法,將此Bean標記爲正在建立中,用來檢測循環依賴
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 經過方法傳入的ObjectFactory<?> singletonFactory來建立Bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 建立單例以後調用該方法,將單例標記爲不在建立中
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 加入到單例池容器中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
複製代碼
經過源碼咱們能夠知道,在getSingleton
方法中是經過調用傳入的ObjectFactory<?> singletonFactory
對象的getObject();
方法來建立單例Bean的,而該方法實際上是AbstractAutowireCapableBeanFactory#createBean
方法。github
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 爲指定的bean定義解析bean類,將bean類名稱解析爲Class引用(若是須要,並將解析後的Class存儲在bean定義中以備未來使用),也就是經過類加載去加載這個Class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 校驗和準備 Bean 中的方法覆蓋
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 執行BeanPostProcessors , 給 BeanPostProcessors 一個機會直接返回代理對象來代替Bean實例
// 在Bean尚未開始實例化以前執行 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法,這個方法可能會直接返回Bean
// 若是這裏直接返回了Bean,那麼這裏返回的Bean多是被通過處理的Bean(多是代理對象)
// 在這裏須要注意Spring方法中的兩個單詞: Instantiation 和 Initialization , 實例化和初始化, 先實例化,而後初始化
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// 若是bean不爲null,則直接返回,不在作後續處理
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 建立Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
複製代碼
總的來看createBean
方法,大概經歷了以下幾個步驟:spring
調用resolveBeanClass(mbd, beanName);
方法,爲指定的bean定義解析bean類api
調用mbdToUse.prepareMethodOverrides();
方法,校驗和準備 Bean中的方法覆蓋app
調用resolveBeforeInstantiation(beanName, mbdToUse);
方法,給BeanPostProcessors
一個機會直接返回代理對象來代替Bean實例框架
調用doCreateBean(beanName, mbdToUse, args);
方法,真正執行Bean的建立ide
在createBean
方法中最重要的方法之一就是resolveBeforeInstantiation(beanName, mbdToUse);
。post
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
複製代碼
在resolveBeforeInstantiation
方法內部執行了兩個BeanPostProcessor
的相關方法,分別是: applyBeanPostProcessorsBeforeInstantiation
和applyBeanPostProcessorsAfterInitialization
。
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
複製代碼
該方法在Bean實例化以前調用,給BeanPostProcessor
一個機會去建立代理對象來代理Bean。
也就是說,通過調用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
方法以後,生成的Bean可能已經不是咱們的原生Bean,而是一個代理對象。
在執行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
方法後,若是返回的Bean對象不爲null,則直接執行applyBeanPostProcessorsAfterInitialization
方法,執行完後Bean建立過程結束。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
複製代碼
在執行完resolveBeforeInstantiation
方法以後,若是返回的對象仍是爲null,則調用doCreateBean(beanName, mbdToUse, args);
方法來建立Bean。
看了這麼多Spring的源碼,Spring的編碼風格就是這樣,真正幹活的方法每每都是do
開頭的方法,例如doXxxx
方法。
關於doCreateBean
方法的具體源碼,咱們下期在解析。如今咱們在來說一下InstantiationAwareBeanPostProcessor
。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
複製代碼
InstantiationAwareBeanPostProcessor
繼承了BeanPostProcessor
接口。
Subinterface of BeanPostProcessor that adds a before-instantiation callback, and a callback after instantiation but before explicit properties are set or autowiring occurs.
Typically used to suppress default instantiation for specific target beans, for example to create proxies with special TargetSources (pooling targets, lazily initializing targets, etc), or to implement additional injection strategies such as field injection.
NOTE: This interface is a special purpose interface, mainly for internal use within the framework. It is recommended to implement the plain BeanPostProcessor interface as far as possible, or to derive from InstantiationAwareBeanPostProcessorAdapter in order to be shielded from extensions to this interface.
BeanPostProcessor的子接口,它添加實例化以前的回調,以及在實例化以後但在設置顯式屬性或發生自動裝配以前的回調。
一般用於抑制特定目標Bean的默認實例化,例如建立具備特殊TargetSource的代理(池目標,延遲初始化目標等),或實現其餘注入策略,例如字段注入。
注意:此接口是專用接口,主要供框架內部使用。 建議儘量實現普通的BeanPostProcessor接口,或從InstantiationAwareBeanPostProcessorAdapter派生,以避免對該接口進行擴展。
此次咱們先重點關注一下InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
方法。這個方法有什麼用呢?一塊兒來看一下doc文檔的描述:
Apply this BeanPostProcessor before the target bean gets instantiated
If a non-null object is returned by this method, the bean creation process will be short-circuited. The only further processing applied is the
BeanPostProcessor.postProcessAfterInitialization(java.lang.Object, java.lang.String)
callback from the configuredBeanPostProcessors
.This callback will be applied to bean definitions with their bean class, as well as to factory-method definitions in which case the returned bean type will be passed in here.
Post-processors may implement the extended
SmartInstantiationAwareBeanPostProcessor
interface in order to predict the type of the bean object that they are going to return here.The default implementation returns
null
.在實例化目標bean以前應用此BeanPostProcessor。 返回的bean對象能夠是代替目標bean使用的代理,從而有效地抑制了目標bean的默認實例化。 若是此方法返回一個非null對象,則Bean建立過程將被短路。 惟一應用的進一步處理是來自已配置BeanPostProcessors的BeanPostProcessor.postProcessAfterInitialization(java.lang.Object,java.lang.String)回調。
此回調將應用於具備其bean類的bean定義以及工廠方法定義,在這種狀況下,返回的bean類型將在此處傳遞。
後處理器能夠實現擴展的SmartInstantiationAwareBeanPostProcessor接口,以便預測它們將在此處返回的Bean對象的類型。
默認實現返回null。
有這樣一個Bean,代碼以下:
@Service
public class UserService {
public UserService() {
System.out.println("create UserService...");
}
@PostConstruct
public void init() {
System.out.println("do init...");
}
@PreDestroy
public void destroy() {
System.out.println("do destroy...");
}
}
複製代碼
正常狀況下,該在Bean在生命週期內,應該會輸出:
create UserService...
do init...
do destroy...
複製代碼
如今,讓咱們添加一個自定義的InstantiationAwareBeanPostProcessor
,來干預UserService
的生命週期。
@Component
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (UserService.class.equals(beanClass)) {
return new UserService();
}
return null;
}
}
複製代碼
MyInstantiationAwareBeanPostProcessor
繼承了InstantiationAwareBeanPostProcessorAdapter
,同時Override了postProcessBeforeInstantiation
方法。
此時,該在Bean在生命週期內輸出:
create UserService...
複製代碼
爲何呢?不知道聰明的讀者讀完這篇文章能不能本身分析出緣由。
未完待續......
源碼註釋GITHUB地址:github.com/shenjianeng…
歡迎關注公衆號: