??該學(xué)習(xí)筆記是《尚學(xué)堂spring視頻教程》的學(xué)習(xí)筆記第二部分灵妨。
6幻枉、依賴注入
依賴注入(dependency injection)
依賴:bean 對(duì)象依賴于容器來(lái)進(jìn)行創(chuàng)建术羔。
注入:bean對(duì)象依賴的資源由容器來(lái)設(shè)置和裝配苹支。
Spring注入分為兩種,一種是構(gòu)造器創(chuàng)建對(duì)象——見(jiàn)Spring框架-學(xué)習(xí)筆記1中4宣渗、Spring IoC創(chuàng)建對(duì)象的方式
。
??除此以外梨州,還有setter注入痕囱。要求被注入的屬性必須要有set方法。
a)常量注入:
首先仍然是先建立一個(gè)Student對(duì)象暴匠。
下面的beans.xml就是實(shí)現(xiàn)常量注入鞍恢。
接著就可以在Test文件中獲取到對(duì)象了。
b)bean注入:
創(chuàng)建一個(gè)Address類每窖,并且為其創(chuàng)建get和set方法帮掉。
并且在上面的Student類中新增一個(gè)addr屬性,以及一個(gè)setAddr()方法窒典。
在配置文件中通過(guò)ref引用到addr這個(gè)對(duì)象蟆炊。其實(shí)這在IoC的部分已經(jīng)講過(guò)了。
c)數(shù)組注入:
假如繼續(xù)在Student類中添加一個(gè)屬性String[] books
崇败,在配置文件中為其設(shè)置屬性值:
除此以外盅称,還有List、Map后室、Set注入缩膝。還有Null注入。
d)properties注入:
還提及
P命名空間注入
和C命名空間注入
岸霹。需要在頭文件中加入:
7疾层、bean 的作用域
bean的作用域跟scope屬性有關(guān)。
singleton
單列贡避,表示整個(gè)容器中只有一個(gè)對(duì)象實(shí)例痛黎。也是默認(rèn)值。
prototype
原型刮吧,表示每次獲取bean都產(chǎn)生一個(gè)新的對(duì)象湖饱。
request
表示每次請(qǐng)求時(shí)創(chuàng)建一個(gè)新的對(duì)象。
session
表示在會(huì)話的范圍內(nèi)時(shí)產(chǎn)生一個(gè)對(duì)象杀捻。
global session
只在portlet下有用井厌,表示是application。
application
表示在一個(gè)應(yīng)用范圍內(nèi)只有一個(gè)對(duì)象。
8仅仆、bean 的自動(dòng)裝配
自動(dòng)裝配可以簡(jiǎn)化Spring的一些配置器赞。
不推薦使用自動(dòng)裝配。容易產(chǎn)生一些問(wèn)題墓拜。
??這里使用了
autowire
就是表示自動(dòng)裝配港柜。這里的byName表示根據(jù)相應(yīng)的名稱去查找bean,如果找到對(duì)應(yīng)名稱(參考的是set方法名而非屬性名)的bean就進(jìn)行裝配咳榜。這樣就可以不通過(guò)id進(jìn)行查找夏醉。??除了使用
byName
還可以byType
,但是這樣的話同種類型的bean就只能有一個(gè)而不能重復(fù)贿衍,否則會(huì)發(fā)生錯(cuò)誤授舟,所以不建議使用byType方法自動(dòng)裝配。
9贸辈、代理的講解
??假如有
Client
释树、Host
和Proxy
三種角色,其中Client表示租客擎淤,Host表示房東奢啥,Proxy表示代理(中介)。那么Host具有rent()方法嘴拢,表明房東可以出租房屋桩盲。而Proxy的rent()方法其本質(zhì)是觸發(fā)了Host的rent()方法。??為了保持方法的一致席吴,可以讓Host和Proxy都繼承于Rent接口赌结。而Rent接口中定義了rent()方法。
??如果需要調(diào)用Proxy類的rent()方法孝冒,那么就需要有一個(gè)host對(duì)象柬姚。而這個(gè)host對(duì)象怎么傳遞到proxy對(duì)象呢。
??如上所示庄涡,可以通過(guò)構(gòu)造方法
Proxy(Host host)
和setHost(Host host)
兩種方法量承。那么對(duì)于proxy而言,就可以比較方便地實(shí)現(xiàn)租房功能了穴店。??并且中介還有自己要實(shí)現(xiàn)的功能撕捍,例如這里還定義了
seehouse()
和fare()
兩個(gè)功能。
對(duì)客戶來(lái)說(shuō)泣洞,房東是不透明的忧风。
靜態(tài)代理的角色分析:
1、抽象角色(AbstractSubject
)——接口或者抽象類球凰。
2阀蒂、真實(shí)角色(RealSubject
)——被代理的角色该窗。
3、代理角色(Proxy
)——代理真實(shí)角色蚤霞。一般還會(huì)做一些附屬的操作。
- 優(yōu)點(diǎn):
??真實(shí)角色處理的業(yè)務(wù)更加純粹义钉,不用關(guān)注公共的業(yè)務(wù)昧绣。公共的業(yè)務(wù)由代理來(lái)完成,實(shí)現(xiàn)了業(yè)務(wù)的分工捶闸。
公共業(yè)務(wù)發(fā)生改變(拓展)時(shí)夜畴,變得更加集中和方便。 - 缺點(diǎn):
??每一個(gè)類都需要一個(gè)代理類删壮。工作量變大贪绘。而使用動(dòng)態(tài)代理可以實(shí)現(xiàn)一個(gè)代理代理多個(gè)類。接下來(lái)關(guān)鍵看動(dòng)態(tài)代理如何做到的央碟。和靜態(tài)代理有什么區(qū)別税灌。
10、動(dòng)態(tài)代理
??動(dòng)態(tài)代理的代理類是動(dòng)態(tài)生成的亿虽,不需要提前寫好菱涤。動(dòng)態(tài)代理分為兩類,一類是基于基于接口(jdk
)的動(dòng)態(tài)代理洛勉,一類是基于類(cglib
)的動(dòng)態(tài)代理≌掣眩現(xiàn)在使用javassist
來(lái)生成動(dòng)態(tài)代理。
??jdk動(dòng)態(tài)代理:proxy
類和invocationHandler
接口收毫。
動(dòng)態(tài)生成代理類攻走。和靜態(tài)代理相同之處:同樣需要接口Rent和真實(shí)對(duì)象Host。然后創(chuàng)建一個(gè)類ProxyInovationHanlder
來(lái)實(shí)現(xiàn)InvocationHandler
接口此再。
??在靜態(tài)代理類中昔搂,只有一個(gè)接口Rent
。而這里多了一個(gè)InvocationHandler
引润。而且在靜態(tài)代理中Proxy和Host都要實(shí)現(xiàn)Rent接口巩趁,但是這里ProxyInovationHanlder
并不需要實(shí)現(xiàn)Rent接口,只需要實(shí)現(xiàn)InvocationHandler
接口淳附。
??上面也分析過(guò)议慰,之所以靜態(tài)代理實(shí)現(xiàn)同一個(gè)接口,是因?yàn)?strong>可以保證方法名的一致(都是rent()
方法)奴曙。
??這里代理中也不存在具體的rent()方法了别凹。而是多了一個(gè)invoke(Object proxy,Method method,Object[] args)
方法。可以預(yù)期到這個(gè)方法應(yīng)該是用于調(diào)用Host中的rent()方法的洽糟。但是具體而言是如何實(shí)現(xiàn)的呢炉菲。
在
@override
前面還需要引入rent對(duì)象堕战,然后將method.invoke(obj.args)
中的obj
更改為rent
。最后結(jié)果如下所示:
這樣在Client中通過(guò):
ProxyInovationHandler pih = new ProxyInovationHandler();
pih.setRent(host);
就可以將具體的Host中的方法傳遞到代理中拍霜。
@override
后面的內(nèi)容也可以進(jìn)行一點(diǎn)修改嘱丢,將method.invoke(rent,args)
的結(jié)果賦值到變量result
。
在該類中祠饺,除了setRent()以外越驻,還可以添加一個(gè)getProxy()
方法:
最終在Client類中:
??可以看見(jiàn)最后的rent()方法還是通過(guò)proxy對(duì)象來(lái)調(diào)用,這和靜態(tài)代理的相同道偷。但是這個(gè)proxy對(duì)象是通過(guò)pih調(diào)用getProxy()生成的缀旁。
??如果將上面的
ProxyInovationHandler
中的private Rent rent;
和setRent(Rent rent)
分別替換為private Object object;
和setObject(Object object);
,那么這個(gè)代理類就可以代理多個(gè)不同的類,當(dāng)然Client中的代碼也需要進(jìn)行修改勺鸦。??一個(gè)動(dòng)態(tài)代理可以代理某一類業(yè)務(wù)并巍,可以代理多個(gè)類。而靜態(tài)代理的話每一個(gè)類都需要一個(gè)代理類换途。