0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Spring容器原始Bean是如何創(chuàng)建的?Spring源碼中方法的執(zhí)行順序

OSC開(kāi)源社區(qū) ? 來(lái)源:江南一點(diǎn)雨 ? 2023-08-04 10:12 ? 次閱讀

以下內(nèi)容基于 Spring6.0.4。

這個(gè)話題其實(shí)非常龐大,我本來(lái)想從 getBean 方法講起,但一想這樣講完估計(jì)很多小伙伴就懵了,所以我們還是一步一步來(lái),今天我主要是想和小伙伴們講講 Spring 容器創(chuàng)建 Bean 最最核心的 createBeanInstance 方法,這個(gè)方法專門(mén)用來(lái)創(chuàng)建一個(gè)原始 Bean 實(shí)例。

這里就以 Spring 源碼中方法的執(zhí)行順序?yàn)槔齺?lái)和小伙伴們分享。

1. doCreateBean

AbstractAutowireCapableBeanFactory#doCreateBean 就是 Bean 的創(chuàng)建方法,但是 Bean 的創(chuàng)建涉及到的步驟非常多,包括各種需要調(diào)用的前置后置處理器方法,今天我主要是想和大家聊聊單純的創(chuàng)建 Bean 的過(guò)程,其他方法咱們后面文章繼續(xù)。

在 doCreateBean 方法中,有如下一行方法調(diào)用:

protectedObjectdoCreateBean(StringbeanName,RootBeanDefinitionmbd,@NullableObject[]args)
throwsBeanCreationException{
//Instantiatethebean.
BeanWrapperinstanceWrapper=null;
if(mbd.isSingleton()){
instanceWrapper=this.factoryBeanInstanceCache.remove(beanName);
}
if(instanceWrapper==null){
instanceWrapper=createBeanInstance(beanName,mbd,args);
}
Objectbean=instanceWrapper.getWrappedInstance();
//...
returnexposedObject;
}

createBeanInstance 這個(gè)方法就是真正的根據(jù)我們的配置去創(chuàng)建一個(gè) Bean 了。

2. createBeanInstance

先來(lái)看源碼:

protectedBeanWrappercreateBeanInstance(StringbeanName,RootBeanDefinitionmbd,@NullableObject[]args){
//Makesurebeanclassisactuallyresolvedatthispoint.
ClassbeanClass=resolveBeanClass(mbd,beanName);
if(beanClass!=null&&!Modifier.isPublic(beanClass.getModifiers())&&!mbd.isNonPublicAccessAllowed()){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Beanclassisn'tpublic,andnon-publicaccessnotallowed:"+beanClass.getName());
}
SupplierinstanceSupplier=mbd.getInstanceSupplier();
if(instanceSupplier!=null){
returnobtainFromSupplier(instanceSupplier,beanName);
}
if(mbd.getFactoryMethodName()!=null){
returninstantiateUsingFactoryMethod(beanName,mbd,args);
}
//Shortcutwhenre-creatingthesamebean...
booleanresolved=false;
booleanautowireNecessary=false;
if(args==null){
synchronized(mbd.constructorArgumentLock){
if(mbd.resolvedConstructorOrFactoryMethod!=null){
resolved=true;
autowireNecessary=mbd.constructorArgumentsResolved;
}
}
}
if(resolved){
if(autowireNecessary){
returnautowireConstructor(beanName,mbd,null,null);
}
else{
returninstantiateBean(beanName,mbd);
}
}
//Candidateconstructorsforautowiring?
Constructor[]ctors=determineConstructorsFromBeanPostProcessors(beanClass,beanName);
if(ctors!=null||mbd.getResolvedAutowireMode()==AUTOWIRE_CONSTRUCTOR||
mbd.hasConstructorArgumentValues()||!ObjectUtils.isEmpty(args)){
returnautowireConstructor(beanName,mbd,ctors,args);
}
//Preferredconstructorsfordefaultconstruction?
ctors=mbd.getPreferredConstructors();
if(ctors!=null){
returnautowireConstructor(beanName,mbd,ctors,null);
}
//Nospecialhandling:simplyuseno-argconstructor.
returninstantiateBean(beanName,mbd);
}

這里就是核心的 Bean 的創(chuàng)建方法了,因此這個(gè)方法我來(lái)和大家詳細(xì)分析一下。

2.1 resolveBeanClass

這個(gè)方法是用來(lái)解析出來(lái)當(dāng)前的 beanClass 對(duì)象,它的核心邏輯就是根據(jù)我們?cè)?XML 文件中配置的類的全路徑,通過(guò)反射加載出來(lái)這個(gè) Class

@Nullable
protectedClassresolveBeanClass(RootBeanDefinitionmbd,StringbeanName,Class...typesToMatch)
throwsCannotLoadBeanClassException{
if(mbd.hasBeanClass()){
returnmbd.getBeanClass();
}
returndoResolveBeanClass(mbd,typesToMatch);
}

首先會(huì)調(diào)用 mbd.hasBeanClass() 方法去判斷是否已經(jīng)通過(guò)反射加載出來(lái) beanClass 了,如果加載出來(lái)了就直接返回,沒(méi)有加載的話,就繼續(xù)執(zhí)行下面的 doResolveBeanClass 去加載。

什么時(shí)候會(huì)走 if 這條線呢?松哥舉一個(gè)例子,如果我們?cè)O(shè)置某一個(gè) Bean 的 Scope 是 prototype 的話,那么當(dāng)?shù)诙潍@取該 Bean 的實(shí)例的時(shí)候,就會(huì)走 if 這條線。

@Nullable
privateClassdoResolveBeanClass(RootBeanDefinitionmbd,Class...typesToMatch)
throwsClassNotFoundException{
//...
StringclassName=mbd.getBeanClassName();
if(className!=null){
Objectevaluated=evaluateBeanDefinitionString(className,mbd);
if(!className.equals(evaluated)){
//Adynamicallyresolvedexpression,supportedasof4.2...
if(evaluatedinstanceofClassclazz){
returnclazz;
}
elseif(evaluatedinstanceofStringstr){
className=str;
freshResolve=true;
}
else{
thrownewIllegalStateException("Invalidclassnameexpressionresult:"+evaluated);
}
}
if(freshResolve){
//Whenresolvingagainstatemporaryclassloader,exitearlyinorder
//toavoidstoringtheresolvedClassinthebeandefinition.
if(dynamicLoader!=null){
returndynamicLoader.loadClass(className);
}
returnClassUtils.forName(className,dynamicLoader);
}
}
//Resolveregularly,cachingtheresultintheBeanDefinition...
returnmbd.resolveBeanClass(beanClassLoader);
}

按理說(shuō),根據(jù)我們配置的類的全路徑加載出來(lái)一個(gè) Class 應(yīng)該是非常容易的,直接 Class.forName 就可以了。

但是?。?!

如果對(duì) Spring 用法比較熟悉的小伙伴就知道,配置 Class 全路徑的時(shí)候,我們不僅可以像下面這樣老老實(shí)實(shí)配置:


我們甚至可以使用 SpEL 來(lái)配置 Bean 名稱,例如我有如下類:

publicclassBeanNameUtils{
publicStringgetName(){
return"org.javaboy.bean.User";
}
}

這里有一個(gè) getName 方法,這個(gè)方法返回的是一個(gè)類的全路徑,現(xiàn)在我們?cè)?XML 文件中可以這樣配置:



在 XML 的 class 屬性中,我們可以直接使用 SpEL 去引用一個(gè)方法的執(zhí)行,用該方法的返回值作為 class 的值。

了解了 Spring 中的這個(gè)玩法,再去看上面的源碼就很好懂了:

首先調(diào)用 mbd.getBeanClassName(); 去獲取到類路徑。

接下來(lái)調(diào)用 evaluateBeanDefinitionString 方法進(jìn)行 SpEL 運(yùn)算,這個(gè)運(yùn)算的目的是為了解析 className 中的 SpEL 表達(dá)式,當(dāng)然,一般情況下 className 就是一個(gè)普通的字符串,不是 SpEL 表達(dá)式,那么解析完成之后就還是原本的字符串。如果是 className 是一個(gè) SpEL,那么合法的解析結(jié)果分為兩種:

首先就是解析之后拿到了一個(gè) Class,那這個(gè)就是我們想要的結(jié)果,直接返回即可。

要么就是解析出來(lái)是一個(gè)字符串,松哥上面舉的例子就是這種情況,那么就把這個(gè)字符串賦值給 className,并且將 freshResolve 屬性設(shè)置為 true,然后在接下來(lái)的 if 分支中去加載 Class。

當(dāng)然,上面這些都是處理特殊情況,一般我們配置的普通 Bean,都是直接走最后一句 mbd.resolveBeanClass(beanClassLoader),這個(gè)方法的邏輯其實(shí)很好懂,我把代碼貼出來(lái)小伙伴們來(lái)瞅一瞅:

@Nullable
publicClassresolveBeanClass(@NullableClassLoaderclassLoader)throwsClassNotFoundException{
StringclassName=getBeanClassName();
if(className==null){
returnnull;
}
ClassresolvedClass=ClassUtils.forName(className,classLoader);
this.beanClass=resolvedClass;
returnresolvedClass;
}

這個(gè)方法就相當(dāng)直白了,根據(jù) className 加載出來(lái) Class 對(duì)象,然后給 beanClass 屬性也設(shè)置上值,這就和一開(kāi)始的 if (mbd.hasBeanClass()) 對(duì)應(yīng)上了。

好了,到此,我們總算是根據(jù) className 拿到 Class 對(duì)象了。

2.2 Supplier 和 factory-method

好了,回到一開(kāi)始的源碼中,接下來(lái)該執(zhí)行如下兩行代碼了:

SupplierinstanceSupplier=mbd.getInstanceSupplier();
if(instanceSupplier!=null){
returnobtainFromSupplier(instanceSupplier,beanName);
}
if(mbd.getFactoryMethodName()!=null){
returninstantiateUsingFactoryMethod(beanName,mbd,args);
}

這兩個(gè)松哥在前面的文章中和小伙伴們已經(jīng)講過(guò)了(Spring5 中更優(yōu)雅的第三方 Bean 注入):前面的 obtainFromSupplier 方法是 Spring5 開(kāi)始推出來(lái)的 Supplier,通過(guò)回調(diào)的方式去獲取一個(gè)對(duì)象;第二個(gè)方法 instantiateUsingFactoryMethod 則是通過(guò)配置的 factory-method 來(lái)獲取到一個(gè) Bean 實(shí)例。

對(duì)這兩個(gè)方法不熟悉的小伙伴可以參考前面的文章:Spring5 中更優(yōu)雅的第三方 Bean 注入。

2.3 re-create 邏輯

繼續(xù)回到一開(kāi)始的源碼中,接下來(lái)是一段 re-create 的處理邏輯,如下:

booleanresolved=false;
booleanautowireNecessary=false;
if(args==null){
synchronized(mbd.constructorArgumentLock){
if(mbd.resolvedConstructorOrFactoryMethod!=null){
resolved=true;
autowireNecessary=mbd.constructorArgumentsResolved;
}
}
}
if(resolved){
if(autowireNecessary){
returnautowireConstructor(beanName,mbd,null,null);
}
else{
returninstantiateBean(beanName,mbd);
}
}

根據(jù)前面的介紹,我們現(xiàn)在已經(jīng)獲取到 Class 對(duì)象了,接下來(lái)直接調(diào)用相應(yīng)的構(gòu)造方法就可以獲取到 Bean 實(shí)例了。但是這個(gè) Class 對(duì)象可能存在多個(gè)構(gòu)造方法,所以還需要一堆流程去確定到底調(diào)用哪個(gè)構(gòu)造方法。

所以這里會(huì)先去判斷 resolvedConstructorOrFactoryMethod 是否不為空,不為空的話,說(shuō)明這個(gè) Bean 之前已經(jīng)創(chuàng)建過(guò)了,該用什么方法創(chuàng)建等等問(wèn)題都已經(jīng)確定了,所以這次就不用重新再去確定了(resolved = true)。另一方面,autowireNecessary 表示構(gòu)造方法的參數(shù)是否已經(jīng)處理好了,這個(gè)屬性為 true 則表示構(gòu)造方法的參數(shù)已經(jīng)處理好了,那么就可以調(diào)用 autowireConstructor 方法去創(chuàng)建一個(gè) Bean 出來(lái),否則調(diào)用 instantiateBean 方法初始化 Bean。

這里涉及到的 autowireConstructor 和 instantiateBean 方法我們先不細(xì)說(shuō)了,因?yàn)樵诤竺孢€會(huì)再次涉及到。

2.4 構(gòu)造器注入

繼續(xù)回到一開(kāi)始的源碼中,接下來(lái)就是針對(duì)各種處理器的預(yù)處理了:

Constructor[]ctors=determineConstructorsFromBeanPostProcessors(beanClass,beanName);
if(ctors!=null||mbd.getResolvedAutowireMode()==AUTOWIRE_CONSTRUCTOR||
mbd.hasConstructorArgumentValues()||!ObjectUtils.isEmpty(args)){
returnautowireConstructor(beanName,mbd,ctors,args);
}

先來(lái)看 determineConstructorsFromBeanPostProcessors 方法,這個(gè)方法主要是考慮到你可能提供了 SmartInstantiationAwareBeanPostProcessor,松哥在前面的文章中和大家專門(mén)講過(guò) BeanPostProcessor(BeanFactoryPostProcessor 和 BeanPostProcessor 有什么區(qū)別?),這里的 SmartInstantiationAwareBeanPostProcessor 算是 BeanPostProcessor 的一種,也是 Bean 的一種增強(qiáng)器。SmartInstantiationAwareBeanPostProcessor 中有一個(gè) determineCandidateConstructors 方法,這個(gè)方法返回某一個(gè) Bean 的構(gòu)造方法,將來(lái)可以通過(guò)這個(gè)構(gòu)造方法初始化某一個(gè) Bean。

我給大家舉一個(gè)簡(jiǎn)單例子,假設(shè)我有如下類:

publicclassUser{
privateStringusername;
privateStringaddress;

publicUser(){
System.out.println("=====noargs=====");
}

publicUser(ObjectProviderusername){
System.out.println("args==username");
this.username=username.getIfAvailable();
}

//省略getter/setter/toString
}

現(xiàn)在我在 Spring 容器中注冊(cè)這個(gè)對(duì)象:



按照我們已有的知識(shí),這個(gè)將來(lái)會(huì)調(diào)用 User 的無(wú)參構(gòu)造方法去完成 User 對(duì)象的初始化。

但是現(xiàn)在,假設(shè)我添加如下一個(gè)處理器:

publicclassMySmartInstantiationAwareBeanPostProcessorimplementsSmartInstantiationAwareBeanPostProcessor{
@Override
publicConstructor[]determineCandidateConstructors(ClassbeanClass,StringbeanName)throwsBeansException{
if("user".equals(beanName)){
Constructorconstructor=null;
try{
constructor=beanClass.getConstructor(ObjectProvider.class);
}catch(NoSuchMethodExceptione){
thrownewRuntimeException(e);
}
returnnewConstructor[]{constructor};
}
returnSmartInstantiationAwareBeanPostProcessor.super.determineCandidateConstructors(beanClass,beanName);
}
}

在 determineCandidateConstructors 方法中,返回一個(gè)有參構(gòu)造方法,那么將來(lái) Spring 容器會(huì)通過(guò)這里返回的有參構(gòu)造方法去創(chuàng)建 User 對(duì)象,而不是通過(guò)無(wú)參構(gòu)造方法去創(chuàng)建 User 對(duì)象。

最后,將這個(gè)處理器注冊(cè)到 Spring 容器:


現(xiàn)在,當(dāng)我們啟動(dòng) Spring 容器的時(shí)候,User 就是通過(guò)有參構(gòu)造方法初始化的,而不是無(wú)參構(gòu)造方法。之所以會(huì)這樣,就是因?yàn)楸拘」?jié)一開(kāi)始提到的源碼 determineConstructorsFromBeanPostProcessors,這個(gè)方法就是去查看有無(wú) SmartInstantiationAwareBeanPostProcessor,如果有,就調(diào)用對(duì)應(yīng)的方法找到處理器并返回。

這個(gè)弄懂之后,if 中其他幾種情況就好理解了,mbd.getResolvedAutowireMode() 是查看當(dāng)前對(duì)象的注入方式,這個(gè)一般是在 XML 中配置的,不過(guò)日常開(kāi)發(fā)中我們一般不會(huì)配置這個(gè)屬性,如果需要配置,方式如下:



如果添加了 autowire="constructor" 就表示要通過(guò)構(gòu)造方法進(jìn)行注入,那么這里也會(huì)進(jìn)入到 if 中。

if 里邊剩下的幾個(gè)條件都好說(shuō),就是看是否有配置構(gòu)造方法參數(shù),如果配置了,那么也直接調(diào)用相應(yīng)的構(gòu)造方法就行了。

這里最終執(zhí)行的是 autowireConstructor 方法,這個(gè)方法比較長(zhǎng),我就不貼出來(lái)了,和大家說(shuō)一說(shuō)它的思路:

首先把能獲取到的構(gòu)造方法都拿出來(lái),如果構(gòu)造方法只有一個(gè),且目前也沒(méi)有任何和構(gòu)造方法有關(guān)的參數(shù),那就直接用這個(gè)構(gòu)造方法就行了。

如果第一步不能解決問(wèn)題,接下來(lái)就遍歷所有的構(gòu)造方法,并且和已有的參數(shù)進(jìn)行參數(shù)數(shù)量和類型比對(duì),找到合適的構(gòu)造方法并調(diào)用。

2.5 PreferredConstructors

繼續(xù)回到一開(kāi)始的源碼中,接下來(lái)是這樣了:

ctors=mbd.getPreferredConstructors();
if(ctors!=null){
returnautowireConstructor(beanName,mbd,ctors,null);
}

這塊代碼看字面好理解,就是獲取到主構(gòu)造方法,不過(guò)這個(gè)是針對(duì) Kotlin 的,跟我們 Java 無(wú)關(guān),我就不啰嗦了。

2.6 instantiateBean

最后就是 instantiateBean 方法了,這個(gè)方法就比較簡(jiǎn)單了,我把代碼貼一下小伙伴們應(yīng)該自己都能看明白:

protectedBeanWrapperinstantiateBean(StringbeanName,RootBeanDefinitionmbd){
try{
ObjectbeanInstance=getInstantiationStrategy().instantiate(mbd,beanName,this);
BeanWrapperbw=newBeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
returnbw;
}
catch(Throwableex){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,ex.getMessage(),ex);
}
}
@Override
publicObjectinstantiate(RootBeanDefinitionbd,@NullableStringbeanName,BeanFactoryowner){
//Don'toverridetheclasswithCGLIBifnooverrides.
if(!bd.hasMethodOverrides()){
ConstructorconstructorToUse;
synchronized(bd.constructorArgumentLock){
constructorToUse=(Constructor)bd.resolvedConstructorOrFactoryMethod;
if(constructorToUse==null){
finalClassclazz=bd.getBeanClass();
if(clazz.isInterface()){
thrownewBeanInstantiationException(clazz,"Specifiedclassisaninterface");
}
try{
constructorToUse=clazz.getDeclaredConstructor();
bd.resolvedConstructorOrFactoryMethod=constructorToUse;
}
catch(Throwableex){
thrownewBeanInstantiationException(clazz,"Nodefaultconstructorfound",ex);
}
}
}
returnBeanUtils.instantiateClass(constructorToUse);
}
else{
//MustgenerateCGLIBsubclass.
returninstantiateWithMethodInjection(bd,beanName,owner);
}
}

從上面小伙伴么可以看到,本質(zhì)上其實(shí)就是調(diào)用了 constructorToUse = clazz.getDeclaredConstructor();,獲取到一個(gè)公開(kāi)的無(wú)參構(gòu)造方法,然后據(jù)此創(chuàng)建一個(gè) Bean 實(shí)例出來(lái)。

3. 小結(jié)

好了,這就是 Spring 容器中 Bean 的創(chuàng)建過(guò)程,我這里單純和小伙伴們分享了原始 Bean 的創(chuàng)建這一個(gè)步驟,這塊內(nèi)容其實(shí)非常龐雜,以后有空我會(huì)再和小伙伴們分享。

最后,給上面分析的方法生成了一個(gè)時(shí)序圖,小伙伴們作為參考。

8ddfb090-31ee-11ee-9e74-dac502259ad0.png

其實(shí)看 Spring 源碼,松哥最大的感悟就是小伙伴們一定要了解 Spring 的各種用法,在此基礎(chǔ)之上,源碼就很好懂,如果你只會(huì) Spring 一些基本用法,那么源碼一定是看得云里霧里的。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19286

    瀏覽量

    229868
  • XML技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    15

    瀏覽量

    6011
  • Beacon技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    6

    瀏覽量

    6257
  • spring框架
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

    2047

原文標(biāo)題:Spring容器原始Bean是如何創(chuàng)建的?

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    java spring教程

    Spring核心概念介紹控制反轉(zhuǎn)(IOC)依賴注入(DI)集合對(duì)象注入等Bean的管理BeanFactoryApplicationContextSpring 在web中的使用
    發(fā)表于 09-11 11:09

    什么是java spring

    的配置和生命周期,在這個(gè)意義上它是一種容器,你可以配置你的每個(gè)bean如何被創(chuàng)建——基于一個(gè)可配置原型(prototype),你的bean可以創(chuàng)建
    發(fā)表于 09-11 11:16

    spring實(shí)例

    ;UTF-8"?><!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN""http://www.springframework.org
    發(fā)表于 09-11 11:22

    怎么閱讀Spring源碼

    封裝,很有可能在讀源碼的過(guò)程中掉到各種細(xì)節(jié)里出不來(lái),所以讀這種源碼要事無(wú)巨細(xì),理解原理即可。基本原理其實(shí)就是通過(guò)反射解析類及其類的各種信息,包括構(gòu)造器、方法及其參數(shù),屬性。然后將其封裝成bea
    發(fā)表于 05-04 15:21

    三大框架之Spring

    Spring:沒(méi)有出現(xiàn)Spring之前,各層之間的訪問(wèn),需要在調(diào)用層中創(chuàng)建被調(diào)用層的對(duì)象,使用該對(duì)象去調(diào)用相應(yīng)的方法,這樣層與層之間的耦合性(緊密度)就會(huì)加強(qiáng),日后在修改代碼的時(shí)候,會(huì)
    發(fā)表于 05-27 07:21

    Spring工作原理

    的依賴關(guān)系核心:bean工廠;在Spring中,bean工廠創(chuàng)建的各個(gè)實(shí)例稱作bean二.AOP(Aspect-Oriented Progr
    發(fā)表于 07-10 07:41

    Spring認(rèn)證」Spring Hello World 項(xiàng)目示例

    ()。該 API 加載 bean 配置文件,并最終基于提供的 API,負(fù)責(zé)創(chuàng)建和初始化所有對(duì)象,即配置文件中提到的 bean。第二步用于使用創(chuàng)建的上下文的getBean()
    發(fā)表于 08-17 13:49

    Spring Boot嵌入式Web容器原理是什么

    Spring Boot嵌入式Web容器原理Spring Boot的目標(biāo)是構(gòu)建“非常容易創(chuàng)建、獨(dú)立、產(chǎn)品級(jí)別的基于Spring的應(yīng)用”。這些應(yīng)
    發(fā)表于 12-16 07:57

    Spring應(yīng)用 1 springXML配置說(shuō)明

    Spring應(yīng)用 1 springXML配置說(shuō)明 隱式對(duì)Spring容器注冊(cè)Process ? context:annotation-config / 為了在spring開(kāi)發(fā)過(guò)程中,為
    發(fā)表于 01-13 12:20 ?389次閱讀

    解析加載及實(shí)例化Bean順序(零配置)

    的@AutoConfigureAfter注解,手動(dòng)的指定Bean的實(shí)例化順序。 了解Spring內(nèi)Bean的解析,加載和實(shí)例化順序機(jī)制有助于
    的頭像 發(fā)表于 08-04 16:08 ?1332次閱讀

    Spring認(rèn)證」Spring IoC 容器

    Spring 容器Spring 框架的核心容器創(chuàng)建對(duì)象,將它們連接到配置中,并管理它們從創(chuàng)建
    的頭像 發(fā)表于 06-28 13:27 ?765次閱讀
    「<b class='flag-5'>Spring</b>認(rèn)證」<b class='flag-5'>Spring</b> IoC <b class='flag-5'>容器</b>

    bean放入Spring容器中有哪些方式

    bean放入Spring容器中有哪些方式?
    的頭像 發(fā)表于 09-19 15:25 ?724次閱讀

    SpringBean的生命周期是怎樣的?

    1. 基礎(chǔ)知識(shí) 1.1 什么是 IoC ? 1.2 Bean 生命周期 1.3 執(zhí)行流程 1.4 擴(kuò)展方法 2. 源碼解讀 2.1 代碼入口 2.2 實(shí)例化 2.3 屬性賦值 2.4
    的頭像 發(fā)表于 10-11 15:08 ?1392次閱讀

    淺談Spring事務(wù)底層原理

    開(kāi)啟Spring事務(wù)本質(zhì)上就是增加了一個(gè)Advisor,但我們使用@EnableTransactionManagement注解來(lái)開(kāi)啟Spring事務(wù)是,該注解代理的功能就是向Spring容器
    的頭像 發(fā)表于 12-06 09:56 ?697次閱讀

    Spring Dependency Inject與Bean Scops注解

    DependsOn`注解可以配置Spring IoC容器在初始化一個(gè)Bean之前,先初始化其他的Bean對(duì)象。下面是此注解使用示例代碼:
    的頭像 發(fā)表于 04-07 11:35 ?696次閱讀
    <b class='flag-5'>Spring</b> Dependency Inject與<b class='flag-5'>Bean</b> Scops注解