Spring?Bean是如何初始化的詳解
前言
做Java都有很多年了,一直有一個(gè)疑惑: Spring 如何初始化bean,怎么調(diào)用反射實(shí)例化對(duì)象的,自己動(dòng)手來解除這個(gè)疑惑。 過去我認(rèn)為spring bean對(duì)象實(shí)例化一直都是由BeanPostProcessor接口實(shí)現(xiàn)類去做的,我就是不知道具體那個(gè)實(shí)現(xiàn)類,下面就去驗(yàn)證下這個(gè)猜想。
三級(jí)緩存
為什么面試官特別喜歡問創(chuàng)建bean的三級(jí)緩存,主要是因?yàn)閎ean創(chuàng)建都是伴隨著三級(jí)緩存之間的轉(zhuǎn)換完成的,對(duì)象不同狀態(tài)分別存在不同緩存中,下面我會(huì)在分析代碼時(shí),順便支持對(duì)象如何在緩存中流轉(zhuǎn)的。 先了解下spring 三級(jí)緩存。
/** 一級(jí)緩存 用于存放完全可以使用單例bean,也就是初始化完成并且注入所有依賴 */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** 二級(jí)緩存 過早暴露單例對(duì)象,此時(shí)bean剛剛完成初始化,未完成屬性注入和執(zhí)行 init 方法 */ private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** 三級(jí)緩存 裝載創(chuàng)建bean的工廠對(duì)象 */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)
三級(jí)緩存主要作用: 創(chuàng)建對(duì)象ObjectFactory首先放入三級(jí)換緩存中,當(dāng)調(diào)用getObject 創(chuàng)建實(shí)例時(shí),會(huì)將創(chuàng)建好對(duì)象加入二級(jí)緩存中,并且刪除三級(jí)中緩存,當(dāng)對(duì)象已經(jīng)完成初始化方法和屬性注入,再將緩存添加到一級(jí)緩存中,并且刪除二級(jí)緩存。
doGetBean
從源頭開始找,所有spring bean 初始化都是由AbstractBeanFactory.doGetBean方法實(shí)現(xiàn)的。下面我將源碼減除臃腫部分,貼出來。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//name 前綴處理 beanFactory beanName 帶有&開頭
String beanName = transformedBeanName(name);
Object beanInstance;
//從三級(jí)緩存去取bean,三級(jí)中都沒有則返回null,說明對(duì)象還沒有創(chuàng)建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) { //如果緩存中bean 是FactoryBean實(shí)例,要通過接口獲取到實(shí)際bean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//判斷bean對(duì)象標(biāo)記是否正在創(chuàng)建中,如果正在創(chuàng)建中則不應(yīng)該繼續(xù)下去,出現(xiàn)依賴循環(huán)就會(huì)出現(xiàn)這個(gè)錯(cuò)誤
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 檢查父容器是否存在,嘗試從父容器中獲取
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) { //緩存中標(biāo)記beanName 正在被創(chuàng)建
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) { //bean 中@DependsOn 信息,用于標(biāo)記bean之間初始化順序,優(yōu)先創(chuàng)建@DependsOn 中bean
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(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//創(chuàng)建單例對(duì)象
if (mbd.isSingleton()) { //重點(diǎn)就在這里實(shí)例化對(duì)象 ,getSingleton 就是在這里將創(chuàng)建完成對(duì)象加入到一級(jí)緩存中
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex)
destroySingleton(beanName);
throw ex;
}
});
//如果生成bean 是FactoryBean ,再獲取真正的對(duì)象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//作用域 = prototype,因?yàn)椴粫?huì)放入緩存中,每次獲取都要重新創(chuàng)建
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else { // session request 這些作用域,由作用域容器去管理這些對(duì)象
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();
}
}
//返回初始化成功的對(duì)象,一個(gè)對(duì)象初始化就這樣完成的了
return adaptBeanInstance(name, beanInstance, requiredType);
}大概總結(jié)一下上面代碼流程:
- 先從三級(jí)緩存中獲取,如果緩存中都沒有。再去判斷是否存在父容器,從父容器中獲取。沒有正式進(jìn)入bean 初始化流程,先根據(jù)beanName 獲取到RootBeanDefinition,bean類元信息、先處理dependsOn中bean,保證bean依賴的創(chuàng)建順序,下面會(huì)說明
org.springframework.context.annotation.@DependsOn這個(gè)注解。下一步按照不同scope 進(jìn)行bean 對(duì)象初始化。初始化流程就是這樣,我們將目光放在單例bean 如何實(shí)例化,集中關(guān)注AbstractAutowireCapableBeanFactory.createBean獲取注冊(cè)一個(gè)單例對(duì)象
@DependsOn 注解意思是實(shí)例化某個(gè)對(duì)象依賴于某一個(gè)實(shí)例化,但是不需要持有這個(gè)實(shí)例對(duì)象。比如bean A上 需要依賴bean b才能實(shí)例化,但是bean b 不需要作為他的屬性,常常用于不同實(shí)例實(shí)例化順序標(biāo)記。
看下getSingleton方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) { //標(biāo)記bean 是否在銷毀
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!)");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
}
catch (BeanCreationException ex) {
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject); //就是在這里刪除二三級(jí)緩存,提交到一級(jí)緩存
}
}
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);
}
}添加到一級(jí)緩存則說明bean已經(jīng)完成實(shí)例化,可以正常使用了。下面看下如何進(jìn)行實(shí)例化和屬性注入的。
createBean
下面進(jìn)入AbstractAutowireCapableBeanFactory.createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
//克隆一份mbd => mbdToUse
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
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 增強(qiáng)返回一個(gè)代理對(duì)象,這個(gè)生成AOP的代理對(duì)象,使用多個(gè)BeanPostProcessors來處理
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);
}
try {
// bean 對(duì)象實(shí)例化就這里實(shí)現(xiàn)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}這里邏輯就比較簡單了 ,克隆一份RootBeanDefinition用于初始化對(duì)象,resolveBeforeInstantiation 主要用于初始化代理對(duì)象情況,主要使用BeanPostProcessor子類InstantiationAwareBeanPostProcessor實(shí)現(xiàn)方法去實(shí)現(xiàn)對(duì)象初始化,并且在實(shí)例化成功后在調(diào)用后置方法進(jìn)行對(duì)象依賴注入,這里可以看見此方法返回對(duì)象直接跳出方法棧,這里可以看出單例和代理對(duì)象還是有區(qū)別的。單例對(duì)象初始化就在doCreateBean 實(shí)現(xiàn)了
doCreateBean
下面就是AbstractAutowireCapableBeanFactory.doCreateBean非常接近對(duì)象如何實(shí)例化的了
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args); //這個(gè)就是實(shí)例化方法
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 使用BeanDefinitionPostProcessors 對(duì)合并bean進(jìn)行實(shí)例化
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;
}
}
// 這里就需要用到上面說的三級(jí)緩存知識(shí)了
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName)); //是否放入第三級(jí)緩存中
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); //將已經(jīng)實(shí)例化的對(duì)象加入到第三級(jí)緩存 singletonFactories
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper); //對(duì)屬性進(jìn)入注入,下面會(huì)具體分析的
exposedObject = initializeBean(beanName, exposedObject, mbd); //執(zhí)行初始化方法,或者注入Aware 接口bean
}
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);
}
}
//下面代碼省略
//主要就是對(duì)設(shè)置了DisposableBean 接口銷毀鉤子方法處理
}這里代碼主要分成三部分
- 初始化實(shí)例,創(chuàng)建對(duì)象完成,并且添加到3級(jí)緩存。第3級(jí)緩存常常用于存儲(chǔ)代理對(duì)象,因?yàn)橛行╊愋枰獎(jiǎng)討B(tài)代理方法,需要生成代理對(duì)象,會(huì)委派給第三級(jí)緩存方法ObjectFactroy去實(shí)現(xiàn)的,普通對(duì)象如果不需要會(huì)直接返回。
- 對(duì)實(shí)例化bean進(jìn)行屬性注入
- 執(zhí)行初始化方法,DisposableBean接口加入到disposableBeans容器中
instantiateBean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
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());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {// 有實(shí)現(xiàn)Supplier 接口,由instanceSupplier.get() 方法創(chuàng)建實(shí)例
return obtainFromSupplier(instanceSupplier, beanName);
}
//factoryName 使用工廠模式創(chuàng)建bean,調(diào)用工廠方法去創(chuàng)建,這個(gè)支持靜態(tài)方法和factoryBean.invoke
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false; //標(biāo)記構(gòu)造函數(shù)是否需要參數(shù)
boolean autowireNecessary = false; //標(biāo)記構(gòu)造方法的參數(shù)是否使用注入方式
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
//使用構(gòu)造函數(shù)注入方式實(shí)例化
return autowireConstructor(beanName, mbd, null, null);
}
else {
//實(shí)例化對(duì)象
return instantiateBean(beanName, mbd);
}
}
// 獲取構(gòu)造函數(shù)參數(shù)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
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.
return instantiateBean(beanName, mbd);
}實(shí)例化方法instantiateBean最終會(huì)調(diào)用SimpleInstantiationStrategy.instantiate 進(jìn)行實(shí)例化
instantiate
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
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 {
constructorToUse = clazz.getDeclaredConstructor(); //獲取構(gòu)造函數(shù)
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse); //調(diào)用構(gòu)造函數(shù)進(jìn)行實(shí)例化
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}instantiateClass
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
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 {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse); //調(diào)用構(gòu)造器進(jìn)行初始化
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}這里要注意下先判斷bean是否有方法重寫的,沒有則使用反射生成的構(gòu)造器,有就使用gclib方式創(chuàng)建代理對(duì)象,具體實(shí)現(xiàn)方式就在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate,有興趣同學(xué)可以去學(xué)習(xí)下。 到此一個(gè)簡單bean實(shí)例化完成了。
注入
下面進(jìn)入IOC另一個(gè)特點(diǎn),bean注入,先從AbstractAutowireCapableBeanFactory.populateBean方法開始
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 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.
//通過InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 如果返回true,目標(biāo)實(shí)例內(nèi)部的返回值會(huì)被populate,否則populate這個(gè)過程會(huì)被忽視
//翻譯說如果返回true可以執(zhí)行字段注入 真的6666啊
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//獲取注入方式分布有4種
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();
//依賴方式,模式都是沒有類型檢查,這種依賴方式一般都是xml 配置用得比較多,沒有配置這里都是返回false
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); //獲取注解標(biāo)注需要注入方法或者是字段,并且進(jìn)行注入
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);
}
}小知識(shí)點(diǎn): AutowireCapableBeanFactory.AUTOWIRE_NO 表明不會(huì)對(duì)當(dāng)前Bean進(jìn)行外部類的注入,常規(guī)使用@Autowire、@Resource 都是這類型 剩下三種都是通過xml 或者 AutowireCapableBeanFactory.autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) 進(jìn)行設(shè)置autowireMode 。
根據(jù)上面代碼可以知道主流程bean注入都是由InstantiationAwareBeanPostProcessor 進(jìn)行處理的,簡單說明接口方法
| 方法 | 描述 |
|---|---|
| postProcessBeforeInitialization | 方法是最 先執(zhí)行的方法,它在目標(biāo)對(duì)象實(shí)例化之前調(diào)用,該方法的返回值類型是Object,我們可以返回任何類型的值。由于這個(gè)時(shí)候目標(biāo)對(duì)象還未實(shí)例化,所以這個(gè)返回值可以用來代替原本該生成的目標(biāo)對(duì)象的實(shí)例(比如代理對(duì)象)。如果該方法的返回值代替原本該生成的目標(biāo)對(duì)象,后續(xù)只有postProcessAfterInitialization方法會(huì)調(diào)用,其它方法不再調(diào)用;否則按照正常的流程走 |
| postProcessAfterInitialization | 方法在目標(biāo)對(duì)象實(shí)例化之后調(diào)用,這個(gè)時(shí)候?qū)ο笠呀?jīng)被實(shí)例化,但是該實(shí)例的屬性還未被設(shè)置,都是null。因?yàn)樗姆祷刂凳菦Q定要不要調(diào)用postProcessPropertyValues方法的其中一個(gè)因素(因?yàn)檫€有一個(gè)因素是mbd.getDependencyCheck());如果該方法返回false,并且不需要check,那么postProcessPropertyValues就會(huì)被忽略不執(zhí)行;如果返回true,postProcessPropertyValues就會(huì)被執(zhí)行 |
| postProcessPropertyValues | 對(duì)bean屬性值賦值后調(diào)用,對(duì)屬性值的修改。如果postProcessAfterInstantiation方法返回false,該方法可能不會(huì)被調(diào)用??梢栽谠摲椒▋?nèi)對(duì)屬性值進(jìn)行修改 |
| postProcessProperties | Bean屬性賦值就是調(diào)用這個(gè)方法的 |
InstantiationAwareBeanPostProcessor 接口實(shí)現(xiàn)類主要分3個(gè)
- ConfigurationClassPostProcessor:看類名就知道處理@Configuration實(shí)例化,并沒有屬性注入邏輯,不詳講略過。
- CommonAnnotationBeanPostProcessor:這個(gè)類就是實(shí)現(xiàn)bean注入,但是是實(shí)現(xiàn)JSR-250 注解、@Resource,@EJB、@WebServiceRef,@WebServiceContext,@PostConstrusct、@PreDestory這些注解實(shí)現(xiàn)。
- AutowiredAnnotationBeanPostProcessor:實(shí)現(xiàn) @Autowired、@Value注入,并且支持JSR-330's @Inject,主要分析這個(gè)類就可以知道bean 注入的。
AutowiredAnnotationBeanPostProcessor分析
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
@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.
}
}在初始化時(shí)就將支持注解加入集合中,再使用掃描器去掃描方法、構(gòu)造器、字段,如果有這些注解就進(jìn)行注入。
看下怎么判斷是否需要注入的
@Nullable
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;
} AccessibleObject 是Method、Field、Constructor 父類。
postProcessProperties 如何實(shí)現(xiàn)bean注入的
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//獲取需要注入字段,方法
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;
}
//下面就行獲取InjectionMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 快速從緩存中獲取,如果沒有加鎖去解析,然后在結(jié)果放入緩存中
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) { //雙重檢查
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}- InjectionMetadata 主要是集合bean需要被注入類型,因?yàn)橐呀?jīng)解析過bean Class信息了,相當(dāng)于解析結(jié)果裝起來
看下如何去掃描方法、字段的
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//從給定注解中判斷class 是否攜帶這個(gè)注解
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//遍歷所有Field,找出掃描的注解,特意標(biāo)注不支持static 修飾field
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;
}
// 獲取注解內(nèi) required 值
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//獲取方法上橋接方法,因?yàn)榉盒皖愋筒脸?,要?duì)橋接方法進(jìn)行安全檢查,防止在調(diào)用是出現(xiàn)異常
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//獲取注解
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
//方法安全檢查
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) { //不支持靜態(tài)方法注入
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
// 這樣寫是為了后面加入排在隊(duì)列前面,父類屬性優(yōu)先于子類
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class); //這里寫得很好,向上解析父類,直到是Object 為止
return InjectionMetadata.forElements(elements, clazz);
}邏輯非常簡單,就是根據(jù)給定注解去class獲取指定的注解,從而獲取到需要注入類型,但是幾行簡單的代碼可以看出強(qiáng)大編碼能力,學(xué)習(xí)了??。 現(xiàn)在需要注入對(duì)象已經(jīng)獲取到,看如何注入吧
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter(); //類型轉(zhuǎn)換器
Object value;
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
// 將注入關(guān)系添加到容器中,方便bean銷毀時(shí)同步銷毀
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { //這些都是為了緩存起來
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
}主要核心是如從緩存獲取到需要注入類型實(shí)例在beanFactory.resolveDependency中 進(jìn)入DefaultListableBeanFactory看下
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//懶加載 掃描@Lazy注解,返回一個(gè)代理對(duì)象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}@Lazy 使用注解修飾bean 或者Class,在容器初始化化時(shí)不會(huì)立刻創(chuàng)建,只要需要使用bean才會(huì)創(chuàng)建的。 根據(jù)類型Optional、ObjectFactory、Provider,還有懶加載情景不同的處理,這些處理本質(zhì)都是要調(diào)用doResolveDependency方法初始化對(duì)象,無論那種對(duì)象都要 獲取原始對(duì)象然后再交給這些接口去包裝增強(qiáng)。
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//如果這個(gè)注入是通過構(gòu)造器注入,可以從構(gòu)造器解析緩存中去獲取注入信息點(diǎn)
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//嘗試從注解中獲取默認(rèn)值 @Value 的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());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
//多種混合類型處理,stream、collection、Map Array 這些
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//根據(jù)類型獲取容器中bean名,返回map key就是bean名,value 初始從容器中獲取對(duì)象,如果沒有找到就會(huì)拋出異常了
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) { //出現(xiàn)一個(gè)類型,不同實(shí)例,可以根據(jù)@Primary, @Priority、屬性名方式去配置
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { //沒有確定,拋出異常
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) { //這里其實(shí)就是從容器中獲取實(shí)例,如果這時(shí)候沒有初始化,就走上面初始化流程
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}這個(gè)方法簡單做個(gè)總結(jié),先是處理 @Value 情況,然后通過findAutowireCandidates 通過類型去容器中獲取實(shí)例,如何實(shí)例還沒有初始化,就會(huì)調(diào)用上面那個(gè)初始化過程,將初始化對(duì)象返回。根據(jù)注入類型進(jìn)行相應(yīng)處理,像stream、Collection,這些混合類型都是直接添加進(jìn)去。如果出現(xiàn)了一個(gè)類型多個(gè)bean情況,這時(shí)就是就是@Primary、@Priority這些注解來判斷或者根據(jù)屬性名去和beanName匹配,最后將bean對(duì)象返回。 這里就簡單看完一個(gè)bean初始化流程了。
總結(jié)
現(xiàn)在知道了Bean實(shí)例化是由一個(gè)策略模式,使用反射攻擊類創(chuàng)建的,和BeanPostProcessor其實(shí)并沒有太多關(guān)系的。像我剛開始學(xué)spring時(shí),老師就說@Autowired 和@Resources向比較,基于類型和beanName進(jìn)行注入的,這樣說不完全正確的。他是通過類型去獲取bean,如果出現(xiàn)一個(gè)類型有多個(gè)beanName,才通過bean和屬性名進(jìn)行注入。使用這么多年Spring了,從來沒有使用過@DependsOn、@Primary、@Priority、@Lookup如果不看源碼還不知道有這個(gè)特性呢??赐暾麄€(gè)源碼,對(duì)bean生命周期有了比較清晰 bean實(shí)例化-> 屬性注入-> 執(zhí)行初始化方法-> 加入spring容器
到此這篇關(guān)于Spring Bean是如何初始化的文章就介紹到這了,更多相關(guān)Spring Bean初始化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC 方法四種類型返回值總結(jié)(你用過幾種)
這篇文章主要介紹了SpringMVC 方法四種類型返回值總結(jié)(你用過幾種),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05
Java中的super關(guān)鍵字_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java中的super關(guān)鍵字的相關(guān)知識(shí),需要的朋友參考下2017-04-04
Mybatis如何傳入多個(gè)參數(shù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Mybatis如何傳入多個(gè)參數(shù)的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Mybatis一對(duì)多與多對(duì)一查詢處理詳解
這篇文章主要給大家介紹了關(guān)于Mybatis一對(duì)多與多對(duì)一查詢處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java Web基于Session的登錄實(shí)現(xiàn)方法
這篇文章主要介紹了Java Web基于Session的登錄實(shí)現(xiàn)方法,涉及Java針對(duì)session的操作及表單提交與驗(yàn)證技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
Spring?Data?Jpa?復(fù)雜查詢方式總結(jié)(多表關(guān)聯(lián)及自定義分頁)
這篇文章主要介紹了Spring?Data?Jpa?復(fù)雜查詢方式總結(jié)(多表關(guān)聯(lián)及自定義分頁),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
利用logback 設(shè)置不同包下的日志級(jí)別
這篇文章主要介紹了利用logback 設(shè)置不同包下的日志級(jí)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12

