javascript
使用Spring MVC时的常见错误
當(dāng)我大約10年前開始我的職業(yè)生涯時,Struts MVC就是市場上的常態(tài)。 但是,多年來,我觀察到Spring MVC逐漸流行起來。 鑒于Spring MVC與Spring容器的無縫集成以及它提供的靈活性和可擴(kuò)展性,這對我來說并不奇怪。
從到目前為止的Spring旅程中,我通常會看到人們在配置Spring框架時犯了一些常見的錯誤。 與人們?nèi)匀皇褂肧truts框架的時間相比,這種情況發(fā)生的頻率更高。 我想這是靈活性和可用性之間的權(quán)衡。 另外,Spring文檔中有很多示例,但缺乏解釋。 為了填補這一空白,本文將嘗試闡述和解釋我經(jīng)常看到的3個常見問題。
在Servlet上下文定義文件中聲明bean
因此,我們每個人都知道Spring使用ContextLoaderListener加載Spring應(yīng)用程序上下文。 不過,當(dāng)宣布
DispatcherServlet ,我們需要創(chuàng)建名稱為“ $ {servlet.name} -context.xml”的servlet上下文定義文件。 有沒有想過為什么?
應(yīng)用程序上下文層次結(jié)構(gòu)
并非所有開發(fā)人員都知道Spring應(yīng)用程序上下文具有層次結(jié)構(gòu)。 讓我們看一下這種方法:
org.springframework.context.ApplicationContext.getParent()
它告訴我們Spring Application Context具有父級。 那么,這個父母干什么呢?
如果下載源代碼并進(jìn)行快速引用搜索,則應(yīng)該發(fā)現(xiàn)Spring Application Context將parent作為其擴(kuò)展名。 如果您不介意閱讀代碼,請讓我向您展示方法BeanFactoryUtils.beansOfTypeIn includedAncestors()中的用法示例:
if (lbf instanceof HierarchicalBeanFactory) {HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {Map parentResult = beansOfTypeIncludingAncestors((ListableBeanFactory) hbf.getParentBeanFactory(), type);...} } return result; }如果遍歷整個方法,您將發(fā)現(xiàn)在搜索父上下文之前,Spring Application Context會掃描以在內(nèi)部上下文中查找bean。 通過這種策略,Spring Application Context將有效地進(jìn)行反向廣度優(yōu)先搜索以查找bean。
ContextLoaderListener
這是每個開發(fā)人員都應(yīng)該知道的眾所周知的類。 它有助于從預(yù)定義的上下文定義文件中加載Spring應(yīng)用程序上下文。 由于實現(xiàn)了ServletContextListener ,因此將在加載Web應(yīng)用程序后立即加載Spring應(yīng)用程序上下文。 當(dāng)加載包含帶有@PostContruct批注或批處理作業(yè)的bean的Spring容器時,這帶來了無可爭議的好處。
相反,在初始化servlet之前,不會構(gòu)造servlet上下文定義文件中的任何bean定義。 何時初始化Servlet? 這是不確定的。 在最壞的情況下,您可能需要等到用戶對servlet映射URL進(jìn)行第一次點擊才能加載spring上下文。
根據(jù)以上信息,您應(yīng)該在哪里聲明所有珍貴的豆子? 我覺得這樣做的最佳位置是ContextLoaderListener加載的上下文定義文件,而沒有其他地方。 這里的竅門是將ApplicationContext作為servlet屬性存儲在鍵org.springframework.web.context.WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE下
稍后, DispatcherServlet將從ServletContext加載此上下文,并將其分配為父應(yīng)用程序上下文。
由于這種行為,強烈建議創(chuàng)建一個空的servlet應(yīng)用程序上下文定義文件,并在父上下文中定義您的bean。 這將有助于避免在加載Web應(yīng)用程序時重復(fù)創(chuàng)建Bean,并確保立即執(zhí)行批處理作業(yè)。
從理論上講,在servlet應(yīng)用程序上下文定義文件中定義bean會使該bean唯一且僅對該servlet可見。 但是,在使用Spring的8年中,除了定義Web Service端點之外,我?guī)缀鯖]有發(fā)現(xiàn)此功能的任何用途。
在
這是一個小錯誤,但是如果您不注意它,它將引起您的注意。 Log4jConfigListener是我在-Dlog4j.configuration首選的解決方案,我們可以控制的log4j加載不改變服務(wù)器的引導(dǎo)過程。
顯然,這應(yīng)該是在web.xml中聲明的第一個偵聽器。 否則,您浪費所有的時間來聲明正確的日志記錄配置。
由于對Bean的探索管理不善而復(fù)制了Bean
在Spring的早期,開發(fā)人員在xml文件上打字的時間比Java類花費的時間更多。 對于每個新bean,我們需要自己聲明和連接依賴項,這是干凈,整潔但非常痛苦的。 毫無疑問,Spring框架的更高版本向更高的可用性發(fā)展。 如今,開發(fā)人員可能只需要聲明事務(wù)管理器,數(shù)據(jù)源,屬性源,Web服務(wù)端點,其余的就可以進(jìn)行組件掃描和自動裝配。
我喜歡這些新功能,但是這種強大的力量需要承擔(dān)巨大的責(zé)任。 否則,事情會很快變得混亂。 XML文件中的組件掃描和bean聲明是完全獨立的。 因此,如果對bean進(jìn)行注釋以進(jìn)行組件掃描并手動進(jìn)行聲明,則在bean容器中完全可能具有相同類的相同bean。 幸運的是,這種錯誤應(yīng)該只發(fā)生在初學(xué)者身上。
當(dāng)我們需要將一些嵌入式組件集成到最終產(chǎn)品中時,情況變得更加復(fù)雜。 然后,我們確實需要一種策略來避免重復(fù)的bean聲明。
上圖顯示了我們?nèi)粘I钪杏龅降姆N種現(xiàn)實問題。 大多數(shù)情況下,系統(tǒng)是由多個組件組成的,通常,一個組件可為多個產(chǎn)品提供服務(wù)。 每個應(yīng)用程序和組件都有自己的bean。 在這種情況下,最好的聲明方式是避免重復(fù)的bean聲明?
這是我建議的策略:
- 確保每個組件都必須以專用的軟件包名稱開頭。 當(dāng)我們需要進(jìn)行組件掃描時,它使我們的工作變得更輕松。
- 不要指示開發(fā)組件的團(tuán)隊采用在組件本身中聲明Bean的方法(注釋與xml聲明)。 開發(fā)人員負(fù)責(zé)將組件打包到最終產(chǎn)品中,以確保沒有重復(fù)的bean聲明。
- 如果組件中包含上下文定義文件,請給它一個包,而不是放在classpath的根目錄中。 最好給它起一個特定的名字。 例如, src / main / resources / spring-core / spring-core-context.xml比src / main / resource / application-context.xml更好。 想象一下,如果在相同的程序包中打包幾個包含相同文件application-context.xml的組件,那該怎么辦!
- 如果您已經(jīng)在一個上下文文件中聲明了Bean,則不要為組件掃描提供任何注釋( @ Component, @ Service或@Repository )。
- 將特定于環(huán)境的bean(例如data-source , property-source)拆分到一個單獨的文件中并重用。
- 不要在常規(guī)包裝上進(jìn)行組件掃描。 例如,與掃描org.springframework包相比,如果我們掃描幾個子包(例如org.springframework.core , org.springframework.context , org.springframework.ui ,…), 則更易于管理。
結(jié)論
希望以上技巧對日常使用很有幫助。 如有任何疑問或任何其他想法,請發(fā)送反饋以提供幫助。
翻譯自: https://www.javacodegeeks.com/2014/07/common-mistakes-when-using-spring-mvc.html
總結(jié)
以上是生活随笔為你收集整理的使用Spring MVC时的常见错误的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果手机总是耳机模式取消不了怎么办
- 下一篇: 华为手机YOYO在哪里