A. bean註解注入
如何將一個組件注冊到容器中?Bean註解一招解決-通過組件掃描和自動注入已經大大簡化了我們的開發,然而,Spring仍然不滿足於此,經過版本的迭代,現在我們已經可以完全拋棄配置文件使用Spring進行開發了,一起來看看吧。
現在我們不創建Spring的配置文件,那麼如何將一個組件注冊到容器中呢?其實,我們仍然是需要一個配置文件的,不過這個配置文件能夠以一個類的形式存在:
@Configuration用於將一個普通的Java類變為一個Spring的配置類,現在這個類就相當於之前的配置文件了,此時如果想注冊一個組件,則使用@Bean註解:
這里需要注意幾點,若有方法被@Bean註解標注,則該方法的返回值則為需要注冊的組件,而方法名則為組件在容器中的名字,當然了,這些都需要建立在代碼是寫在配置類的前提下。
如果想要修改組件的名字,可以修改方法名:
若是不想修改方法名,@Bean註解也提供了修改名字的方式:
@Bean中還有initMethod和destroyMethod屬性,它們分別用於指定組件的兩個生命周期方法:
@ComponentScan註解是用來完成組件掃描的,它需要標注在配置類上:
它的作用等價於如下配置:
我們來聊一聊關於@ComponentScan的一些高級用法,該註解是可以在掃描時指定掃描規則的,比如我們想掃描com.wwj.spring.demo這個包,但是包里有一些類、或者一些註解的內容是我們不想要注冊的,此時我們就可以指定掃描規則,如下:
在如上的配置中,excludeFilters用來配置需要排除的組件,需要藉助@Filter註解,@Filter註解中的type屬性用於指定以哪種方式排除組件,Spring一共提供了5種匹配方式:
所以如果想要具體排除某個組件,則使用ASSIGNABLE_TYPE,如果想要排除某個註解標注的所有組件,則使用ANNOTATION:
將excludeFilters切換為includeFilters,功能將變為只掃描匹配的組件,如下:
以上配置的作用是掃描com.wwj.spring.demo包下被@Service註解標注的組件,注意一點,由於Spring默認的掃描規則就是掃描所有帶@Component註解的組件,所以若是想實現只掃描某個註解,則需要添加配置useDefaultFilters=false來禁用掉Spirng默認的掃描規則。
若是想實現自定義掃描規則,也非常簡單,只需實現TypeFilter介面:
然後進行配置即可:
千萬別忘了配置useDefaultFilters=false,此時將只能掃描到名字為user的組件。
這些內容在配置文件中也是可以進行配置的,簡單舉一個例子吧:
@Scope用於指定組件的作用域,關於作用域在上一篇我們已經介紹過了,所以用法其實非常簡單:
不過多介紹,但由此可以引申出一個新的註解:@Lazy,該註解的作用是指定組件是否懶載入,默認情況下,所有組件會在容器啟動的時候被創建,而如果標注@Lazy,則組件會在第一次使用時被創建。我們可以來試驗一下,首先編寫一個User類:
編寫測試代碼:
當沒有添加@Lazy註解,控制台輸出:
當添加了@Lazy註解,控制台沒有任何輸出,只有調用了context.getBean_(_"user"_)_;User對象才會被創建。
@Conditional註解的功能是以指定的條件來注冊組件,現在我們有兩個組件:
一個是夏季水果西瓜,一個是冬季水果獼猴桃,現在有一個需求是當傳入參數為夏天時,就注冊西瓜,當傳入參數是冬天時,就注冊獼猴桃,該如何實現呢?
我們可以藉助@Conditional註解來實現,首先創建類實現Condition介面:
接下來就可以使用它們進行配置了:
此時在虛擬機參數位置填寫-Dseason=summer,Watermelon將被注冊,當參數被修改為-Dseason=winter時,Kiwi將被注冊,SpringBoot框架的底層就大量地使用到了這個註解,不過這是題外話了,我將在後續SpringBoot系統的文章中對其再度進行介紹。
我們已經知道,目前將一個組件注冊到容器中有多種方式,使用@Bean或者組件掃描都可以,然而在某些情況下,這些方式都不太方便,比如將一個第三方的組件注冊到容器中,此時我們可以藉助@Import註解:
另一種方式是使用ImportSelector,創建類實現ImportSelector介面:
將需要注冊到容器中的組件全類名寫到數組中,然後@Import註解只需要填寫這個類的信息即可:
還有一種方式是實現ImportBeanDefinitionRegistrar介面,它與第二種方式類似,與之不同的是,這種方式可以自定義組件注冊到容器中的名字:
配置如下:
需要注意的是第一種和第二種方式注冊的組件,其在容器中的名字是組件的全類名。
FactoryBean也是Spring提供的一種注冊組件的方式,不過它比較特殊,看一個例子:
這三個方法非常好理解:
那有同學提出疑問了,這種方式豈不是更加麻煩了,有必要存在嗎?當然有了,它牛就牛在你可以隨意篡改需要注冊的組件,比如:
現在看似注冊的是User對象,其實注冊的是Cat,不信我們試試:
運行結果:
若是想要獲得實現了FactoryBean介面的User對象本身,則需要在名字面前添加:
運行結果:
採用spring註解後如何注入bean問題使用註解可以寫一個配置累,然後返回實體bean,在獲取類的地方註解@autowrite或者@resource可以直接注入
@Bean註解放到方法上的時候這兩個特性你知道嗎?
1、@Bean只能存在於配置類中,當配置類中的方法存在這個註解時,這個註解會將方法的返回值放入ioc容器中去。
2、當@Bean標注的方法中有參數的時候,會去ioc容器中尋找該類型的bean作為參數注入進該方法中。當找不到同類型的bean的的時候會報錯。
spring如何用註解的方式給普通類注入bean你在PersonTest類裡面聲明一個變數,加上他的set和get方法;然後你在applicationContext.xml裡面寫
beanname="給你要注入的類起個名字例如A"class=「你要注入類的路徑」
propertyname="被注入的類裡面你剛聲明的那個變數的名字"ref="A"/property
/bean
Spring註解方式管理Bean雖然Spring以簡化開發著稱,但在學習的過程中我們發現,每新建一個類,就需要在配置文件中進行配置,並且類與類之間的關系也需要配置在標簽中,好像這並沒有簡化我們的開發,反而增加了很多繁瑣的配置。別擔心,本篇文章我們就來學習一下用註解方式來管理Bean。
組件掃描
大家不要對組件這個詞感到陌生,在Spring中,一個類可以被稱為Bean,也被稱為一個組件,回想一下,在之前,我們如何將一個組件注冊到IOC容器中呢?沒錯,我們需要寫一段配置,例如:
為了讓大家從繁瑣的配置中解脫出來,Spring提供了一種基於註解的管理方式,Spring提供了以下註解用來注冊一個組件:
1.@Component2.@Controller3.@Service4.@Repository
這四個註解都可以用來注冊一個組件,不過每個註解都有其意義,比如@Controller,它是用來注冊一個前端控制器的,我們將在SpringMVC中對其進行詳解;而@Service是用來注冊一個服務層對象的;@Repository是用來注冊一個持久層對象的。來體驗一下它們的強大吧:
我們從容器中取出所有的組件,看看注冊是否成功了:
當你運行這段測試代碼時你會發現控制台沒有任何輸出,是我們獲取的方式不對嗎?不對,其實我們還需要進行一項配置:
運行結果:
可以看到我們的組件確實注冊到Spring中了,剩下的是一些Spring內置的組件,我們無需關系。
context:component-scan標簽是用來進行組件掃描的,其中base-package屬性用於配置需要掃描的包,一般情況下我們會掃描項目的頂包,即:最外層的包,這樣所有項目中的組件都會被掃描到並注冊。
事實上,@Component、@Controller、@Service、@Repository四個註解的作用是完全一樣的,你也可以在組件上隨意地使用它們,比如:
這是完全沒有問題的,因為@Service、@Controller、@Repository註解是由@Component註解衍生出來的,但為了規范,還是建議將註解添加到指定的組件上。
自動注入
還記得Spring中的屬性注入嗎?如果不記得的話,我們來回顧一下:
若是想將一個對象屬性注入進去,我們需要進行配置:
但Spring提供了一種更加便捷的注入方式,自動注入:
只需在User類的對象屬性上添加@Autowired註解即可將Pet對象自動注入進來,而且它非常智能,我們對程序進行一些改造,首先去掉Pet類的@Component註解:
然後添加一個Dog類繼承Pet,並注冊:
來測試一下:
運行結果:
這樣Dog類就被自動注入到User中了,但如果我們又創建了一個類繼承Pet並注冊:
此時程序就會報錯:
這是Spring中比較常見的一個異常,意思是期望單個匹配的Bean:Pet,但是匹配到了兩個Bean:cat、dog。錯誤非常好理解,因為Pet的子類有兩個,所以Spring也不清楚我們到底想要哪一個Bean,所以拋出了異常。
這一問題會在Service層中出現,比如:
現在我們有一個UserService介面,並且有兩個實現類,當自動注入UserService時顯然會報錯,那麼如何解決這一問題呢?我們可以使用@Qualifier註解:
該註解的值即為需要注入的組件名,如果沒有配置組件名,則默認是類名且首字母小寫,當然了,我們也可以進行配置:
注入方式如下:
這一問題也可以使用@Primary註解解決:
當出現多個類型相同的類導致Spring無法選擇時,如果某個類標注了@Primary,Spring將優先將該組件注冊到IOC容器,不過這種方式確實不太優雅。
@Resource註解
剛才的問題其實可以通過換一個註解來解決,我們不妨試試看:
@Resource註解是JSR-250定義的註解,它和Spring沒有關系,但能夠實現和@Autowired註解相同的功能,我們先來介紹一下這兩個註解之間的區別:
?@Autowired默認按類型進行注入,若要按名稱注入,則需要配合@Qualifier註解一起使用;@Resource既支持類型注入,也支持名稱注入,默認為名稱注入?@Autowired能夠標注在構造器、方法、參數、成員變數、註解上;@Resource只能標注在類、成員變數和方法上?@Autowired是Spring提供的註解,脫離了Spring框架則無法使用;@Resource是JSR-250定義的註解,可以脫離任何框架使用
現在問題就解決了嗎?其實並沒有,當你運行測試代碼時程序仍然會拋出異常,這是因為雖然@Resource默認為名稱注入,但是在使用名稱找不到組件的情況下,會繼續使用類型注入,所以眼熟的異常就又出現了。
我們已經知道,Spring在掃描組件時會將類名且首字母小寫作為組件的名稱注入到IOC容器中,所以像這樣注入就是沒有問題的:
不過一般情況下我們不會這么寫,而是像這樣:
通過@Resource註解,我們就解決了@Autowired和@Qualifier兩個註解組合才能解決的問題,至於到底用哪個,還是看大家的使用習慣了。
@Value
可能有同學有疑問了,我知道對象類型的屬性如何注入了,那基本類型數據如何注入呢?@Value註解能夠幫助到你,使用方法如下:
不過一般情況下,我們都不會把數據這樣寫死,都會將其放到配置文件中:
此時需要藉助一個新註解@PropertySource將值注入到指定的組件中:
@Value還能夠注入操作系統屬性:
還可以注入表達式計算後的結果:
spring普通類怎麼注入beanspring在普通類中注入bean實例或注入靜態變數的bean
Spring的注入有一個問題就是普通類沒有辦法獲得Bean文件中的bean實例。這就是如果是在Web的Servlet環境中可以通過WebApplicationContextUtils,如果是普通類就不好處理了。這需
要一點設計的技巧。下面是一個靜態類使用Bean文件中實例的例子
1、如果是在配置文件中配置來注入:
publicclassUserinfoUtil
{
privateIUserInfouserInfo;
privatestaticUserinfoUtilinfo;
publicvoidsetUserInfo(IUserInfouserInfo)
{
this.userInfo=userInfo;
}
publicvoidinit()
{
info=this;
info.userInfo=this.userInfo;
}
(Stringphonenumber)
{
returninfo.userInfo.addUserLoginCnt(phonenumber);
}
}
相應的bean的配置:
相應的Bean文件的配置
beanid="userinfoUtil"class="com.huawei.aimi.webportal.service.UserinfoUtil"init-method="init"
propertyname="userInfo"ref="userInfo"/
/bean
2、用註解的方式注入:
publicclassUserinfoUtil
{
@Autowired
privateIUserInfouserInfo;
privatestaticUserinfoUtilinfo;
publicvoidsetUserInfo(IUserInfouserInfo)
{
this.userInfo=userInfo;
}
@PostConstruct
publicvoidinit()
{
info=this;
info.userInfo=this.userInfo;
}
(Stringphonenumber)
{
returninfo.userInfo.addUserLoginCnt(phonenumber);
}
}
B. 怎麼配置servlet
一、servlet的配置
servlet有兩種配置的方法
1.在web.xml文件中配置
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.hwua.servlet.LoginServlet</servlet-class></servlet><servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern></servlet-mapping>
2.在servlet中用Java註解的方式配置
使用註解配置Servlet的步驟:
1. 在Servlet類上貼@WebServlet註解2. 在web.xml文件中進行如下的配置
metadata-complete="true":表示是否忽略Servlet上面的註解
metadata-complete="false"表示是否不忽略Servlet上面的註解,預設值
二、servlet生命周期
public void init(ServletConfig config):初始化方法,在第一次請求時調用,只在最初的時候調用一次.
public void service(ServletRequest req, ServletResponse res):服務方法
public void destroy():銷毀方法
三、在web.xml文件中設置/獲取初始化參數
1.作用域當前的servlet 寫在servlet標簽中
過去參數 在init方法中
2.上下文參數 寫在web-app標簽中
獲取參數 在init方法中
四、設置servlet啟動的時間
默認情況下servlet是在第一次被請求時啟動的
通過在web.xml文件中設置
注意:
五、常用方法:
六、獲取請求參數的方法:
C. 怎麼使用postconstruct註解讀取配置表
使用postconstruct註解讀取配置表方法如下。
1、通過PostConstruct註解能夠通過一種更友好的方式將配置進行讀取。
2、伺服器載入Servlet-servlet構造函數的載入。
3、創建service時發生的事件。
4、PostConstruct註解把config配置讀取到bean變成靜態方法。
5、註解配置從Spring開始就可以使用註解來配置依賴注入。