前言
這段時間在學習spring,依賴注入di和面向切面編程aop是spring框架最核心的部分。這次主要是總結依賴注入的bean的裝配方式。
什么是依賴注入呢?也可以稱為控制反轉,簡單的來說,一般完成稍微復雜的業務邏輯,可能需要多個類,會出現有些類要引用其他類的實例,也可以稱為依賴其他類。傳統的方法就是直接引用那個類對象作為自己的一個屬性,但如果我們每次創建這個類的對象時,都會創建依賴的類的對象,還有如果那個類將來可能不用了,還需要到這個類去刪除這個對象,那破壞了代碼的復用性和導致高度耦合!
依賴注入的出現可以很好地解決這個問題,依賴注入就是由系統負責協調類的依賴對象的創建,我們無需自己去顯示的創建依賴對象,而是由系統給我們注入這個對象,系統控制了這個對象的創建,也稱為控制反轉。
spring給我們注入對象有三種方式:
- 隱式的bean掃描發現機制和自動裝配
- 在java中進行顯示配置
- 在xml中進行顯示配置
第一種:
spring從兩個角度實現自動化裝配:組件掃描和自動裝配。
當對一個類標注@component注解時,表明該類會作為組件類,spring將為這個類創建bean。當在應用文中引用這個bean,spring會自動掃描事先指定的包查找這個 bean。但spring默認是不啟用組件掃描的,可以在xml中配置加上<context:component-scan base-package="xx"/>
。還有一種方法:在新建一個配置類,類中可以什么不用寫,在配置類上加上@componentscan注解,spring會自動掃描改配置類所在的包,一般應該傾向xml配置。下面是一個bbs論壇系統用戶發帖的功能小例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
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; // } @autowired public 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( "發帖成功" ); else system.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。像下面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@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,不應該有業務邏輯代碼,所以單獨建一個類。
1
2
3
4
5
6
7
8
9
10
|
@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。可參考這篇文章,寫的挺清楚的。
這里如果再聲明一個bean,返回的仍是postserviceimpl對象,和之前的那個bean完全一樣,是同一個實例。一般spring@bean如果是同一個beanid,默認返回的是一個單例bean,注入的是同一個實例。如果修改其中一個會都改變的。
不過在這里要注意進行測試時,由于spring的單元測試和springioc容器是完全獨立的,postdao和userdao注入檢測時是使用locations加載xml文件,而postservice使用classes加載config類的,但是兩個不能同時混用在@contextconfiguration中。所以非要都測試的話,就分開測試吧。
第三種:
在xml中裝配bean
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?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/beans http: //www.springframework.org/schema/beans/spring-beans.xsd http: //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。
混合使用三種裝配:
1.在類上可以使用@ import(bbsconfig.class)
組合其他java注解
2.在類上使用@ imortresource("classpath:spring-dao.xml")
組合其他xml注解
3.在類上可以使用@contenxtconfiguration
包含class或者xml
4.在xml中可以用<import resource="spring-dao.xml">
引入xml注解,也可以使用<bean class="com.bbs.dao.userdao">
引入java注解
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。
原文鏈接:https://www.cnblogs.com/maxshare/p/10467761.html