Spring?Bean是如何初始化的詳解
前言
做Java都有很多年了,一直有一個疑惑: Spring 如何初始化bean,怎么調(diào)用反射實例化對象的,自己動手來解除這個疑惑。 過去我認為spring bean對象實例化一直都是由BeanPostProcessor接口實現(xiàn)類去做的,我就是不知道具體那個實現(xiàn)類,下面就去驗證下這個猜想。
三級緩存
為什么面試官特別喜歡問創(chuàng)建bean的三級緩存,主要是因為bean創(chuàng)建都是伴隨著三級緩存之間的轉(zhuǎn)換完成的,對象不同狀態(tài)分別存在不同緩存中,下面我會在分析代碼時,順便支持對象如何在緩存中流轉(zhuǎn)的。 先了解下spring 三級緩存。
/** 一級緩存 用于存放完全可以使用單例bean,也就是初始化完成并且注入所有依賴 */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** 二級緩存 過早暴露單例對象,此時bean剛剛完成初始化,未完成屬性注入和執(zhí)行 init 方法 */ private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** 三級緩存 裝載創(chuàng)建bean的工廠對象 */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)
三級緩存主要作用: 創(chuàng)建對象ObjectFactory首先放入三級換緩存中,當調(diào)用getObject 創(chuàng)建實例時,會將創(chuàng)建好對象加入二級緩存中,并且刪除三級中緩存,當對象已經(jīng)完成初始化方法和屬性注入,再將緩存添加到一級緩存中,并且刪除二級緩存。
doGetBean
從源頭開始找,所有spring bean 初始化都是由AbstractBeanFactory.doGetBean方法實現(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;
//從三級緩存去取bean,三級中都沒有則返回null,說明對象還沒有創(chuàng)建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) { //如果緩存中bean 是FactoryBean實例,要通過接口獲取到實際bean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//判斷bean對象標記是否正在創(chuàng)建中,如果正在創(chuàng)建中則不應(yīng)該繼續(xù)下去,出現(xiàn)依賴循環(huán)就會出現(xiàn)這個錯誤
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) { //緩存中標記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 信息,用于標記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)建單例對象
if (mbd.isSingleton()) { //重點就在這里實例化對象 ,getSingleton 就是在這里將創(chuàng)建完成對象加入到一級緩存中
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex)
destroySingleton(beanName);
throw ex;
}
});
//如果生成bean 是FactoryBean ,再獲取真正的對象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//作用域 = prototype,因為不會放入緩存中,每次獲取都要重新創(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 這些作用域,由作用域容器去管理這些對象
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);
}大概總結(jié)一下上面代碼流程:
- 先從三級緩存中獲取,如果緩存中都沒有。再去判斷是否存在父容器,從父容器中獲取。沒有正式進入bean 初始化流程,先根據(jù)beanName 獲取到RootBeanDefinition,bean類元信息、先處理dependsOn中bean,保證bean依賴的創(chuàng)建順序,下面會說明
org.springframework.context.annotation.@DependsOn這個注解。下一步按照不同scope 進行bean 對象初始化。初始化流程就是這樣,我們將目光放在單例bean 如何實例化,集中關(guān)注AbstractAutowireCapableBeanFactory.createBean獲取注冊一個單例對象
@DependsOn 注解意思是實例化某個對象依賴于某一個實例化,但是不需要持有這個實例對象。比如bean A上 需要依賴bean b才能實例化,但是bean b 不需要作為他的屬性,常常用于不同實例實例化順序標記。
看下getSingleton方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) { //標記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); //就是在這里刪除二三級緩存,提交到一級緩存
}
}
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);
}
}添加到一級緩存則說明bean已經(jīng)完成實例化,可以正常使用了。下面看下如何進行實例化和屬性注入的。
createBean
下面進入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 增強返回一個代理對象,這個生成AOP的代理對象,使用多個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 對象實例化就這里實現(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用于初始化對象,resolveBeforeInstantiation 主要用于初始化代理對象情況,主要使用BeanPostProcessor子類InstantiationAwareBeanPostProcessor實現(xiàn)方法去實現(xiàn)對象初始化,并且在實例化成功后在調(diào)用后置方法進行對象依賴注入,這里可以看見此方法返回對象直接跳出方法棧,這里可以看出單例和代理對象還是有區(qū)別的。單例對象初始化就在doCreateBean 實現(xiàn)了
doCreateBean
下面就是AbstractAutowireCapableBeanFactory.doCreateBean非常接近對象如何實例化的了
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); //這個就是實例化方法
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 使用BeanDefinitionPostProcessors 對合并bean進行實例化
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;
}
}
// 這里就需要用到上面說的三級緩存知識了
// 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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); //將已經(jīng)實例化的對象加入到第三級緩存 singletonFactories
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper); //對屬性進入注入,下面會具體分析的
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);
}
}
//下面代碼省略
//主要就是對設(shè)置了DisposableBean 接口銷毀鉤子方法處理
}這里代碼主要分成三部分
- 初始化實例,創(chuàng)建對象完成,并且添加到3級緩存。第3級緩存常常用于存儲代理對象,因為有些類需要動態(tài)代理方法,需要生成代理對象,會委派給第三級緩存方法ObjectFactroy去實現(xiàn)的,普通對象如果不需要會直接返回。
- 對實例化bean進行屬性注入
- 執(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) {// 有實現(xiàn)Supplier 接口,由instanceSupplier.get() 方法創(chuàng)建實例
return obtainFromSupplier(instanceSupplier, beanName);
}
//factoryName 使用工廠模式創(chuàng)建bean,調(diào)用工廠方法去創(chuàng)建,這個支持靜態(tài)方法和factoryBean.invoke
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false; //標記構(gòu)造函數(shù)是否需要參數(shù)
boolean autowireNecessary = false; //標記構(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ù)注入方式實例化
return autowireConstructor(beanName, mbd, null, null);
}
else {
//實例化對象
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);
}實例化方法instantiateBean最終會調(diào)用SimpleInstantiationStrategy.instantiate 進行實例化
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ù)進行實例化
}
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)造器進行初始化
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}這里要注意下先判斷bean是否有方法重寫的,沒有則使用反射生成的構(gòu)造器,有就使用gclib方式創(chuàng)建代理對象,具體實現(xiàn)方式就在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate,有興趣同學(xué)可以去學(xué)習(xí)下。 到此一個簡單bean實例化完成了。
注入
下面進入IOC另一個特點,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,目標實例內(nèi)部的返回值會被populate,否則populate這個過程會被忽視
//翻譯說如果返回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); //獲取注解標注需要注入方法或者是字段,并且進行注入
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);
}
}小知識點: AutowireCapableBeanFactory.AUTOWIRE_NO 表明不會對當前Bean進行外部類的注入,常規(guī)使用@Autowire、@Resource 都是這類型 剩下三種都是通過xml 或者 AutowireCapableBeanFactory.autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) 進行設(shè)置autowireMode 。
根據(jù)上面代碼可以知道主流程bean注入都是由InstantiationAwareBeanPostProcessor 進行處理的,簡單說明接口方法
| 方法 | 描述 |
|---|---|
| postProcessBeforeInitialization | 方法是最 先執(zhí)行的方法,它在目標對象實例化之前調(diào)用,該方法的返回值類型是Object,我們可以返回任何類型的值。由于這個時候目標對象還未實例化,所以這個返回值可以用來代替原本該生成的目標對象的實例(比如代理對象)。如果該方法的返回值代替原本該生成的目標對象,后續(xù)只有postProcessAfterInitialization方法會調(diào)用,其它方法不再調(diào)用;否則按照正常的流程走 |
| postProcessAfterInitialization | 方法在目標對象實例化之后調(diào)用,這個時候?qū)ο笠呀?jīng)被實例化,但是該實例的屬性還未被設(shè)置,都是null。因為它的返回值是決定要不要調(diào)用postProcessPropertyValues方法的其中一個因素(因為還有一個因素是mbd.getDependencyCheck());如果該方法返回false,并且不需要check,那么postProcessPropertyValues就會被忽略不執(zhí)行;如果返回true,postProcessPropertyValues就會被執(zhí)行 |
| postProcessPropertyValues | 對bean屬性值賦值后調(diào)用,對屬性值的修改。如果postProcessAfterInstantiation方法返回false,該方法可能不會被調(diào)用??梢栽谠摲椒▋?nèi)對屬性值進行修改 |
| postProcessProperties | Bean屬性賦值就是調(diào)用這個方法的 |
InstantiationAwareBeanPostProcessor 接口實現(xiàn)類主要分3個
- ConfigurationClassPostProcessor:看類名就知道處理@Configuration實例化,并沒有屬性注入邏輯,不詳講略過。
- CommonAnnotationBeanPostProcessor:這個類就是實現(xiàn)bean注入,但是是實現(xiàn)JSR-250 注解、@Resource,@EJB、@WebServiceRef,@WebServiceContext,@PostConstrusct、@PreDestory這些注解實現(xiàn)。
- AutowiredAnnotationBeanPostProcessor:實現(xiàn) @Autowired、@Value注入,并且支持JSR-330's @Inject,主要分析這個類就可以知道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.
}
}在初始化時就將支持注解加入集合中,再使用掃描器去掃描方法、構(gòu)造器、字段,如果有這些注解就進行注入。
看下怎么判斷是否需要注入的
@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 如何實現(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需要被注入類型,因為已經(jīng)解析過bean Class信息了,相當于解析結(jié)果裝起來
看下如何去掃描方法、字段的
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//從給定注解中判斷class 是否攜帶這個注解
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,找出掃描的注解,特意標注不支持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 -> {
//獲取方法上橋接方法,因為泛型類型擦除,要對橋接方法進行安全檢查,防止在調(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));
}
});
// 這樣寫是為了后面加入排在隊列前面,父類屬性優(yōu)先于子類
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class); //這里寫得很好,向上解析父類,直到是Object 為止
return InjectionMetadata.forElements(elements, clazz);
}邏輯非常簡單,就是根據(jù)給定注解去class獲取指定的注解,從而獲取到需要注入類型,但是幾行簡單的代碼可以看出強大編碼能力,學(xué)習(xí)了??。 現(xiàn)在需要注入對象已經(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銷毀時同步銷毀
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;
}
}主要核心是如從緩存獲取到需要注入類型實例在beanFactory.resolveDependency中 進入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注解,返回一個代理對象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}@Lazy 使用注解修飾bean 或者Class,在容器初始化化時不會立刻創(chuàng)建,只要需要使用bean才會創(chuàng)建的。 根據(jù)類型Optional、ObjectFactory、Provider,還有懶加載情景不同的處理,這些處理本質(zhì)都是要調(diào)用doResolveDependency方法初始化對象,無論那種對象都要 獲取原始對象然后再交給這些接口去包裝增強。
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//如果這個注入是通過構(gòu)造器注入,可以從構(gòu)造器解析緩存中去獲取注入信息點
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//嘗試從注解中獲取默認值 @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 初始從容器中獲取對象,如果沒有找到就會拋出異常了
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)一個類型,不同實例,可以根據(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) { //這里其實就是從容器中獲取實例,如果這時候沒有初始化,就走上面初始化流程
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);
}
}這個方法簡單做個總結(jié),先是處理 @Value 情況,然后通過findAutowireCandidates 通過類型去容器中獲取實例,如何實例還沒有初始化,就會調(diào)用上面那個初始化過程,將初始化對象返回。根據(jù)注入類型進行相應(yīng)處理,像stream、Collection,這些混合類型都是直接添加進去。如果出現(xiàn)了一個類型多個bean情況,這時就是就是@Primary、@Priority這些注解來判斷或者根據(jù)屬性名去和beanName匹配,最后將bean對象返回。 這里就簡單看完一個bean初始化流程了。
總結(jié)
現(xiàn)在知道了Bean實例化是由一個策略模式,使用反射攻擊類創(chuàng)建的,和BeanPostProcessor其實并沒有太多關(guān)系的。像我剛開始學(xué)spring時,老師就說@Autowired 和@Resources向比較,基于類型和beanName進行注入的,這樣說不完全正確的。他是通過類型去獲取bean,如果出現(xiàn)一個類型有多個beanName,才通過bean和屬性名進行注入。使用這么多年Spring了,從來沒有使用過@DependsOn、@Primary、@Priority、@Lookup如果不看源碼還不知道有這個特性呢??赐暾麄€源碼,對bean生命周期有了比較清晰 bean實例化-> 屬性注入-> 執(zhí)行初始化方法-> 加入spring容器
到此這篇關(guān)于Spring Bean是如何初始化的文章就介紹到這了,更多相關(guān)Spring Bean初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC 方法四種類型返回值總結(jié)(你用過幾種)
這篇文章主要介紹了SpringMVC 方法四種類型返回值總結(jié)(你用過幾種),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05
Java中的super關(guān)鍵字_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了Java中的super關(guān)鍵字的相關(guān)知識,需要的朋友參考下2017-04-04
Mybatis如何傳入多個參數(shù)的實現(xiàn)代碼
這篇文章主要介紹了Mybatis如何傳入多個參數(shù)的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Java Web基于Session的登錄實現(xiàn)方法
這篇文章主要介紹了Java Web基于Session的登錄實現(xiàn)方法,涉及Java針對session的操作及表單提交與驗證技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10
Spring?Data?Jpa?復(fù)雜查詢方式總結(jié)(多表關(guān)聯(lián)及自定義分頁)
這篇文章主要介紹了Spring?Data?Jpa?復(fù)雜查詢方式總結(jié)(多表關(guān)聯(lián)及自定義分頁),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02

