javascript
记下来 Spring 装配 Bean 的三种方式
ps:拿筆記一下,面試可能會考。依賴注入DI和面向切面編程AOP是Spring框架最核心的部分。這次主要是總結依賴注入的bean的裝配方式。
前言
什么是依賴注入呢?也可以稱為控制反轉,簡單的來說,一般完成稍微復雜的業務邏輯,可能需要多個類,會出現有些類要引用其他類的實例,也可以稱為依賴其他類。傳統的方法就是直接引用那個類對象作為自己的一個屬性,但如果我們每次創建這個類的對象時,都會創建依賴的類的對象,還有如果那個類將來可能不用了,還需要到這個類去刪除這個對象,那破壞了代碼的復用性和導致高度耦合!
依賴注入的出現可以很好地解決這個問題,依賴注入就是由系統負責協調類的依賴對象的創建,我們無需自己去顯示的創建依賴對象,而是由系統給我們注入這個對象,系統控制了這個對象的創建,也稱為控制反轉。
Spring給我們注入對象有三種方式:
-
隱式的bean掃描發現機制和自動裝配
-
在java中進行顯示配置
-
在XML中進行顯示配置
第一種:spring從兩個角度實現自動化裝配:組件掃描和自動裝配。
當對一個類標注@Component注解時,表明該類會作為組件類,spring將為這個類創建bean。當在應用文中引用這個bean,spring會自動掃描事先指定的包查找這個 bean。但spring默認是不啟用組件掃描的,可以在XML中配置加上。還有一種方法:在新建一個配置類,類中可以什么不用寫,在配置類上加上@ComponentScan注解,spring會自動掃描改配置類所在的包,一般應該傾向xml配置。下面是一個bbs論壇系統用戶發帖的功能小例子:
package?bbs.dao; @Component public?interface?Postdao?{/**用戶發帖?,post表添加帖子信息*/public?int?addpost(@Param("title")?String?title,@Param("content")?String?content,@Param("userid")?int?userid); }package?bbs.dao; @Component public?interface?Userdao?{/**?用戶發帖后,user表將用戶發帖數加一*/public?int?addpost(int?userid); }再在bbs.service包中創建一個postservice接口及其實現類,依賴Postdao和Userdao。
package?bbs.service; public?interface?PostService?{/*用戶發帖后,先添加帖子信息再更新用戶發帖數量*/public?void?addpost(String?title,String?content,int?userid); }package?bbs.service; @Component public?class?PostserviceImpl?implements?PostService?{private?Postdao?postdao;private?Userdao?userdao;//????@Autowired //????public?void?setPostdao(Postdao?postdao) //????{ //????????this.postdao=postdao; //????} // //????@Autowired //????public?void?setUserdao(Userdao?userdao) //????{ //????????this.userdao=userdao; //????}@Autowiredpublic?PostserviceImpl(Postdao?postdao,Userdao?userdao){this.userdao=userdao;this.postdao=postdao;}public?void?addpost(String?title,?String?content,?int?userid)?{int?i=postdao.addpost(title,?content,?userid);int?j=userdao.addpost(userid);if(i==1&j==1)System.out.println("發帖成功");elseSystem.out.println("發帖失敗");} }@Component在接口實現上注解就可以,但發現在userdao、postdao接口也加上了,其實可以去掉,因為我采用mybatis在xml中配置數據庫的操作,動態實現dao接口。等下會提到。上面代碼出現的@Autowired注解實現bean自動裝配,會在spring應用上下文中的組件類尋找需求的bean。一般有兩種裝配方式:構造器和Setter方法(其他方法名也行,只要能夠使注入的bean成為這個類的屬性就行)
也可能出現spring沒有查找到匹配的bean會拋出異常,在@Autowired加上required=false,如果沒有匹配的bean時,spring會使這個bean處于未裝配的狀態,沒有裝配成功。還有可能會出現相同名字的bean有很多個,會產生歧義,一般在組件類上添加注解@Qualifier()括號寫這個bean的id,在注入時也加上@Qualifier(),寫上bean的id。像下面:
@Component @Qualifier("postdao") public?interface?Postdao{ .?.?.?. }@Component @Qualifier("userdao") public?interface?Userdao{ .?.?.?. }@Autowired @Qualifier("usedao") public?void?setUserdao(Userdao?userdao) {.?.?. }@Autowired @Qualifier("postdao") public?void?setUserdao(Postdao?postdao) {.?.?. }由于java不允許在同一個條目上重復出現相同類型的多個注解,所有注入采用set方式。但是其實可以創建自定義的限定符注解。這里就不介紹啦。
第二種:通過java代碼裝配bean
一般通過組件掃描和自動裝配方式就比較方便了,但如果由于需求我們要使用第三方的庫的類,在這種情況沒有辦法到第三方庫中去給類加注解,就不能使用第一種方法了。這時得采用顯示裝配,可以采用java代碼或xml顯示裝配bean。使用java代碼,先新建一個配置類JavaConfig,里面都是配置所需的bean,不應該有業務邏輯代碼,所以單獨建一個類。
@Configuration @ContextConfiguration(locations?=?{"classpath:spring/spring-dao.xml","classpath:scan.xml"}) public?class?bbsConfig{private?Postdao?postdao;private?Userdao?userdao;@Bean(name="postservice")public?PostService?getPost(){return?new?PostserviceImpl(postdao,userdao);} }在對PostService的bean注入時,同時又依賴了兩個bean,postdao和userdao。直接引用beanID就可以,spring會自動地從容器中獲取這些bean,只要他們的配置是正確的就行。這個例子中userdao、postdao是Mybatis配置自動掃描將dao接口生成代理注入到spring的,其實也算是xml裝配bean??蓞⒖歼@篇文章,寫的挺清楚的。 https://bijian1013.iteye.com/blog/2318860
這里如果再聲明一個bean,返回的仍是postserviceImpl對象,和之前的那個bean完全一樣,是同一個實例。一般spring@bean如果是同一個beanID,默認返回的是一個單例bean,注入的是同一個實例。如果修改其中一個會都改變的。
不過在這里要注意進行測試時,由于spring的單元測試和springIoc容器是完全獨立的,postdao和userdao注入檢測時是使用locations加載xml文件,而postservice使用classes加載config類的,但是兩個不能同時混用在@ContextConfiguration中。所以非要都測試的話,就分開測試吧。
第三種:在XML中裝配bean
<?xml?version="1.0"?encoding="UTF-8"??> <beans?xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context"><import?resource="spring/spring-dao.xml"/><bean?id="postservice"?class="com.bbs.service.impl.PostserviceImpl"><constructor-arg?ref="postdao"/><constructor-arg?ref="userdao"/></bean> </beans>配置postservice的bean時需要引入兩個bean,postdao和userdao,放到constructor-arg的標簽中,ref指的是依賴的bean的ID。如果是在javaConfig中配置的,就寫@Bean的內容。如果是@Component就寫@Qualifier的內容。這里是引入的是動態實現的dao接口的bean,是在spring-dao.xml中配置的,引入這個配置文件就可以自動獲得beanID。
混合使用三種裝配:
在類上可以使用 @import(bbsConfig.class)組合其他java注解
在類上使用 @importResource("classpath:spring-dao.xml")組合其他xml注解
在類上可以使用@ContenxtConfiguration包含class或者xml
在xml中可以用引入xml注解,也可以使用引入java注解
總結
以上是生活随笔為你收集整理的记下来 Spring 装配 Bean 的三种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对话行癫:解密阿里云顶层设计和底层逻辑
- 下一篇: Nginx 搭建图片服务器