目錄
-
-
- getSingleton() 擷取單例對象
-
- 3個map(三級緩存)
- 其它集合類型的成員字段
- getSingleton() 從三級緩存擷取單例bean執行個體
- getSingleton() 從工廠執行個體擷取單例bean執行個體
- getBean() 擷取bean執行個體的過程
-
- getBean()
- doGetBean()
- getBean() 整體流程圖
- DependsOn依賴
- bean的懶加載
- createBean() 建立bean執行個體的過程
-
- createBean()
- createBean() 流程圖
- doCreateBean()
- populateBean() 填充屬性,注入所需依賴
- initializeBean() 初始化
- doCreateBean() 整體流程圖
- 循環依賴
-
- 循環依賴的概念
- 循環依賴問題觸發的時機
- spring解決循環依賴的原理圖
- spring解決循環依賴的原理
- spring可以解決哪些種類的循環依賴問題
- 三級緩存各自的存入時機
- 可以不要第二級緩存嗎
- 可以不要第三級緩存嗎 | 隻使用兩級緩存行嗎
- bean的生命周期
-
- bean的生命周期
- bean生命周期中的常見單詞
- bean的初始化、銷毀方法
- @PostConstruct、@PreDestroy
- bean的後置處理器BeanPostProcessor
- InstantiationAwareBeanPostProcessor
- BeanFactoryPostProcessor
-
使用的spring源碼版本 5.3.x
getSingleton() 擷取單例對象
提供單例操作的類主要是 DefaultSingletonBeanRegistry ,此處介紹這個類的
- 幾個集合類型的成員變量:三級緩存
- 2個重載的 getSingleton() 方法:用于擷取單例bean的執行個體
- getSingleton(String beanName, boolean allowEarlyReferenc) 從三級緩存擷取單例bean的執行個體
- getSingleton(String beanName, ObjectFactory<?> singletonFactory) 從工廠執行個體擷取單例bean的執行個體
3個map(三級緩存)
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
spring使用三級緩存解決循環依賴問題
- singletonObjects:一級緩存,用于儲存已經建立好的單例bean
- earlySingletonObjects:二級緩存,用于儲存已經建立執行個體但尚未進行屬性注入(初始化)的單例bean
- singletonFactories:三級緩存,用于儲存bean的工廠執行個體,二級緩存中存儲的就是從工廠執行個體中擷取到的對象。
其它集合類型的成員字段
/** Set of registered singletons, containing the bean names in registration order. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** Names of beans that are currently in creation. */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Names of beans currently excluded from in creation checks. */
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/** Map between dependent bean names: bean name to Set of dependent bean names. */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
getSingleton() 從三級緩存擷取單例bean執行個體
此實質是到三級緩存中嘗試擷取bean
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先在一級緩存中查找
Object singletonObject = this.singletonObjects.get(beanName);
//如果找不到且目前bean是正在建立的單例bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//則到二級緩存中查找
singletonObject = this.earlySingletonObjects.get(beanName);
/**如果二級緩存中也沒有,且 allowEarlyReference為true,則嘗試到三級緩存中擷取對應的工廠執行個體,通過工廠建立bean執行個體,放到二級緩存中并傳回該執行個體(尚未填充屬性)*/
if (singletonObject == null && allowEarlyReference) {
/**在此期間,可能其它線程已經建立好了執行個體放到一二級緩存中,是以需要再次校驗一級緩存、二級緩存中是否有對應執行個體,為防止多線程同時操作,加上同步鎖*/
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
//如果一級緩存中仍然沒有
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
//二級緩存中也沒有
if (singletonObject == null) {
//則從三級緩存中擷取對應的工廠執行個體
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//使用工廠建立bean的執行個體(尚未注入屬性|初始化)
singletonObject = singletonFactory.getObject();
//并将建立好的bean執行個體放到二級緩存中
this.earlySingletonObjects.put(beanName, singletonObject);
//因為是擷取的是單例bean,三級緩存中對應的工廠執行個體隻會使用一次,是以使用完就可以移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
//傳回擷取的單例對象
return singletonObject;
}
getSingleton() 從工廠執行個體擷取單例bean執行個體
getSingleton(String beanName, ObjectFactory<?> singletonFactory)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
/** 從工廠執行個體擷取單例bean的執行個體,操作之前需要加同步鎖,并校驗緩存中有沒有需要的單例 */
synchronized (this.singletonObjects) {
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 + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
/** 從工廠執行個體擷取單例bean的執行個體。
形參singletonFactory是ObjectFactory的執行個體,ObjectFactory是函數式接口,需要實作getObject()方法。
ObjectFactory用于從工廠擷取對象執行個體,不僅僅隻用于擷取單例,可能建立的要求是代理,還要注入所依賴的bean,是以實作往往是調用createBean()方法,而非直接調用上面簡單的getSingleton()。
在createBean()方法中,bean經過執行個體化、填充屬性、初始化等流程,已經是完全體的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);
}
/** 如果是新建立的單例,則調用addSingleton()方法把,把執行個體放到一級緩存中,并從二三級緩存移除相關執行個體 */
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
這個方法主要做了2件事
- 調用工廠執行個體的getObject()方法擷取bean執行個體
- 如果是新建立的單例,還會把執行個體一級緩存中、從二三級緩存移除對應的執行個體
getBean() 擷取bean執行個體的過程
抽象類 AbstractBeanFactory 包含了許多操作bean的方法,比如
- 抽象方法 getBeanDefinition()、createBean()
- 提供了實作的方法 getBean()、 doGetBean()
getBean()
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {
return doGetBean(name, requiredType, args, false);
}
getBean()實質是調用 doGetBean()
doGetBean()
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//轉換别名。如果傳入的是别名,會先轉換為對應的beanName
String beanName = transformedBeanName(name);
Object beanInstance;
//先嘗試從三級緩存中擷取執行個體
//實際是調用 getSingleton(beanName, true)
Object sharedInstance = getSingleton(beanName);
//如果從緩存中擷取到執行個體。方法參數args隻用在建立新執行個體時,==null說明是要從緩存中擷取
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//則對執行個體進行修飾處理
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果未擷取到執行個體,說明需要建立執行個體
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
/** 如果目前BeanFactory執行個體中沒有對應的bean definition,且父BeanFactory執行個體存在,則通過父BeanFactory執行個體擷取bean執行個體。
注意:目前類是AbstractBeanFactory,目前對象是BeanFactory的執行個體 */
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
/** 執行到此,說明目前BeanFactory執行個體中存在對應的bean definition,那就使用目前BeanFactory執行個體建立bean執行個體 */
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
//合并bean definition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
/** 處理DependsOn依賴,如果DependsOn依賴尚未執行個體化,則先執行個體化 */
// Guarantee initialization of beans that the current bean depends on.
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 + "'");
}
registerDependentBean(dep, beanName);
try {
//調用getBean(),保證DependsOn依賴在目前bean執行個體化化之前都已執行個體化
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
/** 開始建立bean執行個體。
單例、原型建立執行個體的方式有所差別,需要先判斷bean的類型,但核心都是調用createBean()方法建立執行個體。
此處單例使用的getSingleton()是重載方法,不是操作三級緩存的那個getSingleton() */
// Create bean instance.
if (mbd.isSingleton()) {
/** 這個是重載的getSingleton(),從工廠執行個體擷取單例,用lambda表達式實作ObjectFactory接口。
getSingleton()先調用reateBean()建立bean執行個體,完全建立好的單例放在二級緩存中,getSingleton()再把二級緩存中的這個單例移到一級緩存中 */
sharedInstance = getSingleton(beanName, () -> {
try {
//調用createBean()建立執行個體
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.
//createBean()過程中出問題時需要銷毀執行個體,原型每次都是建立,即使出問題也不影響下次getBean(),是以不用銷毀,gc會自動回收
destroySingleton(beanName);
throw ex;
}
});
//對執行個體進行修飾處理
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
//調用createBean()建立執行個體
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
//對執行個體進行修飾處理
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
//對執行個體進行修飾處理
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
getBean() 整體流程圖
DependsOn依賴
在執行個體化bean之前,會先執行個體化該bean所有的 DependsOn依賴。
如果bean沒有直接使用 | 依賴某些bean,但需要在執行個體化之前保證這些bean已經執行個體化,可以用@DependsOn 或 depends-on 屬性将這些bean辨別為DependsOn依賴。
@Component
@DependsOn("c") //value指定依賴的bean,String[]形式
class A {
@Autowired
private B b;
//...
}
bean的懶加載
bean預設都是懶加載的,使用該bean時才進行加載,是以預設流程依次是
- getBean():BeanFactory的方法,實質是調用doGetBean()
- doGetBean():依次從單例池(一級緩存)、父容器(父BeanFactory的執行個體)嘗試擷取bean的執行個體,如果未擷取到,則調用createBean()建立bean的執行個體
- createBean():實質是調用doCreateBean()
- doCreateBean():建立bean的執行個體
不是直接 createBean() 建立bean的執行個體,而是調用getBean(),用到了該bean的執行個體時才通過createBean()建立執行個體。
可以使用 lazy-init 屬性或 @Lazy 注解設定是否使用懶加載
<!--lazy-init預設true-->
<bean name="" class="" lazy-init="false" />
@Component
@Lazy(false) //value屬性指定是否使用懶加載,預設true
class A {
}
createBean() 建立bean執行個體的過程
AbstractAutowireCapableBeanFactory 繼承了 AbstractBeanFactory ,提供多個方法的實作,其中包括 createBean() 方法的實作,主要是調用 doCreateBean() 方法。
這2個類都是抽象類,以下3個方法均是 AbstractAutowireCapableBeanFactory 類中的。
createBean()
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
//解析BeanClass
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.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
//準備方法覆寫(校驗BeanDefinition中定義的override方法是否合法)
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
//給BeanPostProcessor一個傳回代理的機會。spring aop即使用此原理實作
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
//調用doCreateBean()建立bean執行個體
try {
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);
}
}
/**
* 執行所有InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法,
* 如果某個InstantiationAwareBeanPostProcessor接口傳回了代理,則不再執行後續的postProcessBeforeInstantiation()方法,直接執行所有BeanPostProcessor接口的postProcessAfterInitialization()方法。
*
* InstantiationAwareBeanPostProcessor是BeanPostProcessor的一個特殊子接口,用于spring架構内部實作spring aop,
* 更多資訊可以檢視後面的BeanPostProcessor介紹
*/
@Nullable
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) {
//執行所有InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
//如果某個InstantiationAwareBeanPostProcessor接口傳回了不為null的對象(代理)
if (bean != null) {
//執行所有BeanPostProcessor接口的postProcessAfterInitialization()方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
@Override
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;
}
createBean() 流程圖
doCreateBean()
/**
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//執行個體化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//合并對bean definition的修改
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
/** 如果允許提前暴露(正在建立的單例 && 允許解決循環依賴),則預加載對應的BeanFactory執行個體到三級緩存中,以便後續解決循環依賴時使用。
allowCircularReferences是目前類的一個boolean型的成員字段,是否允許自動解決循環依賴,預設true,可以手動設定 */
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");
}
//把對應的BeanFactory執行個體添加到三級緩存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充屬性,注入所需依賴
populateBean(beanName, mbd, instanceWrapper);
//初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//檢查循環依賴
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
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.");
}
}
}
}
/** 注冊bean的銷毀方法。
包括DisposableBean接口的destroy()方法、destroy-method屬性設定的方法 */
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
populateBean() 填充屬性,注入所需依賴
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
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.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//根據注入模式選擇autowireByName()、autowireByType()進行注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
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 = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//getBean()擷取依賴,調用pvs.add()進行注入
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("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");
}
}
}
}
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
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 != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
/** 擷取依賴的執行個體,調用pvs.add()進行注入。
目前抽象類implements了AutowireCapableBeanFactory接口,但并未實作擷取執行個體的resolveDependency()方法,當然,此方法的實作中也用到了getBean() */
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("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);
}
}
}
此方法主要是根據注入模式,調用autowireByName()或autowireByType()進行注入,這2個方法注入時也會先通過getBean()方法擷取依賴執行個體。
initializeBean() 初始化
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
//invokeAwareMethods() 處理實作的Aware接口,執行Aware方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
//applyBeanPostProcessorsBeforeInitialization() 調用所有BeanPostProcessor接口的postProcessBeforeInitialization()方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//invokeInitMethods() 調用初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//applyBeanPostProcessorsAfterInitialization() 調用所有BeanPostProcessor接口的postProcessAfterInitialization()方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
/**
* 3個Aware接口,依次為:
* BeanNameAware setBeanName() 設定beanName
* BeanClassLoaderAware setBeanClassLoader() 設定bean的類加載器
* BeanFactoryAware setBeanFactory() 設定要使用的工廠執行個體
*/
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
/**
* 2個初始化方法,依次為:
* InitializingBean接口的afterPropertiesSet()方法
* init-method指定的自定義初始化方法
*/
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//執行InitializingBean接口的afterPropertiesSet()方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//執行init-method指定的自定義初始化方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
doCreateBean() 整體流程圖
核心流程有3步
- 建立執行個體
- 填充屬性、注入依賴
- 初始化
執行個體化可以看做在堆上建立對象、配置設定記憶體空間,成員字段的值還是預設初始值;填充屬性是給成員字段設定值。
getBean() 擷取bean執行個體過程中,會用到 createBean() 建立執行個體;
createBean() 建立執行個體,populateBean()填充屬性、注入依賴時,也會調用getBean()擷取所需依賴。
DI:其實就是在createBean建立bean執行個體,填充屬性、注入依賴時,使用getBean擷取所需依賴,注入到bean執行個體中。
循環依賴
循環依賴的概念
circular reference,循環引用 | 依賴
bean之間彼此依賴,依賴關系環形閉環
@Component
class A {
@Autowired
private B b;
}
@Component
class B {
@Autowired
private A a;
}
//bean依賴自身也屬于循環依賴
@Component
class A {
@Autowired
private A a;
}
循環依賴問題觸發的時機
bean執行個體化之後,populateBean()填充屬性時。
spring解決循環依賴的原理圖
A、B構成循環依賴,getBean(beanA)擷取beanA執行個體的過程如下(圖中隻列關鍵步驟)
完成後beanA、beanB的執行個體均已在一級緩存中,後續可以從一級緩存中直接擷取。
spring解決循環依賴的原理
核心思想:提前曝光已執行個體化、但尚未完成屬性填充(建立)的執行個體,填充屬性期間可被其它執行個體引用(作為依賴注入)。
執行個體化bean後,會把目前bean對應的工廠執行個體預先加載到三級緩存中;注入依賴、建立所需依賴的執行個體時,可以從三級緩存擷取到目前bean對應的工廠執行個體,通過工廠執行個體可以擷取到之前建立的目前bean的執行個體(已執行個體化但尚未填充屬性),進而完成依賴本身的屬性注入、初始化。
spring可以解決哪些種類的循環依賴問題
- 單例模式會緩存建立的bean執行個體,原型模式每次都是建立新的執行個體,不會緩存建立的bean執行個體。三級緩存是在getSingleton()擷取單例中使用的,隻能解決單例的循環依賴問題。
- 均采用setter方法注入,或者一方使用構造方法注入、另一方使用setter方法注入的循環依賴都可以被spring解決。(不能解決全采用構造方法注入的循環依賴)
三級緩存各自的存入時機
- 放入三級緩存的時機:bean執行個體化之後、填充屬性之前,會把對應的BeanFactory執行個體放到三級緩存中
- 放入二級緩存的時機:從三級緩存中擷取執行個體時,如果一二級緩存沒有對應的bean執行個體,但三級緩存有對應的工廠執行個體,則通過工廠執行個體的getObject()方法擷取bean執行個體,放到二級緩存中,并移除三級緩存中對應的工廠執行個體
- 放入一級緩存的時機:執行個體建立完成(完全體)後會被放到一級緩存中,并會移除二三級緩存中對應的執行個體
當spring容器被銷毀時,會銷毀一級緩存中的單例執行個體。
可以不要第二級緩存嗎
二級緩存 earlySingletonObjects,early有2個含義
- adj. 早期的:早期的單例,已執行個體化但尚未填充屬性、初始化,還不是完全體的單例,不能正常使用,但可以被引用。
- adv. 提前:本來要成為完全體的單例才暴露出來,二級緩存把已執行個體化的bean提前暴露出來,讓其它bean可以引用。
解決循環依賴主要靠第二級緩存提前暴露早期執行個體,讓其它執行個體可以引用,第二級緩存才是關鍵,不能沒有。
可以不要第三級緩存嗎 | 隻使用兩級緩存行嗎
隻使用一二級緩存時
getBean(beanA) -> 執行個體化beanA ,放到二級緩存中 ->
填充beanA的屬性,getBean(beanB) -> 執行個體化beanB,放到二級緩存中 ->
填充beanB的屬性,getBean(beanA) -> 在二級緩存中擷取到beanA,完成注入 -> beanB建立完成,放到一級緩存中 ->
beanA建立完成,放到一級緩存中
顯然,隻用一二級緩存也可以解決循環依賴問題。
看上面的spring解決循環依賴的原理圖,本來在beanA執行個體化後就可以擷取到引用,把beanA放到二級緩存中;硬是拖了半個流程,在beanB執行個體化後注入依賴,getBean(beanA)時,才從三級緩存中擷取beanA的工廠執行個體,通過工廠擷取beanA執行個體,把beanA執行個體放到二級緩存中。
為什麼要拖那麼久,等beanB填充屬性、注入beanA時才擷取beanA的執行個體放到二級緩存中?因為之前不确定需要的是beanA本身,還是beanA的代理,在beanB實際使用beanA(填充屬性)時才能确定
@Component
class A {
@Autowired
private B b;
}
使用aop對部分bean中的beanB進行增強,自然要等到建立bean、填充屬性要注入beanB時,才能校驗目前bean是不是目前要注入的依賴(beanB)的目标類(切入點),是就注入beanB的代理,否則注入beanB本身。
工廠執行個體擷取bean執行個體的getObject()方法其實就是:判斷目前bean需要的是依賴本身的執行個體,還是依賴的代理(依賴的代理也屬于依賴的執行個體),需要依賴本身就直接傳回已建立好的依賴執行個體,需要代理就在已建立的依賴執行個體的基礎上進行包裝,傳回代理。
總結
第三級緩存的作用是延緩早期執行個體的暴露時機,把早期執行個體的暴露時機從執行個體化後,推遲到依賴本身的填充屬性、依賴注入時,以便應用spring aop、确定依賴本身是否要注入代理。
如果依賴注入時都沒有使用代理(aop),隻使用一二級緩存也可以解決循環依賴問題。
bean的生命周期
bean的生命周期
一般認為bean的生命周期即執行個體的生命周期,主要邏輯在doCreateBean()方法中,createBean()中解析BeanClass、準備方法覆寫之類的操作不算在bean的生命周期中。
- 執行個體化
- 填充屬性,注入依賴
- 如果bean實作了BeanNameAware接口,則調用setBeanName()方法設定beanName
- 如果bean實作了BeanClassLoaderAware接口,則調用setBeanClassLoader()方法設定bean的類加載器
- 如果bean實作了BeanFactoryAware接口,則調用setBeanFactory()方法 設定要使用的BeanFactory執行個體
- 如果bean實作了ApplicationContextAware接口,則調用setApplicationContext()方法設定應用上下文
- 如果bean實作了BeanPostProcessor接口,則調用applyBeanPostProcessorsBeforeInitialization() 做初始化的前處理
- 如果bean實作了InitializingBean接口,則調用afterPropertiesSet()方法進行初始化
- 如果使用了init-method指定的自定義初始化方法,則調用init-method指定的自定義初始化方法
- 如果bean實作了BeanPostProcessor接口,則調用postProcessAfterInitialization() 做初始化的後處理
至此,執行個體建立完成,單例模式放到一級緩存中,由spring容器管理,原型模式交給調用者
- 單例bean的生命周期和spring容器的生命周期保持一緻,在spring容器初始化時就建立執行個體,放到spring容器中,由spring容器負責管理,spring容器運作期間一直存活,在spring容器解除安裝時銷毀執行個體。
- 原型模式的bean在需要時才建立執行個體,每次都是建立新的執行個體,由spring容器建立執行個體,建立後交給使用方(getBean()的調用者),在沒有任何對象引用時成為垃圾等待gc回收。
- 如果bean實作了DisposableBean接口,銷毀時會調用destroy()方法
- 如果使用了destroy-method屬性指定銷毀方法,還會調用destroy-method指定的方法
bean生命周期中的常見單詞
- post:在…之後
- process:處理、加工
- processor:處理器、處理程式、加工者
- BeanPostProcessor:bean後置處理器,對bean進行加工處理
- aware:意識到的、感覺到的、知道的
bean的初始化、銷毀方法
- 初始化方法:可以實作InitializingBean接口,在afterPropertiesSet()方法中寫實作,也可以用 init-method 屬性指定。
- 銷毀方法:常用于釋放 bean 所持有的資源,可以實作DisposableBean接口,在destroy()方法中寫實作,也可以用 destroy-method 屬性指定。
@PostConstruct、@PreDestroy
- @PostConstruct:在構造方法之後執行,常用于初始化操作
- @PreDestroy :在對象銷毀之前執行,常用于釋放對象持有的資源
@Component
public class Xxx {
@PostConstruct
public void postConstruct() {
//...
}
@PreDestroy
public void PreDestroy() {
//...
}
}
jdk自帶的類可分為2類
- 核心類庫:以java開頭,比如 io、date
- 擴充類庫:以javax開頭,比如 servlet、swing
這2個注解作用看起來和 init-method、 destroy-method 差不多,但都是 javax 中的注解,不是 spring 的注解,一般不算在 bean 的生命周期中。
bean的後置處理器BeanPostProcessor
bean的後置處理器BeanPostProcessor用于在初始化階段對bean進行加工。
經過建立執行個體、填充屬性2個階段,bean已經建立得差不多了,初始化階段用于對bean進行進一步的加工修飾,xml配置bean的方式(init-method)很少用了,開發主要通過實作BeanPostProcessor接口來對bean做加工處理。
BeanPostProcessor接口有2個預設方法
- postProcessBeforeInitialization():在bean的初始化方法之前執行
- postProcessAfterInitialization():在bean的初始化方法之後執行
形參都為執行個體本身、beanName,可根據beanName進行篩選;傳回值是加工後的執行個體;預設實作是不做處理、直接傳回執行個體。
bean可以實作多個BeanPostProcessor接口,實作多個BeanPostProcessor接口時往往還需要實作Ordered接口,通過Ordered接口指定多個BeanPostProcessor的執行順序。
@Component
public class Xxx implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//...
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//...
return bean;
}
@Override
public int getOrder() {
return 0;
}
}
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,沒有重寫BeanPostProcessor的2個預設方法,隻是增加了4個預設方法,其中需要postProcessBeforeInstantiation()方法
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
在createBean()中,會先給BeanPostProcessor一個傳回代理的機會:執行所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法
- 如果某個postProcessBeforeInstantiation()方法傳回不為null,則不再執行後續的postProcessBeforeInstantiation()方法,直接執行所有BeanPostProcessor接口的postProcessAfterInitialization()方法,将傳回的對象作為代理直接傳回,不再調用doCreateBean()建立新的執行個體
- 否則調用doCreateBean()建立新的執行個體
InstantiationAwareBeanPostProcessor是一個特殊的BeanPostProcessor接口,主要在spring架構内部使用,用于spring架構本身實作代理(spring aop)。
spring官方說 InstantiationAwareBeanPostProcessor 是面向spring架構本身|内部的,不推薦開發者使用,盡量用BeanPostProcessor代替。
BeanFactoryPostProcessor
BeanFactoryPostProcessor、BeanPostProcessor都是後置處理器(PostProcessor),用于加工處理,容易混淆,差別如下
- 加工對象不同:BeanFactoryPostProcessor用于對BeanFactory進行加工處理,BeanPostProcessor用于對Bean進行加工處理
- 作用時機不同:BeanFactoryPostProcessor作用于spring容器加載bean定義之後、bean執行個體化之前,BeanPostProcessor作用于bean初始化階段。