spring官网在线学习文档翻译六爻呈乾

Ifyouwanttoconfigureabeandefinitionforastaticnestedclass,youhavetousethebinarynameofthenestedclass.

TheSpringteamgenerallyadvocatesconstructorinjectionasitenablesonetoimplementapplicationcomponentsasimmutableobjectsandtoensurethatrequireddependenciesarenotnull.Furthermoreconstructor-injectedcomponentsarealwaysreturnedtoclient(calling)codeinafullyinitializedstate.Asasidenote,alargenumberofconstructorargumentsisabadcodesmell,implyingthattheclasslikelyhastoomanyresponsibilitiesandshouldberefactoredtobetteraddressproperseparationofconcerns.

UsetheDIstylethatmakesthemostsenseforaparticularclass.Sometimes,whendealingwiththird-partyclassesforwhichyoudonothavethesource,thechoiceismadeforyou.Forexample,ifathird-partyclassdoesnotexposeanysettermethods,thenconstructorinjectionmaybetheonlyavailableformofDI.

Circulardependencies

Ifyouusepredominantlyconstructorinjection,itispossibletocreateanunresolvablecirculardependencyscenario.

Forexample:ClassArequiresaninstanceofclassBthroughconstructorinjection,andclassBrequiresaninstanceofclassAthroughconstructorinjection.IfyouconfigurebeansforclassesAandBtobeinjectedintoeachother,theSpringIoCcontainerdetectsthiscircularreferenceatruntime,andthrowsaBeanCurrentlyInCreationException.

Onepossiblesolutionistoeditthesourcecodeofsomeclassestobeconfiguredbysettersratherthanconstructors.Alternatively,avoidconstructorinjectionandusesetterinjectiononly.Inotherwords,althoughitisnotrecommended,youcanconfigurecirculardependencieswithsetterinjection.

Unlikethetypicalcase(withnocirculardependencies),acirculardependencybetweenbeanAandbeanBforcesoneofthebeanstobeinjectedintotheotherpriortobeingfullyinitializeditself(aclassicchicken/eggscenario).

Youcancontrolnotonlythevariousdependenciesandconfigurationvaluesthataretobepluggedintoanobjectthatiscreatedfromaparticularbeandefinition,butalsothescopeoftheobjectscreatedfromaparticularbeandefinition.ThisapproachispowerfulandflexibleinthatyoucanchoosethescopeoftheobjectsyoucreatethroughconfigurationinsteadofhavingtobakeinthescopeofanobjectattheJavaclasslevel.Beanscanbedefinedtobedeployedinoneofanumberofscopes:outofthebox,theSpringFrameworksupportssixscopes,fourofwhichareavailableonlyifyouuseaweb-awareApplicationContext.

Onlyonesharedinstanceofasingletonbeanismanaged,andallrequestsforbeanswithanidoridsmatchingthatbeandefinitionresultinthatonespecificbeaninstancebeingreturnedbytheSpringcontainer.(只管理单例bean的一个共享实例,并且所有对id或id与该bean定义匹配的bean的请求都会导致Spring容器返回一个特定的bean实例。)

Toputitanotherway,whenyoudefineabeandefinitionanditisscopedasasingleton,theSpringIoCcontainercreatesexactlyoneinstanceoftheobjectdefinedbythatbeandefinition.Thissingleinstanceisstoredinacacheofsuchsingletonbeans,andallsubsequentrequestsandreferencesforthatnamedbeanreturnthecachedobject.

Spring’sconceptofasingletonbeandiffersfromtheSingletonpatternasdefinedintheGangofFour(GoF)patternsbook.TheGoFSingletonhard-codesthescopeofanobjectsuchthatoneandonlyoneinstanceofaparticularclassiscreatedperClassLoader.ThescopeoftheSpringsingletonisbestdescribedaspercontainerandperbean.ThismeansthatifyoudefineonebeanforaparticularclassinasingleSpringcontainer,thentheSpringcontainercreatesoneandonlyoneinstanceoftheclassdefinedbythatbeandefinition.ThesingletonscopeisthedefaultscopeinSpring.TodefineabeanasasingletoninXML,youwouldwrite,forexample:

1.5.2.Theprototypescope(原型范围)Thenon-singleton,prototypescopeofbeandeploymentresultsinthecreationofanewbeaninstanceeverytimearequestforthatspecificbeanismade.Thatis,thebeanisinjectedintoanotherbeanoryourequestitthroughagetBean()methodcallonthecontainer.Asarule,usetheprototypescopeforallstatefulbeansandthesingletonscopeforstatelessbeans.

ThefollowingdiagramillustratestheSpringprototypescope.Adataaccessobject(DAO)isnottypicallyconfiguredasaprototype,becauseatypicalDAOdoesnotholdanyconversationalstate;itwasjusteasierforthisauthortoreusethecoreofthesingletondiagram.

ThefollowingexampledefinesabeanasaprototypeinXML:

Whenyouusesingleton-scopedbeanswithdependenciesonprototypebeans,beawarethatdependenciesareresolvedatinstantiationtime.Thusifyoudependency-injectaprototype-scopedbeanintoasingleton-scopedbean,anewprototypebeanisinstantiatedandthendependency-injectedintothesingletonbean.Theprototypeinstanceisthesoleinstancethatiseversuppliedtothesingleton-scopedbean.

Therequest,session,application,andwebsocketscopesareonlyavailableifyouuseaweb-awareSpringApplicationContextimplementation(suchasXmlWebApplicationContext).IfyouusethesescopeswithregularSpringIoCcontainerssuchastheClassPathXmlApplicationContext,anIllegalStateExceptionwillbethrowncomplainingaboutanunknownbeanscope.

Tosupportthescopingofbeansattherequest,session,application,andwebsocketlevels(web-scopedbeans),someminorinitialconfigurationisrequiredbeforeyoudefineyourbeans.(Thisinitialsetupisnotrequiredforthestandardscopes,singletonandprototype.)

HowyouaccomplishthisinitialsetupdependsonyourparticularServletenvironment.

IfyouaccessscopedbeanswithinSpringWebMVC,ineffect,withinarequestthatisprocessedbytheSpringDispatcherServlet,thennospecialsetupisnecessary:DispatcherServletalreadyexposesallrelevantstate.

IfyouuseaServlet2.5webcontainer,withrequestsprocessedoutsideofSpring’sDispatcherServlet(forexample,whenusingJSForStruts),youneedtoregistertheorg.springframework.web.context.request.RequestContextListenerServletRequestListener.ForServlet3.0+,thiscanbedoneprogrammaticallyviatheWebApplicationInitializerinterface.Alternatively,orforoldercontainers,addthefollowingdeclarationtoyourwebapplication’sweb.xmlfile:

...org.springframework.web.context.request.RequestContextListener...Alternatively,ifthereareissueswithyourlistenersetup,considerusingSpring’sRequestContextFilter.Thefiltermappingdependsonthesurroundingwebapplicationconfiguration,soyouhavetochangeitasappropriate.

...requestContextFilterorg.springframework.web.filter.RequestContextFilterrequestContextFilter/*...DispatcherServlet,RequestContextListener,andRequestContextFilteralldoexactlythesamething,namelybindtheHTTPrequestobjecttotheThreadthatisservicingthatrequest.Thismakesbeansthatarerequest-andsession-scopedavailablefurtherdownthecallchain.

ConsiderthefollowingXMLconfigurationforabeandefinition:

TheSpringcontainercreatesanewinstanceoftheLoginActionbeanbyusingtheloginActionbeandefinitionforeachandeveryHTTPrequest.Thatis,theloginActionbeanisscopedattheHTTPrequestlevel.Youcanchangetheinternalstateoftheinstancethatiscreatedasmuchasyouwant,becauseotherinstancescreatedfromthesameloginActionbeandefinitionwillnotseethesechangesinstate;theyareparticulartoanindividualrequest.Whentherequestcompletesprocessing,thebeanthatisscopedtotherequestisdiscarded.

Whenusingannotation-drivencomponentsorJavaConfig,the@RequestScopeannotationcanbeusedtoassignacomponenttotherequestscope.

@RequestScope@ComponentpublicclassLoginAction{//...}SessionscopeConsiderthefollowingXMLconfigurationforabeandefinition:

TheSpringcontainercreatesanewinstanceoftheUserPreferencesbeanbyusingtheuserPreferencesbeandefinitionforthelifetimeofasingleHTTPSession.Inotherwords,theuserPreferencesbeaniseffectivelyscopedattheHTTPSessionlevel.Aswithrequest-scopedbeans,youcanchangetheinternalstateoftheinstancethatiscreatedasmuchasyouwant,knowingthatotherHTTPSessioninstancesthatarealsousinginstancescreatedfromthesameuserPreferencesbeandefinitiondonotseethesechangesinstate,becausetheyareparticulartoanindividualHTTPSession.WhentheHTTPSessioniseventuallydiscarded,thebeanthatisscopedtothatparticularHTTPSessionisalsodiscarded.

Whenusingannotation-drivencomponentsorJavaConfig,the@SessionScopeannotationcanbeusedtoassignacomponenttothesessionscope.

@SessionScope@ComponentpublicclassUserPreferences{//...}ApplicationscopeConsiderthefollowingXMLconfigurationforabeandefinition:

TheSpringcontainercreatesanewinstanceoftheAppPreferencesbeanbyusingtheappPreferencesbeandefinitiononcefortheentirewebapplication.Thatis,theappPreferencesbeanisscopedattheServletContextlevel,storedasaregularServletContextattribute.ThisissomewhatsimilartoaSpringsingletonbeanbutdiffersintwoimportantways:ItisasingletonperServletContext,notperSpring'ApplicationContext'(forwhichtheremaybeseveralinanygivenwebapplication),anditisactuallyexposedandthereforevisibleasaServletContextattribute.

Whenusingannotation-drivencomponentsorJavaConfig,the@ApplicationScopeannotationcanbeusedtoassignacomponenttotheapplicationscope.

@ApplicationScope@ComponentpublicclassAppPreferences{//...}Scopedbeansasdependencies(将限定范围的bean作为依赖项)TheSpringIoCcontainermanagesnotonlytheinstantiationofyourobjects(beans),butalsothewiringupofcollaborators(ordependencies).Ifyouwanttoinject(forexample)anHTTPrequestscopedbeanintoanotherbeanofalonger-livedscope,youmaychoosetoinjectanAOPproxyinplaceofthescopedbean.Thatis,youneedtoinjectaproxyobjectthatexposesthesamepublicinterfaceasthescopedobjectbutthatcanalsoretrievetherealtargetobjectfromtherelevantscope(suchasanHTTPrequest)anddelegatemethodcallsontotherealobject.

Theconfigurationinthefollowingexampleisonlyoneline,butitisimportanttounderstandthe"why"aswellasthe"how"behindit.

Intheprecedingexample,thesingletonbeanuserManagerisinjectedwithareferencetotheHTTPSession-scopedbeanuserPreferences.ThesalientpointhereisthattheuserManagerbeanisasingleton:itwillbeinstantiatedexactlyoncepercontainer,anditsdependencies(inthiscaseonlyone,theuserPreferencesbean)arealsoinjectedonlyonce.ThismeansthattheuserManagerbeanwillonlyoperateontheexactsameuserPreferencesobject,thatis,theonethatitwasoriginallyinjectedwith.

Thisisnotthebehavioryouwantwheninjectingashorter-livedscopedbeanintoalonger-livedscopedbean,forexampleinjectinganHTTPSession-scopedcollaboratingbeanasadependencyintosingletonbean.Rather,youneedasingleuserManagerobject,andforthelifetimeofanHTTPSession,youneedauserPreferencesobjectthatisspecifictosaidHTTPSession.ThusthecontainercreatesanobjectthatexposestheexactsamepublicinterfaceastheUserPreferencesclass(ideallyanobjectthatisaUserPreferencesinstance)whichcanfetchtherealUserPreferencesobjectfromthescopingmechanism(HTTPrequest,Session,etc.).ThecontainerinjectsthisproxyobjectintotheuserManagerbean,whichisunawarethatthisUserPreferencesreferenceisaproxy.Inthisexample,whenaUserManagerinstanceinvokesamethodonthedependency-injectedUserPreferencesobject,itactuallyisinvokingamethodontheproxy.TheproxythenfetchestherealUserPreferencesobjectfrom(inthiscase)theHTTPSession,anddelegatesthemethodinvocationontotheretrievedrealUserPreferencesobject.

Thusyouneedthefollowing,correctandcomplete,configurationwheninjectingrequest-andsession-scopedbeansintocollaboratingobjects:

Choosingthetypeofproxytocreate(选择要创建的代理类型)Bydefault,whentheSpringcontainercreatesaproxyforabeanthatismarkedupwiththeelement,aCGLIB-basedclassproxyiscreated.

Alternatively,youcanconfiguretheSpringcontainertocreatestandardJDKinterface-basedproxiesforsuchscopedbeans,byspecifyingfalseforthevalueoftheproxy-target-classattributeoftheelement.UsingJDKinterface-basedproxiesmeansthatyoudonotneedadditionallibrariesinyourapplicationclasspathtoeffectsuchproxying.However,italsomeansthattheclassofthescopedbeanmustimplementatleastoneinterface,andthatallcollaboratorsintowhichthescopedbeanisinjectedmustreferencethebeanthroughoneofitsinterfaces.

Thebeanscopingmechanismisextensible;Youcandefineyourownscopes,orevenredefineexistingscopes,althoughthelatterisconsideredbadpracticeandyoucannotoverridethebuilt-insingletonandprototypescopes.

TheScopeinterfacehasfourmethodstogetobjectsfromthescope,removethemfromthescope,andallowthemtobedestroyed.

Thefollowingmethodreturnstheobjectfromtheunderlyingscope.Thesessionscopeimplementation,forexample,returnsthesession-scopedbean(andifitdoesnotexist,themethodreturnsanewinstanceofthebean,afterhavingboundittothesessionforfuturereference).

Objectget(Stringname,ObjectFactoryobjectFactory)Thefollowingmethodremovestheobjectfromtheunderlyingscope.Thesessionscopeimplementationforexample,removesthesession-scopedbeanfromtheunderlyingsession.Theobjectshouldbereturned,butyoucanreturnnulliftheobjectwiththespecifiednameisnotfound.

Objectremove(Stringname)Thefollowingmethodregistersthecallbacksthescopeshouldexecutewhenitisdestroyedorwhenthespecifiedobjectinthescopeisdestroyed.RefertothejavadocsoraSpringscopeimplementationformoreinformationondestructioncallbacks.

voidregisterDestructionCallback(Stringname,RunnabledestructionCallback)Thefollowingmethodobtainstheconversationidentifierfortheunderlyingscope.Thisidentifierisdifferentforeachscope.Forasessionscopedimplementation,thisidentifiercanbethesessionidentifier.

StringgetConversationId()Usingacustomscope(使用自定义范围)AfteryouwriteandtestoneormorecustomScopeimplementations,youneedtomaketheSpringcontainerawareofyournewscope(s).ThefollowingmethodisthecentralmethodtoregisteranewScopewiththeSpringcontainer:

voidregisterScope(StringscopeName,Scopescope);ThismethodisdeclaredontheConfigurableBeanFactoryinterface,whichisavailableonmostoftheconcreteApplicationContextimplementationsthatshipwithSpringviatheBeanFactoryproperty.

ThefirstargumenttotheregisterScope(..)methodistheuniquenameassociatedwithascope;examplesofsuchnamesintheSpringcontaineritselfaresingletonandprototype.ThesecondargumenttotheregisterScope(..)methodisanactualinstanceofthecustomScopeimplementationthatyouwishtoregisteranduse.

SupposethatyouwriteyourcustomScopeimplementation,andthenregisteritasbelow.

ScopethreadScope=newSimpleThreadScope();beanFactory.registerScope("thread",threadScope);YouthencreatebeandefinitionsthatadheretothescopingrulesofyourcustomScope:

WithacustomScopeimplementation,youarenotlimitedtoprogrammaticregistrationofthescope.YoucanalsodotheScoperegistrationdeclaratively,usingtheCustomScopeConfigurerclass:

Inadditiontotheinitializationanddestructioncallbacks,Spring-managedobjectsmayalsoimplementtheLifecycleinterfacesothatthoseobjectscanparticipateinthestartupandshutdownprocessasdrivenbythecontainer’sownlifecycle.

-除了初始化和销毁回调之外,spring管理的对象还可以实现生命周期接口,以便这些对象可以参与由容器自己的生命周期驱动的启动和关闭过程。

Thelifecyclecallbackinterfacesaredescribedinthissection.

Theorg.springframework.beans.factory.InitializingBeaninterfaceallowsabeantoperforminitializationworkafterallnecessarypropertiesonthebeanhavebeensetbythecontainer.TheInitializingBeaninterfacespecifiesasinglemethod:

publicclassExampleBean{publicvoidinit(){//dosomeinitializationwork}}…isexactlythesameas…(和…完全一样。)

publicclassAnotherExampleBeanimplementsInitializingBean{publicvoidafterPropertiesSet(){//dosomeinitializationwork}}butdoesnotcouplethecodetoSpring.(但是没有将代码与Spring耦合。)

Implementingtheorg.springframework.beans.factory.DisposableBeaninterfaceallowsabeantogetacallbackwhenthecontainercontainingitisdestroyed.TheDisposableBeaninterfacespecifiesasinglemethod:

publicclassExampleBean{publicvoidcleanup(){//dosomedestructionwork(likereleasingpooledconnections)}}isexactlythesameas:(就等于:)

publicclassAnotherExampleBeanimplementsDisposableBean{publicvoiddestroy(){//dosomedestructionwork(likereleasingpooledconnections)}}butdoesnotcouplethecodetoSpring.(但是没有将代码与Spring耦合。)

WhenyouwriteinitializationanddestroymethodcallbacksthatdonotusetheSpring-specificInitializingBeanandDisposableBeancallbackinterfaces,youtypicallywritemethodswithnamessuchasinit(),initialize(),dispose(),andsoon.Ideally,thenamesofsuchlifecyclecallbackmethodsarestandardizedacrossaprojectsothatalldevelopersusethesamemethodnamesandensureconsistency.

YoucanconfiguretheSpringcontainertolookfornamedinitializationanddestroycallbackmethodnamesoneverybean.Thismeansthatyou,asanapplicationdeveloper,canwriteyourapplicationclassesanduseaninitializationcallbackcalledinit(),withouthavingtoconfigureaninit-method="init"attributewitheachbeandefinition.TheSpringIoCcontainercallsthatmethodwhenthebeaniscreated(andinaccordancewiththestandardlifecyclecallbackcontractdescribedpreviously).Thisfeaturealsoenforcesaconsistentnamingconventionforinitializationanddestroymethodcallbacks.

Supposethatyourinitializationcallbackmethodsarenamedinit()anddestroycallbackmethodsarenameddestroy().Yourclasswillresembletheclassinthefollowingexample.

publicclassDefaultBlogServiceimplementsBlogService{privateBlogDaoblogDao;publicvoidsetBlogDao(BlogDaoblogDao){this.blogDao=blogDao;}//thisis(unsurprisingly)theinitializationcallbackmethodpublicvoidinit(){if(this.blogDao==null){thrownewIllegalStateException("The[blogDao]propertymustbeset.");}}}Thepresenceofthedefault-init-methodattributeonthetop-levelelementattributecausestheSpringIoCcontainertorecognizeamethodcalledinitonbeansastheinitializationmethodcallback.Whenabeaniscreatedandassembled,ifthebeanclasshassuchamethod,itisinvokedattheappropriatetime.

Youconfiguredestroymethodcallbackssimilarly(inXML,thatis)byusingthedefault-destroy-methodattributeonthetop-levelelement.

Whereexistingbeanclassesalreadyhavecallbackmethodsthatarenamedatvariancewiththeconvention,youcanoverridethedefaultbyspecifying(inXML,thatis)themethodnameusingtheinit-methodanddestroy-methodattributesoftheitself.

TheSpringcontainerguaranteesthataconfiguredinitializationcallbackiscalledimmediatelyafterabeanissuppliedwithalldependencies.Thustheinitializationcallbackiscalledontherawbeanreference,whichmeansthatAOPinterceptorsandsofortharenotyetappliedtothebean.Atargetbeanisfullycreatedfirst,thenanAOPproxy(forexample)withitsinterceptorchainisapplied.Ifthetargetbeanandtheproxyaredefinedseparately,yourcodecaneveninteractwiththerawtargetbean,bypassingtheproxy.Hence,itwouldbeinconsistenttoapplytheinterceptorstotheinitmethod,becausedoingsowouldcouplethelifecycleofthetargetbeanwithitsproxy/interceptorsandleavestrangesemanticswhenyourcodeinteractsdirectlytotherawtargetbean.

Multiplelifecyclemechanismsconfiguredforthesamebean,withdifferentinitializationmethods,arecalledasfollows:

Destroymethodsarecalledinthesameorder:

TheLifecycleinterfacedefinestheessentialmethodsforanyobjectthathasitsownlifecyclerequirements(e.g.startsandstopssomebackgroundprocess):

publicinterfaceLifecycle{voidstart();voidstop();booleanisRunning();}AnySpring-managedobjectmayimplementthatinterface.Then,whentheApplicationContextitselfreceivesstartandstopsignals,e.g.forastop/restartscenarioatruntime,itwillcascadethosecallstoallLifecycleimplementationsdefinedwithinthatcontext.ItdoesthisbydelegatingtoaLifecycleProcessor:

publicinterfaceLifecycleProcessorextendsLifecycle{voidonRefresh();voidonClose();}NoticethattheLifecycleProcessorisitselfanextensionoftheLifecycleinterface.Italsoaddstwoothermethodsforreactingtothecontextbeingrefreshedandclosed.

Theorderofstartupandshutdowninvocationscanbeimportant.Ifa"depends-on"relationshipexistsbetweenanytwoobjects,thedependentsidewillstartafteritsdependency,anditwillstopbeforeitsdependency.However,attimesthedirectdependenciesareunknown.Youmayonlyknowthatobjectsofacertaintypeshouldstartpriortoobjectsofanothertype.Inthosecases,theSmartLifecycleinterfacedefinesanotheroption,namelythegetPhase()methodasdefinedonitssuper-interface,Phased.

publicinterfacePhased{intgetPhase();}publicinterfaceSmartLifecycleextendsLifecycle,Phased{booleanisAutoStartup();voidstop(Runnablecallback);}Whenstarting,theobjectswiththelowestphasestartfirst,andwhenstopping,thereverseorderisfollowed.Therefore,anobjectthatimplementsSmartLifecycleandwhosegetPhase()methodreturnsInteger.MIN_VALUEwouldbeamongthefirsttostartandthelasttostop.Attheotherendofthespectrum,aphasevalueofInteger.MAX_VALUEwouldindicatethattheobjectshouldbestartedlastandstoppedfirst(likelybecauseitdependsonotherprocessestoberunning).Whenconsideringthephasevalue,it’salsoimportanttoknowthatthedefaultphaseforany"normal"LifecycleobjectthatdoesnotimplementSmartLifecyclewouldbe0.Therefore,anynegativephasevaluewouldindicatethatanobjectshouldstartbeforethosestandardcomponents(andstopafterthem),andviceversaforanypositivephasevalue.

AsyoucanseethestopmethoddefinedbySmartLifecycleacceptsacallback.Anyimplementationmustinvokethatcallback’srun()methodafterthatimplementation’sshutdownprocessiscomplete.ThatenablesasynchronousshutdownwherenecessarysincethedefaultimplementationoftheLifecycleProcessorinterface,DefaultLifecycleProcessor,willwaituptoitstimeoutvalueforthegroupofobjectswithineachphasetoinvokethatcallback.Thedefaultper-phasetimeoutis30seconds.Youcanoverridethedefaultlifecycleprocessorinstancebydefiningabeannamed"lifecycleProcessor"withinthecontext.Ifyouonlywanttomodifythetimeout,thendefiningthefollowingwouldbesufficient:

IfyouareusingSpring’sIoCcontainerinanon-webapplicationenvironment;forexample,inarichclientdesktopenvironment;youregisterashutdownhookwiththeJVM.Doingsoensuresagracefulshutdownandcallstherelevantdestroymethodsonyoursingletonbeanssothatallresourcesarereleased.Ofcourse,youmuststillconfigureandimplementthesedestroycallbackscorrectly.

Toregisterashutdownhook,youcalltheregisterShutdownHook()methodthatisdeclaredontheConfigurableApplicationContextinterface:

importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicfinalclassBoot{publicstaticvoidmain(finalString[]args)throwsException{ConfigurableApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");//addashutdownhookfortheabovecontext...ctx.registerShutdownHook();//apprunshere...//mainmethodexits,hookiscalledpriortotheappshuttingdown...}}1.6.2.ApplicationContextAwareandBeanNameAwareWhenanApplicationContextcreatesanobjectinstancethatimplementstheorg.springframework.context.ApplicationContextAwareinterface,theinstanceisprovidedwithareferencetothatApplicationContext.

WhenanApplicationContextcreatesaclassthatimplementstheorg.springframework.beans.factory.BeanNameAwareinterface,theclassisprovidedwithareferencetothenamedefinedinitsassociatedobjectdefinition.

publicinterfaceBeanNameAware{voidsetBeanName(Stringname)throwsBeansException;}ThecallbackisinvokedafterpopulationofnormalbeanpropertiesbutbeforeaninitializationcallbacksuchasInitializingBeanafterPropertiesSetoracustominit-method.

BesidesApplicationContextAwareandBeanNameAwarediscussedabove,SpringoffersarangeofAwareinterfacesthatallowbeanstoindicatetothecontainerthattheyrequireacertaininfrastructuredependency.ThemostimportantAwareinterfacesaresummarizedbelow-asageneralrule,thenameisagoodindicationofthedependencytype:

NoteagainthatusageoftheseinterfacestiesyourcodetotheSpringAPIanddoesnotfollowtheInversionofControlstyle.Assuch,theyarerecommendedforinfrastructurebeansthatrequireprogrammaticaccesstothecontainer.

Abeandefinitioncancontainalotofconfigurationinformation,includingconstructorarguments,propertyvalues,andcontainer-specificinformationsuchasinitializationmethod,staticfactorymethodname,andsoon.Achildbeandefinitioninheritsconfigurationdatafromaparentdefinition.Thechilddefinitioncanoverridesomevalues,oraddothers,asneeded.Usingparentandchildbeandefinitionscansavealotoftyping.Effectively,thisisaformoftemplating.

IfyouworkwithanApplicationContextinterfaceprogrammatically,childbeandefinitionsarerepresentedbytheChildBeanDefinitionclass.Mostusersdonotworkwiththemonthislevel,insteadconfiguringbeandefinitionsdeclarativelyinsomethingliketheClassPathXmlApplicationContext.WhenyouuseXML-basedconfigurationmetadata,youindicateachildbeandefinitionbyusingtheparentattribute,specifyingtheparentbeanasthevalueofthisattribute.

Achildbeandefinitionusesthebeanclassfromtheparentdefinitionifnoneisspecified,butcanalsooverrideit.Inthelattercase,thechildbeanclassmustbecompatiblewiththeparent,thatis,itmustaccepttheparent’spropertyvalues.

Achildbeandefinitioninheritsscope,constructorargumentvalues,propertyvalues,andmethodoverridesfromtheparent,withtheoptiontoaddnewvalues.Anyscope,initializationmethod,destroymethod,and/orstaticfactorymethodsettingsthatyouspecifywilloverridethecorrespondingparentsettings.

Theremainingsettingsarealwaystakenfromthechilddefinition:dependson,autowiremode,dependencycheck,singleton,lazyinit.

Theprecedingexampleexplicitlymarkstheparentbeandefinitionasabstractbyusingtheabstractattribute.Iftheparentdefinitiondoesnotspecifyaclass,explicitlymarkingtheparentbeandefinitionasabstractisrequired,asfollows:

Theparentbeancannotbeinstantiatedonitsownbecauseitisincomplete,anditisalsoexplicitlymarkedasabstract.Whenadefinitionisabstractlikethis,itisusableonlyasapuretemplatebeandefinitionthatservesasaparentdefinitionforchilddefinitions.Tryingtousesuchanabstractparentbeanonitsown,byreferringtoitasarefpropertyofanotherbeanordoinganexplicitgetBean()callwiththeparentbeanid,returnsanerror.Similarly,thecontainer’sinternalpreInstantiateSingletons()methodignoresbeandefinitionsthataredefinedasabstract.

Typically,anapplicationdeveloperdoesnotneedtosubclassApplicationContextimplementationclasses.Instead,theSpringIoCcontainercanbeextendedbyplugginginimplementationsofspecialintegrationinterfaces.Thenextfewsectionsdescribetheseintegrationinterfaces.

TheBeanPostProcessorinterfacedefinescallbackmethodsthatyoucanimplementtoprovideyourown(oroverridethecontainer’sdefault)instantiationlogic,dependency-resolutionlogic,andsoforth.IfyouwanttoimplementsomecustomlogicaftertheSpringcontainerfinishesinstantiating,configuring,andinitializingabean,youcanpluginoneormoreBeanPostProcessorimplementations.

Theorg.springframework.beans.factory.config.BeanPostProcessorinterfaceconsistsofexactlytwocallbackmethods.Whensuchaclassisregisteredasapost-processorwiththecontainer,foreachbeaninstancethatiscreatedbythecontainer,thepost-processorgetsacallbackfromthecontainerbothbeforecontainerinitializationmethods(suchasInitializingBean’safterPropertiesSet()andanydeclaredinitmethod)arecalledaswellasafteranybeaninitializationcallbacks.Thepost-processorcantakeanyactionwiththebeaninstance,includingignoringthecallbackcompletely.Abeanpost-processortypicallychecksforcallbackinterfacesormaywrapabeanwithaproxy.SomeSpringAOPinfrastructureclassesareimplementedasbeanpost-processorsinordertoprovideproxy-wrappinglogic.

AnApplicationContextautomaticallydetectsanybeansthataredefinedintheconfigurationmetadatawhichimplementtheBeanPostProcessorinterface.TheApplicationContextregistersthesebeansaspost-processorssothattheycanbecalledlateruponbeancreation.Beanpost-processorscanbedeployedinthecontainerjustlikeanyotherbeans.

NotethatwhendeclaringaBeanPostProcessorusingan@Beanfactorymethodonaconfigurationclass,thereturntypeofthefactorymethodshouldbetheimplementationclassitselforatleasttheorg.springframework.beans.factory.config.BeanPostProcessorinterface,clearlyindicatingthepost-processornatureofthatbean.Otherwise,theApplicationContextwon’tbeabletoautodetectitbytypebeforefullycreatingit.SinceaBeanPostProcessorneedstobeinstantiatedearlyinordertoapplytotheinitializationofotherbeansinthecontext,thisearlytypedetectioniscritical.

Thefollowingexamplesshowhowtowrite,register,anduseBeanPostProcessorsinanApplicationContext.

Thisfirstexampleillustratesbasicusage.TheexampleshowsacustomBeanPostProcessorimplementationthatinvokesthetoString()methodofeachbeanasitiscreatedbythecontainerandprintstheresultingstringtothesystemconsole.

FindbelowthecustomBeanPostProcessorimplementationclassdefinition:

ThefollowingsimpleJavaapplicationexecutestheprecedingcodeandconfiguration:

importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;importorg.springframework.scripting.Messenger;publicfinalclassBoot{publicstaticvoidmain(finalString[]args)throwsException{ApplicationContextctx=newClassPathXmlApplicationContext("scripting/beans.xml");Messengermessenger=(Messenger)ctx.getBean("messenger");System.out.println(messenger);}}Theoutputoftheprecedingapplicationresemblesthefollowing:

Bean'messenger'created:org.springframework.scripting.groovy.GroovyMessenger@272961org.springframework.scripting.groovy.GroovyMessenger@272961Example:TheRequiredAnnotationBeanPostProcessor(例子:)UsingcallbackinterfacesorannotationsinconjunctionwithacustomBeanPostProcessorimplementationisacommonmeansofextendingtheSpringIoCcontainer.AnexampleisSpring’sRequiredAnnotationBeanPostProcessor-aBeanPostProcessorimplementationthatshipswiththeSpringdistributionwhichensuresthatJavaBeanpropertiesonbeansthataremarkedwithan(arbitrary)annotationareactually(configuredtobe)dependency-injectedwithavalue.

Thenextextensionpointthatwewilllookatistheorg.springframework.beans.factory.config.BeanFactoryPostProcessor.ThesemanticsofthisinterfacearesimilartothoseoftheBeanPostProcessor,withonemajordifference:BeanFactoryPostProcessoroperatesonthebeanconfigurationmetadata;thatis,theSpringIoCcontainerallowsaBeanFactoryPostProcessortoreadtheconfigurationmetadataandpotentiallychangeitbeforethecontainerinstantiatesanybeansotherthanBeanFactoryPostProcessors.

YoucanconfiguremultipleBeanFactoryPostProcessors,andyoucancontroltheorderinwhichtheseBeanFactoryPostProcessorsexecutebysettingtheorderproperty.However,youcanonlysetthispropertyiftheBeanFactoryPostProcessorimplementstheOrderedinterface.IfyouwriteyourownBeanFactoryPostProcessor,youshouldconsiderimplementingtheOrderedinterfacetoo.ConsultthejavadocsoftheBeanFactoryPostProcessorandOrderedinterfacesformoredetails.

Abeanfactorypost-processorisexecutedautomaticallywhenitisdeclaredinsideanApplicationContext,inordertoapplychangestotheconfigurationmetadatathatdefinethecontainer.Springincludesanumberofpredefinedbeanfactorypost-processors,suchasPropertyOverrideConfigurerandPropertyPlaceholderConfigurer.AcustomBeanFactoryPostProcessorcanalsobeused,forexample,toregistercustompropertyeditors.

AnApplicationContextautomaticallydetectsanybeansthataredeployedintoitthatimplementtheBeanFactoryPostProcessorinterface.Itusesthesebeansasbeanfactorypost-processors,attheappropriatetime.Youcandeploythesepost-processorbeansasyouwouldanyotherbean.

YouusethePropertyPlaceholderConfigurertoexternalizepropertyvaluesfromabeandefinitioninaseparatefileusingthestandardJavaPropertiesformat.Doingsoenablesthepersondeployinganapplicationtocustomizeenvironment-specificpropertiessuchasdatabaseURLsandpasswords,withoutthecomplexityorriskofmodifyingthemainXMLdefinitionfileorfilesforthecontainer.

ConsiderthefollowingXML-basedconfigurationmetadatafragment,whereaDataSourcewithplaceholdervaluesisdefined.TheexampleshowspropertiesconfiguredfromanexternalPropertiesfile.Atruntime,aPropertyPlaceholderConfigurerisappliedtothemetadatathatwillreplacesomepropertiesoftheDataSource.Thevaluestoreplacearespecifiedasplaceholdersoftheform${property-name}whichfollowstheAnt/log4j/JSPELstyle.

TheactualvaluescomefromanotherfileinthestandardJavaPropertiesformat:

jdbc.driverClassName=org.hsqldb.jdbcDriverjdbc.url=jdbc:hsqldb:hsql://production:9002jdbc.username=sajdbc.password=rootTherefore,thestring${jdbc.username}isreplacedatruntimewiththevalue'sa',andthesameappliesforotherplaceholdervaluesthatmatchkeysinthepropertiesfile.ThePropertyPlaceholderConfigurerchecksforplaceholdersinmostpropertiesandattributesofabeandefinition.Furthermore,theplaceholderprefixandsuffixcanbecustomized.

WiththecontextnamespaceintroducedinSpring2.5,itispossibletoconfigurepropertyplaceholderswithadedicatedconfigurationelement.Oneormorelocationscanbeprovidedasacomma-separatedlistinthelocationattribute.

ThePropertyPlaceholderConfigurernotonlylooksforpropertiesinthePropertiesfileyouspecify.BydefaultitalsochecksagainsttheJavaSystempropertiesifitcannotfindapropertyinthespecifiedpropertiesfiles.YoucancustomizethisbehaviorbysettingthesystemPropertiesModepropertyoftheconfigurerwithoneofthefollowingthreesupportedintegervalues:

ConsultthePropertyPlaceholderConfigurerjavadocsformoreinformation.

ThePropertyOverrideConfigurer,anotherbeanfactorypost-processor,resemblesthePropertyPlaceholderConfigurer,butunlikethelatter,theoriginaldefinitionscanhavedefaultvaluesornovaluesatallforbeanproperties.IfanoverridingPropertiesfiledoesnothaveanentryforacertainbeanproperty,thedefaultcontextdefinitionisused.

Notethatthebeandefinitionisnotawareofbeingoverridden,soitisnotimmediatelyobviousfromtheXMLdefinitionfilethattheoverrideconfigurerisbeingused.IncaseofmultiplePropertyOverrideConfigurerinstancesthatdefinedifferentvaluesforthesamebeanproperty,thelastonewins,duetotheoverridingmechanism.

Propertiesfileconfigurationlinestakethisformat:

beanName.property=valueForexample:

dataSource.driverClassName=com.mysql.jdbc.DriverdataSource.url=jdbc:mysql:mydbThisexamplefilecanbeusedwithacontainerdefinitionthatcontainsabeancalleddataSource,whichhasdriverandurlproperties.

Compoundpropertynamesarealsosupported,aslongaseverycomponentofthepathexceptthefinalpropertybeingoverriddenisalreadynon-null(presumablyinitializedbytheconstructors).Inthisexample…

foo.fred.bob.sammy=123Specifiedoverridevaluesarealwaysliteralvalues;theyarenottranslatedintobeanreferences.ThisconventionalsoapplieswhentheoriginalvalueintheXMLbeandefinitionspecifiesabeanreference.WiththecontextnamespaceintroducedinSpring2.5,itispossibletoconfigurepropertyoverridingwithadedicatedconfigurationelement:

1.8.3.CustomizinginstantiationlogicwithaFactoryBean(使用FactoryBean自定义实例化逻辑)Implementtheorg.springframework.beans.factory.FactoryBeaninterfaceforobjectsthatarethemselvesfactories.

TheFactoryBeaninterfaceisapointofpluggabilityintotheSpringIoCcontainer’sinstantiationlogic.IfyouhavecomplexinitializationcodethatisbetterexpressedinJavaasopposedtoa(potentially)verboseamountofXML,youcancreateyourownFactoryBean,writethecomplexinitializationinsidethatclass,andthenplugyourcustomFactoryBeanintothecontainer.

TheFactoryBeaninterfaceprovidesthreemethods:

TheFactoryBeanconceptandinterfaceisusedinanumberofplaceswithintheSpringFramework;morethan50implementationsoftheFactoryBeaninterfaceshipwithSpringitself.

WhenyouneedtoaskacontainerforanactualFactoryBeaninstanceitselfinsteadofthebeanitproduces,prefacethebean’sidwiththeampersandsymbol(&)whencallingthegetBean()methodoftheApplicationContext.SoforagivenFactoryBeanwithanidofmyBean,invokinggetBean("myBean")onthecontainerreturnstheproductoftheFactoryBean;whereas,invokinggetBean("&myBean")returnstheFactoryBeaninstanceitself.

AreannotationsbetterthanXMLforconfiguringSpring

Theintroductionofannotation-basedconfigurationsraisedthequestionofwhetherthisapproachis'better'thanXML.Theshortanswerisitdepends.Thelongansweristhateachapproachhasitsprosandcons,andusuallyitisuptothedevelopertodecidewhichstrategysuitsthembetter.Duetothewaytheyaredefined,annotationsprovidealotofcontextintheirdeclaration,leadingtoshorterandmoreconciseconfiguration.However,XMLexcelsatwiringupcomponentswithouttouchingtheirsourcecodeorrecompilingthem.SomedeveloperspreferhavingthewiringclosetothesourcewhileothersarguethatannotatedclassesarenolongerPOJOsand,furthermore,thattheconfigurationbecomesdecentralizedandhardertocontrol.

Asalways,youcanregisterthemasindividualbeandefinitions,buttheycanalsobeimplicitlyregisteredbyincludingthefollowingtaginanXML-basedSpringconfiguration(noticetheinclusionofthecontextnamespace):

The@Requiredannotationappliestobeanpropertysettermethods,asinthefollowingexample:

publicclassSimpleMovieLister{privateMovieFindermovieFinder;@RequiredpublicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}//...}Thisannotationsimplyindicatesthattheaffectedbeanpropertymustbepopulatedatconfigurationtime,throughanexplicitpropertyvalueinabeandefinitionorthroughautowiring.Thecontainerthrowsanexceptioniftheaffectedbeanpropertyhasnotbeenpopulated;thisallowsforeagerandexplicitfailure,avoidingNullPointerExceptionsorthelikelateron.Itisstillrecommendedthatyouputassertionsintothebeanclassitself,forexample,intoaninitmethod.Doingsoenforcesthoserequiredreferencesandvaluesevenwhenyouusetheclassoutsideofacontainer.

Youcanapplythe@Autowiredannotationtoconstructors:

publicclassMovieRecommender{privatefinalCustomerPreferenceDaocustomerPreferenceDao;@AutowiredpublicMovieRecommender(CustomerPreferenceDaocustomerPreferenceDao){this.customerPreferenceDao=customerPreferenceDao;}//...}AsofSpringFramework4.3,an@Autowiredannotationonsuchaconstructorisnolongernecessaryifthetargetbeanonlydefinesoneconstructortobeginwith.However,ifseveralconstructorsareavailable,atleastonemustbeannotatedtoteachthecontainerwhichonetouse.Asexpected,youcanalsoapplythe@Autowiredannotationto"traditional"settermethods:

publicclassSimpleMovieLister{privateMovieFindermovieFinder;@AutowiredpublicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}//...}Youcanalsoapplytheannotationtomethodswitharbitrarynamesand/ormultiplearguments:

publicclassMovieRecommender{privateMovieCatalogmovieCatalog;privateCustomerPreferenceDaocustomerPreferenceDao;@Autowiredpublicvoidprepare(MovieCatalogmovieCatalog,CustomerPreferenceDaocustomerPreferenceDao){this.movieCatalog=movieCatalog;this.customerPreferenceDao=customerPreferenceDao;}//...}Youcanapply@Autowiredtofieldsaswellandevenmixitwithconstructors:

publicclassMovieRecommender{@AutowiredprivateMovieCatalog[]movieCatalogs;//...}Thesameappliesfortypedcollections:

publicclassMovieRecommender{privateMapmovieCatalogs;@AutowiredpublicvoidsetMovieCatalogs(MapmovieCatalogs){this.movieCatalogs=movieCatalogs;}//...}Bydefault,theautowiringfailswheneverzerocandidatebeansareavailable;thedefaultbehavioristotreatannotatedmethods,constructors,andfieldsasindicatingrequireddependencies.Thisbehaviorcanbechangedasdemonstratedbelow.

publicclassSimpleMovieLister{privateMovieFindermovieFinder;@Autowired(required=false)publicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}//...}Onlyoneannotatedconstructorper-classcanbemarkedasrequired,butmultiplenon-requiredconstructorscanbeannotated.Inthatcase,eachisconsideredamongthecandidatesandSpringusesthegreediestconstructorwhosedependenciescanbesatisfied,thatistheconstructorthathasthelargestnumberofarguments.Therequiredattributeof@Autowiredisrecommendedoverthe@Requiredannotation.Therequiredattributeindicatesthatthepropertyisnotrequiredforautowiringpurposes,thepropertyisignoredifitcannotbeautowired.@Required,ontheotherhand,isstrongerinthatitenforcesthepropertythatwassetbyanymeanssupportedbythecontainer.Ifnovalueisinjected,acorrespondingexceptionisraised.Alternatively,youmayexpressthenon-requirednatureofaparticulardependencythroughJava8’sjava.util.Optional:或者,你也可以通过Java8的Java.util.optional来表达某个特定依赖项的非必需性质:

publicclassSimpleMovieLister{@AutowiredpublicvoidsetMovieFinder(OptionalmovieFinder){...}}AsofSpringFramework5.0,youmayalsousean@Nullableannotation(ofanykindinanypackage,e.g.javax.annotation.NullablefromJSR-305):

publicclassSimpleMovieLister{@AutowiredpublicvoidsetMovieFinder(@NullableMovieFindermovieFinder){...}}Youcanalsouse@Autowiredforinterfacesthatarewell-knownresolvabledependencies:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,andMessageSource.Theseinterfacesandtheirextendedinterfaces,suchasConfigurableApplicationContextorResourcePatternResolver,areautomaticallyresolved,withnospecialsetupnecessary.

publicclassMovieRecommender{@AutowiredprivateApplicationContextcontext;publicMovieRecommender(){}//...}@Autowired,@Inject,@Resource,and@ValueannotationsarehandledbySpringBeanPostProcessorimplementationswhichinturnmeansthatyoucannotapplytheseannotationswithinyourownBeanPostProcessororBeanFactoryPostProcessortypes(ifany).Thesetypesmustbe'wiredup'explicitlyviaXMLorusingaSpring@Beanmethod.1.9.3.Fine-tuningannotation-basedautowiringwith@Primary(使用@Primary微调基于注释的自动装配)Becauseautowiringbytypemayleadtomultiplecandidates,itisoftennecessarytohavemorecontrolovertheselectionprocess.OnewaytoaccomplishthisiswithSpring’s@Primaryannotation.@Primaryindicatesthataparticularbeanshouldbegivenpreferencewhenmultiplebeansarecandidatestobeautowiredtoasingle-valueddependency.Ifexactlyone'primary'beanexistsamongthecandidates,itwillbetheautowiredvalue.

Let’sassumewehavethefollowingconfigurationthatdefinesfirstMovieCatalogastheprimaryMovieCatalog.

@ConfigurationpublicclassMovieConfiguration{@Bean@PrimarypublicMovieCatalogfirstMovieCatalog(){...}@BeanpublicMovieCatalogsecondMovieCatalog(){...}//...}Withsuchconfiguration,thefollowingMovieRecommenderwillbeautowiredwiththefirstMovieCatalog.

publicclassMovieRecommender{@AutowiredprivateMovieCatalogmovieCatalog;//...}Thecorrespondingbeandefinitionsappearasfollows.

publicclassMovieRecommender{@Autowired@Qualifier("main")privateMovieCatalogmovieCatalog;//...}The@Qualifierannotationcanalsobespecifiedonindividualconstructorargumentsormethodparameters:

publicclassMovieRecommender{privateMovieCatalogmovieCatalog;privateCustomerPreferenceDaocustomerPreferenceDao;@Autowiredpublicvoidprepare(@Qualifier("main")MovieCatalogmovieCatalog,CustomerPreferenceDaocustomerPreferenceDao){this.movieCatalog=movieCatalog;this.customerPreferenceDao=customerPreferenceDao;}//...}Thecorrespondingbeandefinitionsappearasfollows.Thebeanwithqualifiervalue"main"iswiredwiththeconstructorargumentthatisqualifiedwiththesamevalue.

Qualifiersalsoapplytotypedcollections,asdiscussedabove,forexample,toSet.Inthiscase,allmatchingbeansaccordingtothedeclaredqualifiersareinjectedasacollection.Thisimpliesthatqualifiersdonothavetobeunique;theyrathersimplyconstitutefilteringcriteria.Forexample,youcandefinemultipleMovieCatalogbeanswiththesamequalifiervalue"action",allofwhichwouldbeinjectedintoaSetannotatedwith@Qualifier("action").

Youcancreateyourowncustomqualifierannotations.Simplydefineanannotationandprovidethe@Qualifierannotationwithinyourdefinition:

@Target({ElementType.FIELD,ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic@interfaceGenre{Stringvalue();}Thenyoucanprovidethecustomqualifieronautowiredfieldsandparameters:

publicclassMovieRecommender{@Autowired@Genre("Action")privateMovieCatalogactionCatalog;privateMovieCatalogcomedyCatalog;@AutowiredpublicvoidsetComedyCatalog(@Genre("Comedy")MovieCatalogcomedyCatalog){this.comedyCatalog=comedyCatalog;}//...}Next,providetheinformationforthecandidatebeandefinitions.Youcanaddtagsassub-elementsofthetagandthenspecifythetypeandvaluetomatchyourcustomqualifierannotations.Thetypeismatchedagainstthefully-qualifiedclassnameoftheannotation.Or,asaconvenienceifnoriskofconflictingnamesexists,youcanusetheshortclassname.Bothapproachesaredemonstratedinthefollowingexample.

Insomecases,itmaybesufficienttouseanannotationwithoutavalue.Thismaybeusefulwhentheannotationservesamoregenericpurposeandcanbeappliedacrossseveraldifferenttypesofdependencies.Forexample,youmayprovideanofflinecatalogthatwouldbesearchedwhennoInternetconnectionisavailable.Firstdefinethesimpleannotation:

@Target({ElementType.FIELD,ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic@interfaceOffline{}Thenaddtheannotationtothefieldorpropertytobeautowired:

publicclassMovieRecommender{@Autowired@OfflineprivateMovieCatalogofflineCatalog;//...}Nowthebeandefinitiononlyneedsaqualifiertype:

Youcanalsodefinecustomqualifierannotationsthatacceptnamedattributesinadditiontoorinsteadofthesimplevalueattribute.Ifmultipleattributevaluesarethenspecifiedonafieldorparametertobeautowired,abeandefinitionmustmatchallsuchattributevaluestobeconsideredanautowirecandidate.Asanexample,considerthefollowingannotationdefinition:

@Target({ElementType.FIELD,ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic@interfaceMovieQualifier{Stringgenre();Formatformat();}InthiscaseFormatisanenum:

publicenumFormat{VHS,DVD,BLURAY}Thefieldstobeautowiredareannotatedwiththecustomqualifierandincludevaluesforbothattributes:genreandformat.

publicclassMovieRecommender{@Autowired@MovieQualifier(format=Format.VHS,genre="Action")privateMovieCatalogactionVhsCatalog;@Autowired@MovieQualifier(format=Format.VHS,genre="Comedy")privateMovieCatalogcomedyVhsCatalog;@Autowired@MovieQualifier(format=Format.DVD,genre="Action")privateMovieCatalogactionDvdCatalog;@Autowired@MovieQualifier(format=Format.BLURAY,genre="Comedy")privateMovieCatalogcomedyBluRayCatalog;//...}Finally,thebeandefinitionsshouldcontainmatchingqualifiervalues.Thisexamplealsodemonstratesthatbeanmetaattributesmaybeusedinsteadofthesub-elements.Ifavailable,theanditsattributestakeprecedence,buttheautowiringmechanismfallsbackonthevaluesprovidedwithinthetagsifnosuchqualifierispresent,asinthelasttwobeandefinitionsinthefollowingexample.

@ConfigurationpublicclassMyConfiguration{@BeanpublicStringStorestringStore(){returnnewStringStore();}@BeanpublicIntegerStoreintegerStore(){returnnewIntegerStore();}}Assumingthatbeansaboveimplementagenericinterface,i.e.StoreandStore,youcan@AutowiretheStoreinterfaceandthegenericwillbeusedasaqualifier:

@AutowiredprivateStores1;//qualifier,injectsthestringStorebean@AutowiredprivateStores2;//qualifier,injectstheintegerStorebeanGenericqualifiersalsoapplywhenautowiringLists,MapsandArrays:

example.CustomQualifierTheAutowireCandidateResolverdeterminesautowirecandidatesby:

Whenmultiplebeansqualifyasautowirecandidates,thedeterminationofa"primary"isthefollowing:ifexactlyonebeandefinitionamongthecandidateshasaprimaryattributesettotrue,itwillbeselected.

SpringalsosupportsinjectionusingtheJSR-250@Resourceannotationonfieldsorbeanpropertysettermethods.ThisisacommonpatterninJavaEE5and6,forexampleinJSF1.2managedbeansorJAX-WS2.0endpoints.SpringsupportsthispatternforSpring-managedobjectsaswell.

@Resourcetakesanameattribute,andbydefaultSpringinterpretsthatvalueasthebeannametobeinjected.Inotherwords,itfollowsby-namesemantics,asdemonstratedinthisexample:

publicclassSimpleMovieLister{privateMovieFindermovieFinder;@Resource(name="myMovieFinder")publicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}}Ifnonameisspecifiedexplicitly,thedefaultnameisderivedfromthefieldnameorsettermethod.Incaseofafield,ittakesthefieldname;incaseofasettermethod,ittakesthebeanpropertyname.Sothefollowingexampleisgoingtohavethebeanwithname"movieFinder"injectedintoitssettermethod:

Thusinthefollowingexample,thecustomerPreferenceDaofieldfirstlooksforabeannamedcustomerPreferenceDao,thenfallsbacktoaprimarytypematchforthetypeCustomerPreferenceDao.The"context"fieldisinjectedbasedontheknownresolvabledependencytypeApplicationContext.

Springprovidesfurtherstereotypeannotations:@Component,@Service,and@Controller.@ComponentisagenericstereotypeforanySpring-managedcomponent.@Repository,@Service,and@Controllerarespecializationsof@Componentformorespecificusecases,forexample,inthepersistence,service,andpresentationlayers,respectively.Therefore,youcanannotateyourcomponentclasseswith@Component,butbyannotatingthemwith@Repository,@Service,or@Controllerinstead,yourclassesaremoreproperlysuitedforprocessingbytoolsorassociatingwithaspects.Forexample,thesestereotypeannotationsmakeidealtargetsforpointcuts.Itisalsopossiblethat@Repository,@Service,and@ControllermaycarryadditionalsemanticsinfuturereleasesoftheSpringFramework.Thus,ifyouarechoosingbetweenusing@Componentor@Serviceforyourservicelayer,@Serviceisclearlythebetterchoice.Similarly,asstatedabove,@Repositoryisalreadysupportedasamarkerforautomaticexceptiontranslationinyourpersistencelayer.

ManyoftheannotationsprovidedbySpringcanbeusedasmeta-annotationsinyourowncode.Ameta-annotationissimplyanannotationthatcanbeappliedtoanotherannotation.Forexample,the@Serviceannotationmentionedaboveismeta-annotatedwith@Component:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Component//Springwillseethisandtreat@Serviceinthesamewayas@Componentpublic@interfaceService{//....}Meta-annotationscanalsobecombinedtocreatecomposedannotations.Forexample,the@RestControllerannotationfromSpringMVCiscomposedof@Controllerand@ResponseBody.

Inaddition,composedannotationsmayoptionallyredeclareattributesfrommeta-annotationstoallowusercustomization.Thiscanbeparticularlyusefulwhenyouwanttoonlyexposeasubsetofthemeta-annotation’sattributes.Forexample,Spring’s@SessionScopeannotationhardcodesthescopenametosessionbutstillallowscustomizationoftheproxyMode.

@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Scope(WebApplicationContext.SCOPE_SESSION)public@interfaceSessionScope{/***Aliasfor{@linkScope#proxyMode}.*

Defaultsto{@linkScopedProxyMode#TARGET_CLASS}.*/@AliasFor(annotation=Scope.class)ScopedProxyModeproxyMode()defaultScopedProxyMode.TARGET_CLASS;}@SessionScopecanthenbeusedwithoutdeclaringtheproxyModeasfollows:

@Service@SessionScopepublicclassSessionScopedService{//...}OrwithanoverriddenvaluefortheproxyModeasfollows:

SpringcanautomaticallydetectstereotypedclassesandregistercorrespondingBeanDefinitionswiththeApplicationContext.Forexample,thefollowingtwoclassesareeligibleforsuchautodetection:

@ServicepublicclassSimpleMovieLister{privateMovieFindermovieFinder;@AutowiredpublicSimpleMovieLister(MovieFindermovieFinder){this.movieFinder=movieFinder;}}@RepositorypublicclassJpaMovieFinderimplementsMovieFinder{//implementationelidedforclarity}Toautodetecttheseclassesandregisterthecorrespondingbeans,youneedtoadd@ComponentScantoyour@Configurationclass,wherethebasePackagesattributeisacommonparentpackageforthetwoclasses.(Alternatively,youcanspecifyacomma/semicolon/space-separatedlistthatincludestheparentpackageofeachclass.)

@Configuration@ComponentScan(basePackages="org.example")publicclassAppConfig{...}Forconcision,theabovemayhaveusedthevalueattributeoftheannotation,i.e.@ComponentScan("org.example")ThefollowingisanalternativeusingXML

Bydefault,classesannotatedwith@Component,@Repository,@Service,@Controller,oracustomannotationthatitselfisannotatedwith@Componentaretheonlydetectedcandidatecomponents.However,youcanmodifyandextendthisbehaviorsimplybyapplyingcustomfilters.AddthemasincludeFiltersorexcludeFiltersparametersofthe@ComponentScanannotation(orasinclude-filterorexclude-filtersub-elementsofthecomponent-scanelement).Eachfilterelementrequiresthetypeandexpressionattributes.Thefollowingtabledescribesthefilteringoptions.

Thefollowingexampleshowstheconfigurationignoringall@Repositoryannotationsandusing"stub"repositoriesinstead.

@Configuration@ComponentScan(basePackages="org.example",includeFilters=@Filter(type=FilterType.REGEX,pattern=".*Stub.*Repository"),excludeFilters=@Filter(Repository.class))publicclassAppConfig{...}andtheequivalentusingXML(使用XML的等价)

YoucanalsodisablethedefaultfiltersbysettinguseDefaultFilters=falseontheannotationorprovidinguse-default-filters="false"asanattributeoftheelement.Thiswillineffectdisableautomaticdetectionofclassesannotatedwith@Component,@Repository,@Service,@Controller,or@Configuration.1.10.5.Definingbeanmetadatawithincomponents(在组件中定义bean元数据)Springcomponentscanalsocontributebeandefinitionmetadatatothecontainer.Youdothiswiththesame@Beanannotationusedtodefinebeanmetadatawithin@Configurationannotatedclasses.Hereisasimpleexample:

@ComponentpublicclassFactoryMethodComponent{@Bean@Qualifier("public")publicTestBeanpublicInstance(){returnnewTestBean("publicInstance");}publicvoiddoWork(){//Componentmethodimplementationomitted}}ThisclassisaSpringcomponentthathasapplication-specificcodecontainedinitsdoWork()method.However,italsocontributesabeandefinitionthathasafactorymethodreferringtothemethodpublicInstance().The@Beanannotationidentifiesthefactorymethodandotherbeandefinitionproperties,suchasaqualifiervaluethroughthe@Qualifierannotation.Othermethodlevelannotationsthatcanbespecifiedare@Scope,@Lazy,andcustomqualifierannotations.

Autowiredfieldsandmethodsaresupportedaspreviouslydiscussed,withadditionalsupportforautowiringof@Beanmethods:

@ComponentpublicclassFactoryMethodComponent{privatestaticinti;@Bean@Qualifier("public")publicTestBeanpublicInstance(){returnnewTestBean("publicInstance");}//useofacustomqualifierandautowiringofmethodparameters@BeanprotectedTestBeanprotectedInstance(@Qualifier("public")TestBeanspouse,@Value("#{privateInstance.age}")Stringcountry){TestBeantb=newTestBean("protectedInstance",1);tb.setSpouse(spouse);tb.setCountry(country);returntb;}@BeanprivateTestBeanprivateInstance(){returnnewTestBean("privateInstance",i++);}@Bean@RequestScopepublicTestBeanrequestScopedInstance(){returnnewTestBean("requestScopedInstance",3);}}TheexampleautowirestheStringmethodparametercountrytothevalueoftheagepropertyonanotherbeannamedprivateInstance.ASpringExpressionLanguageelementdefinesthevalueofthepropertythroughthenotation#{}.For@Valueannotations,anexpressionresolverispreconfiguredtolookforbeannameswhenresolvingexpressiontext.

AsofSpringFramework4.3,youmayalsodeclareafactorymethodparameteroftypeInjectionPoint(oritsmorespecificsubclassDependencyDescriptor)inordertoaccesstherequestinginjectionpointthattriggersthecreationofthecurrentbean.Notethatthiswillonlyapplytotheactualcreationofbeaninstances,nottotheinjectionofexistinginstances.Asaconsequence,thisfeaturemakesmostsenseforbeansofprototypescope.Forotherscopes,thefactorymethodwillonlyeverseetheinjectionpointwhichtriggeredthecreationofanewbeaninstanceinthegivenscope:forexample,thedependencythattriggeredthecreationofalazysingletonbean.Usetheprovidedinjectionpointmetadatawithsemanticcareinsuchscenarios.

@ComponentpublicclassFactoryMethodComponent{@Bean@Scope("prototype")publicTestBeanprototypeInstance(InjectionPointinjectionPoint){returnnewTestBean("prototypeInstancefor"+injectionPoint.getMember());}}The@BeanmethodsinaregularSpringcomponentareprocesseddifferentlythantheircounterpartsinsideaSpring@Configurationclass.Thedifferenceisthat@ComponentclassesarenotenhancedwithCGLIBtointercepttheinvocationofmethodsandfields.CGLIBproxyingisthemeansbywhichinvokingmethodsorfieldswithin@Beanmethodsin@Configurationclassescreatesbeanmetadatareferencestocollaboratingobjects;suchmethodsarenotinvokedwithnormalJavasemanticsbutrathergothroughthecontainerinordertoprovidetheusuallifecyclemanagementandproxyingofSpringbeansevenwhenreferringtootherbeansviaprogrammaticcallsto@Beanmethods.Incontrast,invokingamethodorfieldinan@Beanmethodwithinaplain@ComponentclasshasstandardJavasemantics,withnospecialCGLIBprocessingorotherconstraintsapplying.

Whenacomponentisautodetectedaspartofthescanningprocess,itsbeannameisgeneratedbytheBeanNameGeneratorstrategyknowntothatscanner.Bydefault,anySpringstereotypeannotation(@Component,@Repository,@Service,and@Controller)thatcontainsanamevaluewilltherebyprovidethatnametothecorrespondingbeandefinition.

Ifsuchanannotationcontainsnonamevalueorforanyotherdetectedcomponent(suchasthosediscoveredbycustomfilters),thedefaultbeannamegeneratorreturnstheuncapitalizednon-qualifiedclassname.Forexample,ifthefollowingcomponentclassesweredetected,thenameswouldbemyMovieListerandmovieFinderImpl:

AswithSpring-managedcomponentsingeneral,thedefaultandmostcommonscopeforautodetectedcomponentsissingleton.However,sometimesyouneedadifferentscopewhichcanbespecifiedviathe@Scopeannotation.Simplyprovidethenameofthescopewithintheannotation:

Togeneratetheindex,simplyaddanadditionaldependencytoeachmodulethatcontainscomponentsthataretargetforcomponentscandirectives:

org.springframeworkspring-context-indexer5.0.8.RELEASEtrueOr,usingGradle:(或者,使用它:)

dependencies{compileOnly("org.springframework:spring-context-indexer:5.0.8.RELEASE")}ThatprocesswillgenerateaMETA-INF/spring.componentsfilethatisgoingtobeincludedinthejar.

StartingwithSpring3.0,SpringofferssupportforJSR-330standardannotations(DependencyInjection).ThoseannotationsarescannedinthesamewayastheSpringannotations.Youjustneedtohavetherelevantjarsinyourclasspath.

Insteadof@Autowired,@javax.inject.Injectmaybeusedasfollows:

importjavax.inject.Inject;publicclassSimpleMovieLister{privateMovieFindermovieFinder;@InjectpublicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}publicvoidlistMovies(){this.movieFinder.findMovies(...);...}}Aswith@Autowired,itispossibletouse@Injectatthefieldlevel,methodlevelandconstructor-argumentlevel.Furthermore,youmaydeclareyourinjectionpointasaProvider,allowingforon-demandaccesstobeansofshorterscopesorlazyaccesstootherbeansthroughaProvider.get()call.Asavariantoftheexampleabove:

importjavax.inject.Inject;importjavax.inject.Provider;publicclassSimpleMovieLister{privateProvidermovieFinder;@InjectpublicvoidsetMovieFinder(ProvidermovieFinder){this.movieFinder=movieFinder;}publicvoidlistMovies(){this.movieFinder.get().findMovies(...);...}}Ifyouwouldliketouseaqualifiednameforthedependencythatshouldbeinjected,youshouldusethe@Namedannotationasfollows:

importjavax.inject.Inject;importjavax.inject.Named;publicclassSimpleMovieLister{privateMovieFindermovieFinder;@InjectpublicvoidsetMovieFinder(@Named("main")MovieFindermovieFinder){this.movieFinder=movieFinder;}//...}Like@Autowired,@Injectcanalsobeusedwithjava.util.Optionalor@Nullable.Thisisevenmoreapplicableheresince@Injectdoesnothavearequiredattribute.

publicclassSimpleMovieLister{@InjectpublicvoidsetMovieFinder(OptionalmovieFinder){...}}publicclassSimpleMovieLister{@InjectpublicvoidsetMovieFinder(@NullableMovieFindermovieFinder){...}}1.11.2.@Namedand@ManagedBean:standardequivalentstothe@Componentannotation(@Named和@ManagedBean:与@Component注释的标准等价物)Insteadof@Component,@javax.inject.Namedorjavax.annotation.ManagedBeanmaybeusedasfollows:

importjavax.inject.Inject;importjavax.inject.Named;@Named("movieListener")//@ManagedBean("movieListener")couldbeusedaswellpublicclassSimpleMovieLister{privateMovieFindermovieFinder;@InjectpublicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}//...}Itisverycommontouse@Componentwithoutspecifyinganameforthecomponent.@Namedcanbeusedinasimilarfashion:

importjavax.inject.Inject;importjavax.inject.Named;@NamedpublicclassSimpleMovieLister{privateMovieFindermovieFinder;@InjectpublicvoidsetMovieFinder(MovieFindermovieFinder){this.movieFinder=movieFinder;}//...}Whenusing@Namedor@ManagedBean,itispossibletousecomponentscanningintheexactsamewayaswhenusingSpringannotations:

@Configuration@ComponentScan(basePackages="org.example")publicclassAppConfig{...}Incontrastto@Component,theJSR-330@NamedandtheJSR-250ManagedBeanannotationsarenotcomposable.PleaseuseSpring’sstereotypemodelforbuildingcustomcomponentannotations.1.11.3.LimitationsofJSR-330standardannotations(JSR-330标准注释的限制)Whenworkingwithstandardannotations,itisimportanttoknowthatsomesignificantfeaturesarenotavailableasshowninthetablebelow:

ThecentralartifactsinSpring’snewJava-configurationsupportare@Configuration-annotatedclassesand@Bean-annotatedmethods.

The@Beanannotationisusedtoindicatethatamethodinstantiates,configuresandinitializesanewobjecttobemanagedbytheSpringIoCcontainer.ForthosefamiliarwithSpring’sXMLconfigurationthe@Beanannotationplaysthesameroleastheelement.Youcanuse@BeanannotatedmethodswithanySpring@Component,however,theyaremostoftenusedwith@Configurationbeans.

Annotatingaclasswith@Configurationindicatesthatitsprimarypurposeisasasourceofbeandefinitions.Furthermore,@Configurationclassesallowinter-beandependenciestobedefinedbysimplycallingother@Beanmethodsinthesameclass.Thesimplestpossible@Configurationclasswouldreadasfollows:

@ConfigurationpublicclassAppConfig{@BeanpublicMyServicemyService(){returnnewMyServiceImpl();}}TheAppConfigclassabovewouldbeequivalenttothefollowingSpringXML:

Full@Configurationvs'lite'@Beanmode

When@Beanmethodsaredeclaredwithinclassesthatarenotannotatedwith@Configurationtheyarereferredtoasbeingprocessedina'lite'mode.Beanmethodsdeclaredina@Componentoreveninaplainoldclasswillbeconsidered'lite',withadifferentprimarypurposeofthecontainingclassandan@Beanmethodjustbeingasortofbonusthere.Forexample,servicecomponentsmayexposemanagementviewstothecontainerthroughanadditional@Beanmethodoneachapplicablecomponentclass.Insuchscenarios,@Beanmethodsareasimplegeneral-purposefactorymethodmechanism.

Unlikefull@Configuration,lite@Beanmethodscannotdeclareinter-beandependencies.Instead,theyoperateontheircontainingcomponent’sinternalstateandoptionallyonargumentsthattheymaydeclare.Suchan@Beanmethodshouldthereforenotinvokeother@Beanmethods;eachsuchmethodisliterallyjustafactorymethodforaparticularbeanreference,withoutanyspecialruntimesemantics.Thepositiveside-effecthereisthatnoCGLIBsubclassinghastobeappliedatruntime,sotherearenolimitationsintermsofclassdesign(i.e.thecontainingclassmayneverthelessbefinaletc).

Incommonscenarios,@Beanmethodsaretobedeclaredwithin@Configurationclasses,ensuringthat'full'modeisalwaysusedandthatcross-methodreferenceswillthereforegetredirectedtothecontainer’slifecyclemanagement.Thiswillpreventthesame@BeanmethodfromaccidentallybeinginvokedthrougharegularJavacallwhichhelpstoreducesubtlebugsthatcanbehardtotrackdownwhenoperatingin'lite'mode.

The@Beanand@Configurationannotationswillbediscussedindepthinthesectionsbelow.First,however,we’llcoverthevariouswaysofcreatingaspringcontainerusingJava-basedconfiguration.

ThesectionsbelowdocumentSpring’sAnnotationConfigApplicationContext,newinSpring3.0.ThisversatileApplicationContextimplementationiscapableofacceptingnotonly@Configurationclassesasinput,butalsoplain@ComponentclassesandclassesannotatedwithJSR-330metadata.

When@Configurationclassesareprovidedasinput,the@Configurationclassitselfisregisteredasabeandefinition,andalldeclared@Beanmethodswithintheclassarealsoregisteredasbeandefinitions.

When@ComponentandJSR-330classesareprovided,theyareregisteredasbeandefinitions,anditisassumedthatDImetadatasuchas@Autowiredor@Injectareusedwithinthoseclasseswherenecessary.

InmuchthesamewaythatSpringXMLfilesareusedasinputwheninstantiatingaClassPathXmlApplicationContext,@ConfigurationclassesmaybeusedasinputwheninstantiatinganAnnotationConfigApplicationContext.ThisallowsforcompletelyXML-freeusageoftheSpringcontainer:

publicstaticvoidmain(String[]args){ApplicationContextctx=newAnnotationConfigApplicationContext(AppConfig.class);MyServicemyService=ctx.getBean(MyService.class);myService.doStuff();}Asmentionedabove,AnnotationConfigApplicationContextisnotlimitedtoworkingonlywith@Configurationclasses.Any@ComponentorJSR-330annotatedclassmaybesuppliedasinputtotheconstructor.Forexample:

publicstaticvoidmain(String[]args){ApplicationContextctx=newAnnotationConfigApplicationContext(MyServiceImpl.class,Dependency1.class,Dependency2.class);MyServicemyService=ctx.getBean(MyService.class);myService.doStuff();}TheaboveassumesthatMyServiceImpl,Dependency1andDependency2useSpringdependencyinjectionannotationssuchas@Autowired.

AnAnnotationConfigApplicationContextmaybeinstantiatedusingano-argconstructorandthenconfiguredusingtheregister()method.ThisapproachisparticularlyusefulwhenprogrammaticallybuildinganAnnotationConfigApplicationContext.

publicstaticvoidmain(String[]args){AnnotationConfigApplicationContextctx=newAnnotationConfigApplicationContext();ctx.register(AppConfig.class,OtherConfig.class);ctx.register(AdditionalConfig.class);ctx.refresh();MyServicemyService=ctx.getBean(MyService.class);myService.doStuff();}Enablingcomponentscanningwithscan(String…)(使用scan启用组件扫描(字符串…)Toenablecomponentscanning,justannotateyour@Configurationclassasfollows:

@Configuration@ComponentScan(basePackages="com.acme")publicclassAppConfig{...}ExperiencedSpringuserswillbefamiliarwiththeXMLdeclarationequivalentfromSpring’scontext:namespaceIntheexampleabove,thecom.acmepackagewillbescanned,lookingforany@Component-annotatedclasses,andthoseclasseswillberegisteredasSpringbeandefinitionswithinthecontainer.AnnotationConfigApplicationContextexposesthescan(String…)methodtoallowforthesamecomponent-scanningfunctionality:

Youcanusethe@Beanannotationina@Configuration-annotatedorina@Component-annotatedclass.

Todeclareabean,simplyannotateamethodwiththe@Beanannotation.YouusethismethodtoregisterabeandefinitionwithinanApplicationContextofthetypespecifiedasthemethod’sreturnvalue.Bydefault,thebeannamewillbethesameasthemethodname.Thefollowingisasimpleexampleofa@Beanmethoddeclaration:

@ConfigurationpublicclassAppConfig{@BeanpublicTransferServiceImpltransferService(){returnnewTransferServiceImpl();}}TheprecedingconfigurationisexactlyequivalenttothefollowingSpringXML:

BothdeclarationsmakeabeannamedtransferServiceavailableintheApplicationContext,boundtoanobjectinstanceoftypeTransferServiceImpl:

transferService->com.acme.TransferServiceImplYoumayalsodeclareyour@Beanmethodwithaninterface(orbaseclass)returntype:

@ConfigurationpublicclassAppConfig{@BeanpublicTransferServicetransferService(){returnnewTransferServiceImpl();}}However,thislimitsthevisibilityforadvancetypepredictiontothespecifiedinterfacetype(TransferService)then,withthefulltype(TransferServiceImpl)onlyknowntothecontaineroncetheaffectedsingletonbeanhasbeeninstantiated.Non-lazysingletonbeansgetinstantiatedaccordingtotheirdeclarationorder,soyoumayseedifferenttypematchingresultsdependingonwhenanothercomponenttriestomatchbyanon-declaredtype(suchas@AutowiredTransferServiceImplwhichwillonlyresolveoncethe"transferService"beanhasbeeninstantiated).

A@Beanannotatedmethodcanhaveanarbitrarynumberofparametersdescribingthedependenciesrequiredtobuildthatbean.ForinstanceifourTransferServicerequiresanAccountRepositorywecanmaterializethatdependencyviaamethodparameter:

The@Beanannotationsupportsspecifyingarbitraryinitializationanddestructioncallbackmethods,muchlikeSpringXML’sinit-methodanddestroy-methodattributesonthebeanelement:

Thedefaultscopeissingleton,butyoucanoverridethiswiththe@Scopeannotation:

IfyouportthescopedproxyexamplefromtheXMLreferencedocumentation(seeprecedinglink)toour@BeanusingJava,itwouldlooklikethefollowing:

//anHTTPSession-scopedbeanexposedasaproxy@Bean@SessionScopepublicUserPreferencesuserPreferences(){returnnewUserPreferences();}@BeanpublicServiceuserService(){UserServiceservice=newSimpleUserService();//areferencetotheproxieduserPreferencesbeanservice.setUserPreferences(userPreferences());returnservice;}Customizingbeannaming(定制bean命名)Bydefault,configurationclassesusea@Beanmethod’snameasthenameoftheresultingbean.Thisfunctionalitycanbeoverridden,however,withthenameattribute.

@ConfigurationpublicclassAppConfig{@Bean(name={"dataSource","subsystemA-dataSource","subsystemB-dataSource"})publicDataSourcedataSource(){//instantiate,configureandreturnDataSourcebean...}}Beandescription(Bean描述)Sometimesitishelpfultoprovideamoredetailedtextualdescriptionofabean.Thiscanbeparticularlyusefulwhenbeansareexposed(perhapsviaJMX)formonitoringpurposes.

When@Beanshavedependenciesononeanother,expressingthatdependencyisassimpleashavingonebeanmethodcallanother:

@ConfigurationpublicclassAppConfig{@BeanpublicFoofoo(){returnnewFoo(bar());}@BeanpublicBarbar(){returnnewBar();}}Intheexampleabove,thefoobeanreceivesareferencetobarviaconstructorinjection.

publicabstractclassCommandManager{publicObjectprocess(ObjectcommandState){//grabanewinstanceoftheappropriateCommandinterfaceCommandcommand=createCommand();//setthestateonthe(hopefullybrandnew)Commandinstancecommand.setState(commandState);returncommand.execute();}//okay...butwhereistheimplementationofthismethodprotectedabstractCommandcreateCommand();}UsingJava-configurationsupport,youcancreateasubclassofCommandManagerwheretheabstractcreateCommand()methodisoverriddeninsuchawaythatitlooksupanew(prototype)commandobject:

@Bean@Scope("prototype")publicAsyncCommandasyncCommand(){AsyncCommandcommand=newAsyncCommand();//injectdependencieshereasrequiredreturncommand;}@BeanpublicCommandManagercommandManager(){//returnnewanonymousimplementationofCommandManagerwithcommand()overridden//toreturnanewprototypeCommandobjectreturnnewCommandManager(){protectedCommandcreateCommand(){returnasyncCommand();}}}FurtherinformationabouthowJava-basedconfigurationworksinternally(关于基于java的配置如何在内部工作的进一步信息)Thefollowingexampleshowsa@Beanannotatedmethodbeingcalledtwice:

MuchastheelementisusedwithinSpringXMLfilestoaidinmodularizingconfigurations,the@Importannotationallowsforloading@Beandefinitionsfromanotherconfigurationclass:

@ConfigurationpublicclassConfigA{@BeanpublicAa(){returnnewA();}}@Configuration@Import(ConfigA.class)publicclassConfigB{@BeanpublicBb(){returnnewB();}}Now,ratherthanneedingtospecifybothConfigA.classandConfigB.classwheninstantiatingthecontext,onlyConfigBneedstobesuppliedexplicitly:

publicstaticvoidmain(String[]args){ApplicationContextctx=newAnnotationConfigApplicationContext(ConfigB.class);//nowbothbeansAandBwillbeavailable...Aa=ctx.getBean(A.class);Bb=ctx.getBean(B.class);}Thisapproachsimplifiescontainerinstantiation,asonlyoneclassneedstobedealtwith,ratherthanrequiringthedevelopertorememberapotentiallylargenumberof@Configurationclassesduringconstruction.

Theexampleaboveworks,butissimplistic.Inmostpracticalscenarios,beanswillhavedependenciesononeanotheracrossconfigurationclasses.WhenusingXML,thisisnotanissue,perse,becausethereisnocompilerinvolved,andonecansimplydeclareref="someBean"andtrustthatSpringwillworkitoutduringcontainerinitialization.Ofcourse,whenusing@Configurationclasses,theJavacompilerplacesconstraintsontheconfigurationmodel,inthatreferencestootherbeansmustbevalidJavasyntax.

@ConfigurationpublicclassServiceConfig{@BeanpublicTransferServicetransferService(AccountRepositoryaccountRepository){returnnewTransferServiceImpl(accountRepository);}}@ConfigurationpublicclassRepositoryConfig{@BeanpublicAccountRepositoryaccountRepository(DataSourcedataSource){returnnewJdbcAccountRepository(dataSource);}}@Configuration@Import({ServiceConfig.class,RepositoryConfig.class})publicclassSystemTestConfig{@BeanpublicDataSourcedataSource(){//returnnewDataSource}}publicstaticvoidmain(String[]args){ApplicationContextctx=newAnnotationConfigApplicationContext(SystemTestConfig.class);//everythingwiresupacrossconfigurationclasses...TransferServicetransferService=ctx.getBean(TransferService.class);transferService.transfer(100.00,"A123","C456");}Thereisanotherwaytoachievethesameresult.Rememberthat@Configurationclassesareultimatelyjustanotherbeaninthecontainer:Thismeansthattheycantakeadvantageof@Autowiredand@Valueinjectionetcjustlikeanyotherbean!

IncaseswherethisambiguityisnotacceptableandyouwishtohavedirectnavigationfromwithinyourIDEfromone@Configurationclasstoanother,considerautowiringtheconfigurationclassesthemselves:

@ConfigurationpublicclassServiceConfig{@AutowiredprivateRepositoryConfigrepositoryConfig;@BeanpublicTransferServicetransferService(){//navigate'through'theconfigclasstothe@Beanmethod!returnnewTransferServiceImpl(repositoryConfig.accountRepository());}}Inthesituationabove,itiscompletelyexplicitwhereAccountRepositoryisdefined.However,ServiceConfigisnowtightlycoupledtoRepositoryConfig;that’sthetradeoff.Thistightcouplingcanbesomewhatmitigatedbyusinginterface-basedorabstractclass-based@Configurationclasses.Considerthefollowing:

ImplementationsoftheConditioninterfacesimplyprovideamatches(…)methodthatreturnstrueorfalse.Forexample,hereistheactualConditionimplementationusedfor@Profile:

Spring’s@Configurationclasssupportdoesnotaimtobea100%completereplacementforSpringXML.SomefacilitiessuchasSpringXMLnamespacesremainanidealwaytoconfigurethecontainer.IncaseswhereXMLisconvenientornecessary,youhaveachoice:eitherinstantiatethecontainerinan"XML-centric"wayusing,forexample,ClassPathXmlApplicationContext,orina"Java-centric"fashionusingAnnotationConfigApplicationContextandthe@ImportResourceannotationtoimportXMLasneeded.

ItmaybepreferabletobootstraptheSpringcontainerfromXMLandinclude@Configurationclassesinanad-hocfashion.Forexample,inalargeexistingcodebasethatusesSpringXML,itwillbeeasiertocreate@Configurationclassesonanas-neededbasisandincludethemfromtheexistingXMLfiles.Belowyou’llfindtheoptionsforusing@Configurationclassesinthiskindof"XML-centric"situation.

Rememberthat@Configurationclassesareultimatelyjustbeandefinitionsinthecontainer.Inthisexample,wecreatea@ConfigurationclassnamedAppConfigandincludeitwithinsystem-test-config.xmlasadefinition.Becauseisswitchedon,thecontainerwillrecognizethe@Configurationannotationandprocessthe@BeanmethodsdeclaredinAppConfigproperly.

@ConfigurationpublicclassAppConfig{@AutowiredprivateDataSourcedataSource;@BeanpublicAccountRepositoryaccountRepository(){returnnewJdbcAccountRepository(dataSource);}@BeanpublicTransferServicetransferService(){returnnewTransferService(accountRepository());}}system-test-config.xml:

jdbc.properties:

jdbc.url=jdbc:hsqldb:hsql://localhost/xdbjdbc.username=sajdbc.password=publicstaticvoidmain(String[]args){ApplicationContextctx=newClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");TransferServicetransferService=ctx.getBean(TransferService.class);//...}Insystem-test-config.xmlabove,theAppConfigdoesnotdeclareanidelement.Whileitwouldbeacceptabletodoso,itisunnecessarygiventhatnootherbeanwilleverrefertoit,anditisunlikelythatitwillbeexplicitlyfetchedfromthecontainerbyname.LikewisewiththeDataSourcebean-itisonlyeverautowiredbytype,soanexplicitbeanidisnotstrictlyrequired.Usingcontext:component-scan/topickup@Configurationclasses(使用context:component-scan/获取@Configuration类)

Because@Configurationismeta-annotatedwith@Component,@Configuration-annotatedclassesareautomaticallycandidatesforcomponentscanning.Usingthesamescenarioasabove,wecanredefinesystem-test-config.xmltotakeadvantageofcomponent-scanning.Notethatinthiscase,wedon’tneedtoexplicitlydeclare,becauseenablesthesamefunctionality.

system-test-config.xml:

@Configurationclass-centricuseofXMLwith@ImportResourceInapplicationswhere@Configurationclassesaretheprimarymechanismforconfiguringthecontainer,itwillstilllikelybenecessarytouseatleastsomeXML.Inthesescenarios,simplyuse@ImportResourceanddefineonlyasmuchXMLasisneeded.Doingsoachievesa"Java-centric"approachtoconfiguringthecontainerandkeepsXMLtoabareminimum.

Aprofileisanamed,logicalgroupofbeandefinitionstoberegisteredwiththecontaineronlyifthegivenprofileisactive.BeansmaybeassignedtoaprofilewhetherdefinedinXMLorviaannotations.TheroleoftheEnvironmentobjectwithrelationtoprofilesisindeterminingwhichprofiles(ifany)arecurrentlyactive,andwhichprofiles(ifany)shouldbeactivebydefault.

Propertiesplayanimportantroleinalmostallapplications,andmayoriginatefromavarietyofsources:propertiesfiles,JVMsystemproperties,systemenvironmentvariables,JNDI,servletcontextparameters,ad-hocPropertiesobjects,Maps,andsoon.TheroleoftheEnvironmentobjectwithrelationtopropertiesistoprovidetheuserwithaconvenientserviceinterfaceforconfiguringpropertysourcesandresolvingpropertiesfromthem.

Beandefinitionprofilesisamechanisminthecorecontainerthatallowsforregistrationofdifferentbeansindifferentenvironments.Thewordenvironmentcanmeandifferentthingstodifferentusersandthisfeaturecanhelpwithmanyusecases,including:

Let’sconsiderthefirstusecaseinapracticalapplicationthatrequiresaDataSource.Inatestenvironment,theconfigurationmaylooklikethis:

@BeanpublicDataSourcedataSource(){returnnewEmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("my-schema.sql").addScript("my-test-data.sql").build();}Let’snowconsiderhowthisapplicationwillbedeployedintoaQAorproductionenvironment,assumingthatthedatasourcefortheapplicationwillberegisteredwiththeproductionapplicationserver’sJNDIdirectory.OurdataSourcebeannowlookslikethis:

@Bean(destroyMethod="")publicDataSourcedataSource()throwsException{Contextctx=newInitialContext();return(DataSource)ctx.lookup("java:comp/env/jdbc/datasource");}Theproblemishowtoswitchbetweenusingthesetwovariationsbasedonthecurrentenvironment.Overtime,Springusershavedevisedanumberofwaystogetthisdone,usuallyrelyingonacombinationofsystemenvironmentvariablesandXMLstatementscontaining${placeholder}tokensthatresolvetothecorrectconfigurationfilepathdependingonthevalueofanenvironmentvariable.Beandefinitionprofilesisacorecontainerfeaturethatprovidesasolutiontothisproblem.

Ifwegeneralizetheexampleusecaseaboveofenvironment-specificbeandefinitions,weendupwiththeneedtoregistercertainbeandefinitionsincertaincontexts,whilenotinothers.YoucouldsaythatyouwanttoregisteracertainprofileofbeandefinitionsinsituationA,andadifferentprofileinsituationB.Let’sfirstseehowwecanupdateourconfigurationtoreflectthisneed.

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Profile("production")public@interfaceProduction{}Ifa@Configurationclassismarkedwith@Profile,allofthe@Beanmethodsand@Importannotationsassociatedwiththatclasswillbebypassedunlessoneormoreofthespecifiedprofilesareactive.Ifa@Componentor@Configurationclassismarkedwith@Profile({"p1","p2"}),thatclasswillnotberegistered/processedunlessprofiles'p1'and/or'p2'havebeenactivated.IfagivenprofileisprefixedwiththeNOToperator(!),theannotatedelementwillberegisterediftheprofileisnotactive.Forexample,given@Profile({"p1","!p2"}),registrationwilloccurifprofile'p1'isactiveorifprofile'p2'isnotactive.@Profilecanalsobedeclaredatthemethodleveltoincludeonlyoneparticularbeanofaconfigurationclass,e.g.foralternativevariantsofaparticularbean:

Nowthatwehaveupdatedourconfiguration,westillneedtoinstructSpringwhichprofileisactive.Ifwestartedoursampleapplicationrightnow,wewouldseeaNoSuchBeanDefinitionExceptionthrown,becausethecontainercouldnotfindtheSpringbeannameddataSource.

Activatingaprofilecanbedoneinseveralways,butthemoststraightforwardistodoitprogrammaticallyagainsttheEnvironmentAPIwhichisavailableviaanApplicationContext:

Notethatprofilesarenotan"either-or"proposition;itispossibletoactivatemultipleprofilesatonce.Programmatically,simplyprovidemultipleprofilenamestothesetActiveProfiles()method,whichacceptsString…varargs:

ctx.getEnvironment().setActiveProfiles("profile1","profile2");Declaratively,spring.profiles.activemayacceptacomma-separatedlistofprofilenames:

-Dspring.profiles.active="profile1,profile2"Defaultprofile(默认配置文件)Thedefaultprofilerepresentstheprofilethatisenabledbydefault.Considerthefollowing:(默认配置文件表示默认情况下启用的配置文件。考虑以下:)

@Configuration@Profile("default")publicclassDefaultDataConfig{@BeanpublicDataSourcedataSource(){returnnewEmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:com/bank/config/sql/schema.sql").build();}}Ifnoprofileisactive,thedataSourceabovewillbecreated;thiscanbeseenasawaytoprovideadefaultdefinitionforoneormorebeans.Ifanyprofileisenabled,thedefaultprofilewillnotapply.

ThenameofthedefaultprofilecanbechangedusingsetDefaultProfiles()ontheEnvironmentordeclarativelyusingthespring.profiles.defaultproperty.

Spring’sEnvironmentabstractionprovidessearchoperationsoveraconfigurablehierarchyofpropertysources.Toexplainfully,considerthefollowing:

Concretely,whenusingtheStandardEnvironment,thecalltoenv.containsProperty("foo")willreturntrueifafoosystempropertyorfooenvironmentvariableispresentatruntime.

Mostimportantly,theentiremechanismisconfigurable.Perhapsyouhaveacustomsourceofpropertiesthatyou’dliketointegrateintothissearch.Noproblem—simplyimplementandinstantiateyourownPropertySourceandaddittothesetofPropertySourcesforthecurrentEnvironment:

Givenafile"app.properties"containingthekey/valuepairtestbean.name=myTestBean,thefollowing@Configurationclassuses@PropertySourceinsuchawaythatacalltotestBean.getName()willreturn"myTestBean".

@Configuration@PropertySource("classpath:/com/myco/app.properties")publicclassAppConfig{@AutowiredEnvironmentenv;@BeanpublicTestBeantestBean(){TestBeantestBean=newTestBean();testBean.setName(env.getProperty("testbean.name"));returntestBean;}}Any${…}placeholderspresentina@PropertySourceresourcelocationwillberesolvedagainstthesetofpropertysourcesalreadyregisteredagainsttheenvironment.Forexample:

@Configuration@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")publicclassAppConfig{@AutowiredEnvironmentenv;@BeanpublicTestBeantestBean(){TestBeantestBean=newTestBean();testBean.setName(env.getProperty("testbean.name"));returntestBean;}}Assumingthat"my.placeholder"ispresentinoneofthepropertysourcesalreadyregistered,e.g.systempropertiesorenvironmentvariables,theplaceholderwillberesolvedtothecorrespondingvalue.Ifnot,then"default/path"willbeusedasadefault.Ifnodefaultisspecifiedandapropertycannotberesolved,anIllegalArgumentExceptionwillbethrown.

Historically,thevalueofplaceholdersinelementscouldberesolvedonlyagainstJVMsystempropertiesorenvironmentvariables.Nolongeristhisthecase.BecausetheEnvironmentabstractionisintegratedthroughoutthecontainer,it’seasytorouteresolutionofplaceholdersthroughit.Thismeansthatyoumayconfiguretheresolutionprocessinanywayyoulike:changetheprecedenceofsearchingthroughsystempropertiesandenvironmentvariables,orremovethementirely;addyourownpropertysourcestothemixasappropriate.

Concretely,thefollowingstatementworksregardlessofwherethecustomerpropertyisdefined,aslongasitisavailableintheEnvironment:

1.14.RegisteringaLoadTimeWeaver(注册一个LoadTimeWeaverTheLoadTimeWeaverisusedbySpringtodynamicallytransformclassesastheyareloadedintotheJavavirtualmachine(JVM).

Toenableload-timeweavingaddthe@EnableLoadTimeWeavingtooneofyour@Configurationclasses:

@Configuration@EnableLoadTimeWeavingpublicclassAppConfig{}AlternativelyforXMLconfigurationusethecontext:load-time-weaverelement:

ToenhanceBeanFactoryfunctionalityinamoreframework-orientedstylethecontextpackagealsoprovidesthefollowingfunctionality:

TheApplicationContextinterfaceextendsaninterfacecalledMessageSource,andthereforeprovidesinternationalization(i18n)functionality.SpringalsoprovidestheinterfaceHierarchicalMessageSource,whichcanresolvemessageshierarchically.TogethertheseinterfacesprovidethefoundationuponwhichSpringeffectsmessageresolution.Themethodsdefinedontheseinterfacesinclude:

WhenanApplicationContextisloaded,itautomaticallysearchesforaMessageSourcebeandefinedinthecontext.ThebeanmusthavethenamemessageSource.Ifsuchabeanisfound,allcallstotheprecedingmethodsaredelegatedtothemessagesource.Ifnomessagesourceisfound,theApplicationContextattemptstofindaparentcontainingabeanwiththesamename.Ifitdoes,itusesthatbeanastheMessageSource.IftheApplicationContextcannotfindanysourceformessages,anemptyDelegatingMessageSourceisinstantiatedinordertobeabletoacceptcallstothemethodsdefinedabove.

SpringprovidestwoMessageSourceimplementations,ResourceBundleMessageSourceandStaticMessageSource.BothimplementHierarchicalMessageSourceinordertodonestedmessaging.TheStaticMessageSourceisrarelyusedbutprovidesprogrammaticwaystoaddmessagestothesource.TheResourceBundleMessageSourceisshowninthefollowingexample:

formatexceptionswindowsIntheexampleitisassumedyouhavethreeresourcebundlesdefinedinyourclasspathcalledformat,exceptionsandwindows.AnyrequesttoresolveamessagewillbehandledintheJDKstandardwayofresolvingmessagesthroughResourceBundles.Forthepurposesoftheexample,assumethecontentsoftwooftheaboveresourcebundlefilesare…

#informat.propertiesmessage=Alligatorsrock!#inexceptions.propertiesargument.required=The{0}argumentisrequired.AprogramtoexecutetheMessageSourcefunctionalityisshowninthenextexample.RememberthatallApplicationContextimplementationsarealsoMessageSourceimplementationsandsocanbecasttotheMessageSourceinterface.

publicstaticvoidmain(String[]args){MessageSourceresources=newClassPathXmlApplicationContext("beans.xml");Stringmessage=resources.getMessage("message",null,"Default",null);System.out.println(message);}Theresultingoutputfromtheaboveprogramwillbe…

Alligatorsrock!Sotosummarize,theMessageSourceisdefinedinafilecalledbeans.xml,whichexistsattherootofyourclasspath.ThemessageSourcebeandefinitionreferstoanumberofresourcebundlesthroughitsbasenamesproperty.Thethreefilesthatarepassedinthelisttothebasenamespropertyexistasfilesattherootofyourclasspathandarecalledformat.properties,exceptions.properties,andwindows.propertiesrespectively.

Thenextexampleshowsargumentspassedtothemessagelookup;theseargumentswillbeconvertedintoStringsandinsertedintoplaceholdersinthelookupmessage.

publicclassExample{privateMessageSourcemessages;publicvoidsetMessages(MessageSourcemessages){this.messages=messages;}publicvoidexecute(){Stringmessage=this.messages.getMessage("argument.required",newObject[]{"userDao"},"Required",null);System.out.println(message);}}Theresultingoutputfromtheinvocationoftheexecute()methodwillbe…

TheuserDaoargumentisrequired.Withregardtointernationalization(i18n),Spring’svariousMessageSourceimplementationsfollowthesamelocaleresolutionandfallbackrulesasthestandardJDKResourceBundle.Inshort,andcontinuingwiththeexamplemessageSourcedefinedpreviously,ifyouwanttoresolvemessagesagainsttheBritish(en-GB)locale,youwouldcreatefilescalledformat_en_GB.properties,exceptions_en_GB.properties,andwindows_en_GB.propertiesrespectively.

Typically,localeresolutionismanagedbythesurroundingenvironmentoftheapplication.Inthisexample,thelocaleagainstwhich(British)messageswillberesolvedisspecifiedmanually.

#inexceptions_en_GB.propertiesargument.required=Ebagumlad,the{0}argumentisrequired,Isay,required.publicstaticvoidmain(finalString[]args){MessageSourceresources=newClassPathXmlApplicationContext("beans.xml");Stringmessage=resources.getMessage("argument.required",newObject[]{"userDao"},"Required",Locale.UK);System.out.println(message);}Theresultingoutputfromtherunningoftheaboveprogramwillbe…

Ebagumlad,the'userDao'argumentisrequired,Isay,required.YoucanalsousetheMessageSourceAwareinterfacetoacquireareferencetoanyMessageSourcethathasbeendefined.AnybeanthatisdefinedinanApplicationContextthatimplementstheMessageSourceAwareinterfaceisinjectedwiththeapplicationcontext’sMessageSourcewhenthebeaniscreatedandconfigured.

EventhandlingintheApplicationContextisprovidedthroughtheApplicationEventclassandApplicationListenerinterface.IfabeanthatimplementstheApplicationListenerinterfaceisdeployedintothecontext,everytimeanApplicationEventgetspublishedtotheApplicationContext,thatbeanisnotified.Essentially,thisisthestandardObserverdesignpattern.

Springprovidesthefollowingstandardevents:

Youcanalsocreateandpublishyourowncustomevents.ThisexampledemonstratesasimpleclassthatextendsSpring’sApplicationEventbaseclass:

publicclassBlackListEventextendsApplicationEvent{privatefinalStringaddress;privatefinalStringtest;publicBlackListEvent(Objectsource,Stringaddress,Stringtest){super(source);this.address=address;this.test=test;}//accessorandothermethods...}TopublishacustomApplicationEvent,callthepublishEvent()methodonanApplicationEventPublisher.TypicallythisisdonebycreatingaclassthatimplementsApplicationEventPublisherAwareandregisteringitasaSpringbean.Thefollowingexampledemonstratessuchaclass:

publicclassEmailServiceimplementsApplicationEventPublisherAware{privateListblackList;privateApplicationEventPublisherpublisher;publicvoidsetBlackList(ListblackList){this.blackList=blackList;}publicvoidsetApplicationEventPublisher(ApplicationEventPublisherpublisher){this.publisher=publisher;}publicvoidsendEmail(Stringaddress,Stringtext){if(blackList.contains(address)){BlackListEventevent=newBlackListEvent(this,address,text);publisher.publishEvent(event);return;}//sendemail...}}Atconfigurationtime,theSpringcontainerwilldetectthatEmailServiceimplementsApplicationEventPublisherAwareandwillautomaticallycallsetApplicationEventPublisher().Inreality,theparameterpassedinwillbetheSpringcontaineritself;you’resimplyinteractingwiththeapplicationcontextviaitsApplicationEventPublisherinterface.

ToreceivethecustomApplicationEvent,createaclassthatimplementsApplicationListenerandregisteritasaSpringbean.Thefollowingexampledemonstratessuchaclass:

publicclassBlackListNotifierimplementsApplicationListener{privateStringnotificationAddress;publicvoidsetNotificationAddress(StringnotificationAddress){this.notificationAddress=notificationAddress;}publicvoidonApplicationEvent(BlackListEventevent){//notifyappropriatepartiesvianotificationAddress...}}NoticethatApplicationListenerisgenericallyparameterizedwiththetypeofyourcustomevent,BlackListEvent.ThismeansthattheonApplicationEvent()methodcanremaintype-safe,avoidinganyneedfordowncasting.Youmayregisterasmanyeventlistenersasyouwish,butnotethatbydefaulteventlistenersreceiveeventssynchronously.ThismeansthepublishEvent()methodblocksuntilalllistenershavefinishedprocessingtheevent.Oneadvantageofthissynchronousandsingle-threadedapproachisthatwhenalistenerreceivesanevent,itoperatesinsidethetransactioncontextofthepublisherifatransactioncontextisavailable.Ifanotherstrategyforeventpublicationbecomesnecessary,refertothejavadocforSpring’sApplicationEventMulticasterinterface.

Thefollowingexampleshowsthebeandefinitionsusedtoregisterandconfigureeachoftheclassesabove:

known.spammer@example.orgknown.hacker@example.orgjohn.doe@example.orgPuttingitalltogether,whenthesendEmail()methodoftheemailServicebeaniscalled,ifthereareanyemailsthatshouldbeblacklisted,acustomeventoftypeBlackListEventispublished.TheblackListNotifierbeanisregisteredasanApplicationListenerandthusreceivestheBlackListEvent,atwhichpointitcannotifyappropriateparties.

AsofSpring4.2,aneventlistenercanberegisteredonanypublicmethodofamanagedbeanviatheEventListenerannotation.TheBlackListNotifiercanberewrittenasfollows:

publicclassBlackListNotifier{privateStringnotificationAddress;publicvoidsetNotificationAddress(StringnotificationAddress){this.notificationAddress=notificationAddress;}@EventListenerpublicvoidprocessBlackListEvent(BlackListEventevent){//notifyappropriatepartiesvianotificationAddress...}}Asyoucanseeabove,themethodsignatureonceagaindeclarestheeventtypeitlistensto,butthistimewithaflexiblenameandwithoutimplementingaspecificlistenerinterface.Theeventtypecanalsobenarrowedthroughgenericsaslongastheactualeventtyperesolvesyourgenericparameterinitsimplementationhierarchy.

Ifyourmethodshouldlistentoseveraleventsorifyouwanttodefineitwithnoparameteratall,theeventtype(s)canalsobespecifiedontheannotationitself:

Forinstance,ournotifiercanberewrittentobeonlyinvokedifthetestattributeoftheeventisequaltofoo:

@EventListener(condition="#blEvent.test=='foo'")publicvoidprocessBlackListEvent(BlackListEventblEvent){//notifyappropriatepartiesvianotificationAddress...}EachSpELexpressionevaluatesagainadedicatedcontext.Thenexttableliststheitemsmadeavailabletothecontextsoonecanusethemforconditionaleventprocessing:

Notethat#root.eventallowsyoutoaccesstotheunderlyingevent,evenifyourmethodsignatureactuallyreferstoanarbitraryobjectthatwaspublished.

Ifyouneedtopublishaneventastheresultofprocessinganother,justchangethemethodsignaturetoreturntheeventthatshouldbepublished,somethinglike:

@EventListener@AsyncpublicvoidprocessBlackListEvent(BlackListEventevent){//BlackListEventisprocessedinaseparatethread}Beawareofthefollowinglimitationswhenusingasynchronousevents:

Ifyouneedthelistenertobeinvokedbeforeanotherone,justaddthe@Orderannotationtothemethoddeclaration:

@EventListener@Order(42)publicvoidprocessBlackListEvent(BlackListEventevent){//notifyappropriatepartiesvianotificationAddress...}Genericevents(通用的事件)Youmayalsousegenericstofurtherdefinethestructureofyourevent.ConsideranEntityCreatedEventwhereTisthetypeoftheactualentitythatgotcreated.YoucancreatethefollowinglistenerdefinitiontoonlyreceiveEntityCreatedEventforaPerson:

@EventListenerpublicvoidonPersonCreated(EntityCreatedEventevent){...}Duetotypeerasure,thiswillonlyworkiftheeventthatisfiredresolvesthegenericparameter(s)onwhichtheeventlistenerfilterson(thatissomethinglikeclassPersonCreatedEventextendsEntityCreatedEvent{…}).

Incertaincircumstances,thismaybecomequitetediousifalleventsfollowthesamestructure(asitshouldbethecasefortheeventabove).Insuchacase,youcanimplementResolvableTypeProvidertoguidetheframeworkbeyondwhattheruntimeenvironmentprovides:

AnapplicationcontextisaResourceLoader,whichcanbeusedtoloadResources.AResourceisessentiallyamorefeaturerichversionoftheJDKclassjava.net.URL,infact,theimplementationsoftheResourcewrapaninstanceofjava.net.URLwhereappropriate.AResourcecanobtainlow-levelresourcesfromalmostanylocationinatransparentfashion,includingfromtheclasspath,afilesystemlocation,anywheredescribablewithastandardURL,andsomeothervariations.Iftheresourcelocationstringisasimplepathwithoutanyspecialprefixes,wherethoseresourcescomefromisspecificandappropriatetotheactualapplicationcontexttype.

Youcanconfigureabeandeployedintotheapplicationcontexttoimplementthespecialcallbackinterface,ResourceLoaderAware,tobeautomaticallycalledbackatinitializationtimewiththeapplicationcontextitselfpassedinastheResourceLoader.YoucanalsoexposepropertiesoftypeResource,tobeusedtoaccessstaticresources;theywillbeinjectedintoitlikeanyotherproperties.YoucanspecifythoseResourcepropertiesassimpleStringpaths,andrelyonaspecialJavaBeanPropertyEditorthatisautomaticallyregisteredbythecontext,toconvertthosetextstringstoactualResourceobjectswhenthebeanisdeployed.

ThelocationpathorpathssuppliedtoanApplicationContextconstructorareactuallyresourcestrings,andinsimpleformaretreatedappropriatelytothespecificcontextimplementation.ClassPathXmlApplicationContexttreatsasimplelocationpathasaclasspathlocation.Youcanalsouselocationpaths(resourcestrings)withspecialprefixestoforceloadingofdefinitionsfromtheclasspathoraURL,regardlessoftheactualcontexttype.

YoucancreateApplicationContextinstancesdeclarativelybyusing,forexample,aContextLoader.OfcourseyoucanalsocreateApplicationContextinstancesprogrammaticallybyusingoneoftheApplicationContextimplementations.

YoucanregisteranApplicationContextusingtheContextLoaderListenerasfollows:

contextConfigLocation/WEB-INF/daoContext.xml/WEB-INF/applicationContext.xmlorg.springframework.web.context.ContextLoaderListenerThelistenerinspectsthecontextConfigLocationparameter.Iftheparameterdoesnotexist,thelisteneruses/WEB-INF/applicationContext.xmlasadefault.Whentheparameterdoesexist,thelistenerseparatestheStringbyusingpredefineddelimiters(comma,semicolonandwhitespace)andusesthevaluesaslocationswhereapplicationcontextswillbesearched.Ant-stylepathpatternsaresupportedaswell.Examplesare/WEB-INF/*Context.xmlforallfileswithnamesendingwith"Context.xml",residinginthe"WEB-INF"directory,and/WEB-INF/**/*Context.xml,forallsuchfilesinanysubdirectoryof"WEB-INF".

ItispossibletodeployaSpringApplicationContextasaRARfile,encapsulatingthecontextandallofitsrequiredbeanclassesandlibraryJARsinaJavaEERARdeploymentunit.ThisistheequivalentofbootstrappingastandaloneApplicationContext,justhostedinJavaEEenvironment,beingabletoaccesstheJavaEEserversfacilities.RARdeploymentismorenaturalalternativetoscenarioofdeployingaheadlessWARfile,ineffect,aWARfilewithoutanyHTTPentrypointsthatisusedonlyforbootstrappingaSpringApplicationContextinaJavaEEenvironment.

RARdeploymentisidealforapplicationcontextsthatdonotneedHTTPentrypointsbutratherconsistonlyofmessageendpointsandscheduledjobs.BeansinsuchacontextcanuseapplicationserverresourcessuchastheJTAtransactionmanagerandJNDI-boundJDBCDataSourcesandJMSConnectionFactoryinstances,andmayalsoregisterwiththeplatform’sJMXserver-allthroughSpring’sstandardtransactionmanagementandJNDIandJMXsupportfacilities.Applicationcomponentscanalsointeractwiththeapplicationserver’sJCAWorkManagerthroughSpring’sTaskExecutorabstraction.

ForasimpledeploymentofaSpringApplicationContextasaJavaEERARfile:packageallapplicationclassesintoaRARfile,whichisastandardJARfilewithadifferentfileextension.AddallrequiredlibraryJARsintotherootoftheRARarchive.Adda"META-INF/ra.xml"deploymentdescriptor(asshowninSpringContextResourceAdaptersjavadoc)andthecorrespondingSpringXMLbeandefinitionfile(s)(typically"META-INF/applicationContext.xml"),anddroptheresultingRARfileintoyourapplicationserver’sdeploymentdirectory.

TheBeanFactoryprovidestheunderlyingbasisforSpring’sIoCfunctionalitybutitisonlyuseddirectlyinintegrationwithotherthird-partyframeworksandisnowlargelyhistoricalinnatureformostusersofSpring.TheBeanFactoryandrelatedinterfaces,suchasBeanFactoryAware,InitializingBean,DisposableBean,arestillpresentinSpringforthepurposesofbackwardcompatibilitywiththelargenumberofthird-partyframeworksthatintegratewithSpring.Oftenthird-partycomponentsthatcannotusemoremodernequivalentssuchas@PostConstructor@PreDestroyinordertoavoidadependencyonJSR-250.

ThissectionprovidesadditionalbackgroundintothedifferencesbetweentheBeanFactoryandApplicationContextandhowonemightaccesstheIoCcontainerdirectlythroughaclassicsingletonlookup.

UseanApplicationContextunlessyouhaveagoodreasonfornotdoingso.(使用ApplicationContext,除非你有很好的理由不这样做。)

ThefollowingtablelistsfeaturesprovidedbytheBeanFactoryandApplicationContextinterfacesandimplementations.

Toexplicitlyregisterabeanpost-processorwithaBeanFactoryimplementation,youneedtowritecodelikethis:

DefaultListableBeanFactoryfactory=newDefaultListableBeanFactory();//populatethefactorywithbeandefinitions//nowregisteranyneededBeanPostProcessorinstancesMyBeanPostProcessorpostProcessor=newMyBeanPostProcessor();factory.addBeanPostProcessor(postProcessor);//nowstartusingthefactoryToexplicitlyregisteraBeanFactoryPostProcessorwhenusingaBeanFactoryimplementation,youmustwritecodelikethis:

DefaultListableBeanFactoryfactory=newDefaultListableBeanFactory();XmlBeanDefinitionReaderreader=newXmlBeanDefinitionReader(factory);reader.loadBeanDefinitions(newFileSystemResource("beans.xml"));//bringinsomepropertyvaluesfromaPropertiesfilePropertyPlaceholderConfigurercfg=newPropertyPlaceholderConfigurer();cfg.setLocation(newFileSystemResource("jdbc.properties"));//nowactuallydothereplacementcfg.postProcessBeanFactory(factory);Inbothcases,theexplicitregistrationstepisinconvenient,whichisonereasonwhythevariousApplicationContextimplementationsarepreferredaboveplainBeanFactoryimplementationsinthevastmajorityofSpring-backedapplications,especiallywhenusingBeanFactoryPostProcessorsandBeanPostProcessors.ThesemechanismsimplementimportantfunctionalitysuchaspropertyplaceholderreplacementandAOP.

THE END
1.魔咒奇漫屋漫画下拉:互联网的坏处用英语怎么说扶他漫画正版免费阅读 下载 漫蛙manwa漫画免费入口页面 下载 里番在线 下载 小黃片秘 视频 下载 老师快扒开腿让我c 下载 嫩草www天堂资源在线观看 下载 查看更多 最新手游分享 更多 www.1688.my进入 下载 国产男男Gay 体育生小说 下载 好爽 要高潮了 再深点动漫 下载 可以变硬的图片 下载 https://bbs.fanruan.com/wenda/question/6256784.html
2.四六级考试神翻译频出,大学生创意与知识漏洞并存睿鸿在线然而,这也正是四六级考试的魅力所在,它不仅考验学生的英语水平,还能在一定程度上反映出学生的思维能力和应变能力。 四六级考试作为衡量中国大学生英语水平的重要标准,自 1987 年首次举办以来,每年都有数百万学生参加。但通过率并不高,尤其是翻译部分,一直是许多学生的难题。这也提醒大学生们在平时的英语学习中,要https://m.orihonor.com/2024/12/15/30944.shtml
3.语法基础3第七节(3)——定语和定语从句考点分析第四,最后一个区别,虽然不够严谨,但是也可以作为参考。那就是定语从句的引导词有很多,而同位语从句的引导词通常是 that(因为同位语从句大部分都是陈述句)。 同位语从句是写作满分句型,定语从句不是;翻译时没区别。 二、写作中的定语化妆 只要在作文中见到名词,都可以给它加一个定语的成分把句子加长。 https://www.jianshu.com/p/104a1a75502c
4.我认为在国外学习有好处也有坏处的翻译是:什么意思?中文翻译我认为在国外学习有好处也有坏处问题补充:匿名 2013-05-23 12:21:38 正在翻译,请等待 匿名 2013-05-23 12:23:18 正在翻译,请等待 匿名 2013-05-23 12:24:58 正在翻译,请等待 匿名 2013-05-23 12:26:38 正在翻译,请等待 匿名 2013-05-23 12:28:18 正在翻译,请http://www.zaixian-fanyi.com/fan_yi_6782975
5.计算机的利与弊英语作文带翻译,手机的利与弊带翻译英语作文(通用5篇在学习、工作、生活中,许多人都有过写作文的经历,对作文都不陌生吧,借助作文人们可以实现文化交流的目的。为了让您在写作文时更加简单方便,下面是小编精心整理的手机的利与弊带翻译英语作文(通用5篇),希望能够帮助到大家。 手机的利与弊带翻译英语作文 篇1 https://blog.csdn.net/weixin_39540178/article/details/118284328
6.高考英语作文范文(精选41篇)在生活、工作和学习中,许多人都有过写作文的经历,对作文都不陌生吧,写作文可以锻炼我们的独处习惯,让自己的心静下来,思考自己未来的方向。你知道作文怎样才能写的好吗?以下是小编为大家整理的高考英语作文范文,欢迎大家借鉴与参考,希望对大家有所帮助。 2023年高https://www.oh100.com/peixun/writing/182836.html
7.关于疫情上网课的英语作文100字疫情上网课英语作文 1 During the pandemic, we had to take online classes. It was a really new and strange experience for me at first. I still remember my first online class. I was so excited but also a bit nervous. However, things didn't go as smoothly as I expected. When I loggedhttps://wenku.baidu.com/view/ad86acf1cc84b9d528ea81c758f5f61fb6362809.html
8.英语学习计划(精选26篇)1、争取把每天听写的短文都翻译,先英译汉,再汉译英。 2、注意整理笔记。 为学习英语拟定一份学习计划,让你在计划中成功学习好英语。 英语学习计划 3 欢迎阅读初三英语学习计划,进入初三后,英语学习不仅仅只是提升理解感知能力,更需要提高应试能力去面对略显无情的考试,所以如果抱着“三天打鱼,两天晒网”的心态来https://www.unjs.com/fanwenwang/gongzuojihuafanwen/xuexijihua/20221126141505_6019804.html
9.学习翻译有什么好处如果你说让小孩学习翻译,小孩的一个疑问一定是学翻译有什么好处?对于成年人来说,如果是旧友重见,问一句你在干嘛,回答说:学翻译,以后做翻译。无论是熟悉的朋友还是交情尚浅的朋友都是免不了问一句:学翻译有什么好处? 然而有的学习翻译的人,思来想去也不知道学习翻译有什么好的,这种就是对翻译的真正热爱的人的https://www.talkingchina.com/info/14542.html
10.大学英语四级考试超详解真题+模拟最新章节但是它也有很多缺点,无法代替传统的课堂学习。 ?全文翻译? [51] 在即将到来的教育预算削减的时代,远程学习可能成为常态 。 [51] 对于那些负责教育预算的人来说,用科技交换教师的诱惑力太大了,以至于他们忽视了远程学习的缺点 。建造和维护学校设施的成本非常高,雇用教师的成本也非常高。在线课堂不需要https://m.zhangyue.com/readbook/12949083/15.html
11.FewUsefulThingstoKnowAboutMachineLearning》翻译与《A Few Useful Things to Know About Machine Learning》翻译与解读了解机器学习的一些有用的东西 key insights 重要见解 Learning = Representation + Evaluation + Optimization 学习=表示+评估+优化 It’s Generalization that Counts 重要的是概括 https://blog.51cto.com/yunyaniu/4996833
12.英语学习方法实用要克服这种情况还需要有个好的学习习惯,一个良好的英语学习习惯与我们平时学习方式有关,首先我们需要先让自己喜欢上英语,然后针对英语的学习不要放过任何与英语有关的事情,比如英语电影或者杂志书籍,通常看电影时建议看三遍,第一遍看翻译字幕,第二部不看字幕,第三遍开始看说话人的口型,渐渐你会发现英语和汉语一样https://www.ruiwen.com/ziliao/fangfa/8178281.html
13.新学期英语学习计划范文29篇此外,“开卷有益”对学习英语同样适用。读英文小故事、小短文,有助于我们掌握句子的结构。虽然我们学习英语没有母语一样的完美环境,但每天坚持大量的听,大声的读,也是非常有效的方法。看过的文章,要争取在读熟、理解的基础上背下来。 作文,不仅考察单词量,同时也考察同学们的写作能力。较强的写作能力,要靠长时间https://bxzi.com/work/xuexijihua/1419/1419404.html
14.www.scmc围绕建设国际数据信息港,南沙将着力大招商——以"网数九条"政策出台为契机,打造完整有活力的网络安全与数据服务产业生态系统,展现出强大的示范效应和领先优势。 全力引人才——聚天下英才而用之,围绕科技领军人才和创新团队、高层次复合型国际人才、海内外青年科技人才、港澳青创人才、工程技术人才全面发力,将南沙打造成http://www.scmc-xa.com/xxxr/706122.htm
15.www.lajoson.com/mokoi12墨西哥总统卡尔德隆在全国部署了5万军队打击暴力的贩毒集团。自2006年来,与毒品走私有关的暴力事件造成墨西哥约6万人死亡。 南京是本次艾弗森中国巡回赛的首站。12月1日,艾弗森飞抵上海再乘车赶往南京。经历了长途飞行和舟车劳顿,让艾弗森难免感到些许疲惫,只能在汽车上打盹。但为了尽早与热情等待自己的球迷见面,艾https://www.lajoson.com/mokoi12_16/19130.html
16.翻译笔有什么功能英语翻译笔的翻译准确吗→MAIGOO知识摘要:翻译笔是学生常用的一种学习辅助工具,主要用来充当电子词典翻译单词,除了这一功能外,翻译笔还具有文档翻译、文档摘录、语音翻译等多个功能,使用非常方便。一些家长担心翻译笔的翻译不准确,一般翻译笔都内置多部词典,还可以通过连接无线网络来获得在线翻译支持,总体来说还是比较准确的。下面一起来了解一下翻译笔有什https://m.maigoo.com/goomai/237781.html
17.英汉互译在线语音转换英汉互译在线翻译有道?学习英汉互译短语的方法 要学习英汉互译短语,有一些有效的方法可以帮助我们。首先,可以通过阅读英汉双语文本,如新闻、杂志和书籍,来积累词汇和短语。其次,可以参加线上或线下的语言交流活动,与讲英语的人互动,提高口语表达能力。此外,还可以使用在线词典和翻译工具,快速查找生词和短语的翻译。最后,不要忘记每天练习口语https://tool.a5.cn/article/show/72652.html