?? 15. spring note.txt
字號:
day1
什么是Spring?
開源、輕量級
Spring 特征:
1.B/S 和 C/S,使用資源小
2.對象間的關(guān)系松,高內(nèi)聚,低耦合
IOC --- Inverse of control
使得業(yè)務(wù)組件都處在框架的管理之下
框架可以管理組件的創(chuàng)建和依賴關(guān)系
框架可以提供可以配置的服務(wù)
3.通過AOP技術(shù)將業(yè)務(wù)與非業(yè)務(wù)分離
AOP --- Aspect Oreinted Programming
在不修改組件的前提下,為組件提供擴(kuò)展的服務(wù)
4.Spring容器管理整個JavaBean生命周期
簡化對j2ee技術(shù)的使用
5.與Hibernate、Struts一樣是個框架
(類集合) (框架提供)
6.Spring是一個全方位的框架
SpringMVC 類似 Struts
Spring框架在多層開發(fā)中位于那一層?或哪幾層?
框架簡化開發(fā)過程,提供公共服務(wù)和便利的工具
1.業(yè)務(wù)邏輯層 (Ioc *AoP) 最擅長的一層
2.表現(xiàn)層 (SpringMVC Web B/S都有)
3.數(shù)據(jù)持久層 (SpringDAO ORM)
什么是IoC:
1.IOC --- Inverse of control (控制反轉(zhuǎn))
A主動創(chuàng)建B的實(shí)例:正向控制
過去:拉模型
組件決定自己依賴的對象的創(chuàng)建
接口沒有在松散耦合中起到太大作用
IOC:推模型,也叫做依賴注入
采用工廠模式管理應(yīng)用組件的創(chuàng)建,管理組件的依賴關(guān)系
用接口表達(dá)組件間的依賴
依賴注入的方式
1)構(gòu)造方法注入
2)set 方法注入
2.Spring IoC 容器先創(chuàng)建B的實(shí)例,再把B的實(shí)例注入A中
3.執(zhí)行過程:
1)執(zhí)行 BeanFactory 或 ApplicationContext 時,解析 xml 文件
2)通過反射,執(zhí)行 JavaBean 的空參構(gòu)造方法,創(chuàng)建實(shí)例
3)調(diào)用 JavaBean 的 set方法,將xml的信息注入到這 JavaBean 實(shí)例
或者執(zhí)行滿參構(gòu)造方法創(chuàng)建實(shí)例,同時注入 xml 的信息
spring 框架的7個組成部分
1.BeanFactory -- (低級容器,接口)使用工廠模式實(shí)例化組件,裝配組件
XmlBeanFactory(實(shí)現(xiàn)類)
2.ApplicationContext (高級容器,接口)--- bean factory 增加事件發(fā)布,增加了國際化,資源訪問等的支持
ClassPathXmlApplicationContext(實(shí)現(xiàn)類)
3.aop -- 提供一種基于聲明方式的AOP
4.dao 支持--簡化jdbc,聲明的事務(wù)
5.orm 支持-- 簡化使用 Hibernate ,toplink 等持久化框架,方便的事務(wù)管理
6.web 支持-- 在 web 應(yīng)用中使用 spring 框架的相關(guān)支持,協(xié)調(diào)表現(xiàn)層和業(yè)務(wù)層的關(guān)系
7.web mvc--- 獨(dú)立的 web mvc 框架
spring 是全方位的框架
spring 的組成部分相對獨(dú)立,可選擇的使用
作業(yè):
用戶注冊頁面
要求: Servlet + Spring + JDBC + MySQL
1.判斷用戶名是否已注冊(保證用戶名唯一性)
2.采用B/S架構(gòu),使用IoC功能,完成JavaBean的注入。
在JavaBean不要使用 new 方式創(chuàng)建對象。
3.連接數(shù)據(jù)庫時的 driver ,配置在 xml 文件中。
day2
二、控制反轉(zhuǎn)(inverse of control IOC )
2、Bean 工廠(BeanFactory)的功能和配置
ClassPathResource
在類路徑下查找資源
另有 FileSystemResource
XmlBeanFactory
讀取 xml 文件中的配置信息
生產(chǎn)bean
解決bean 依賴
* Bean 的創(chuàng)建
spring 可調(diào)用bean的構(gòu)造方法,或通過工廠方法生產(chǎn) bean 對象
1.利用 bean 的構(gòu)造方法創(chuàng)建bean
無參的構(gòu)造方法
<bean id="refName" class="foopak.FooClass">
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
有參的構(gòu)造方法,需指明構(gòu)造方法的參數(shù)列表,通過:
<bean id="refName" class="foopak.FooClass">
<construct-arg><value>arg0</value></construct-arg>
<construct-arg><value>arg1</value></construct-arg>
</bean>
表明調(diào)用了兩個參數(shù)的構(gòu)造方法
2.通過工廠方法獲得 bean 對象
bean 沒有公共的構(gòu)造方法,需通過工廠類或工廠實(shí)例來創(chuàng)建
分為靜態(tài)工廠和實(shí)例工廠方法兩種情況
靜態(tài)工廠方法:
class 指明工廠類,factory-method 指明工廠方法
如: Connection con=DriverManager.getConnection(url,user,pwd);
對應(yīng)的配置:
<bean id="con" class="java.sql.DriverManager" factory-method="getConnection">
<construct-arg><value>jdbc:mysql://localhost/test</value></construct-arg>
<construct-arg><value>zhangsan</value></construct-arg>
<construct-arg><value>pwd</value></construct-arg>
</bean>
工廠方法參數(shù)和構(gòu)造方法參數(shù)設(shè)置的形式相同
實(shí)例工廠方法:
要先創(chuàng)建工廠實(shí)例,然后再由工廠實(shí)例創(chuàng)建產(chǎn)品
如: Statement stmt = con.createStatement();
con 對象是工廠
stmt 對象是產(chǎn)品
配置為:
<bean id="con" class="java.sql.DriverManager" factory-method="getConnection">
……
</bean>
<bean id="stmt" factory-bean="con" factory-method="createStatement"/>
單例 bean
bean 工廠生產(chǎn)bean 缺省都是單例的
scope 屬性
scope="singleton|prototype|request|session"
后兩者用于web應(yīng)用中
通過注入解決bean的依賴
1 依賴注入的兩種方式
1) set 注入
<property name="xxxYy">
……
</property>
相當(dāng)于 setXxxYy(val);
2) 構(gòu)造方法注入
<construtor-arg>……</construtor-arg>
spring 直接利用了 bean 的 set 或 構(gòu)造方法
避免了使用接口注入的侵入性
2 依賴的目標(biāo)類型分成三種形式:
1) 基本類型+String
<value>data</value>
類型自動轉(zhuǎn)化
2) 對其他bean 的引用
<ref bean="target"/>
3) 集合類型
list
props
set
map
3 讓spring 自動裝配bean,解決依賴
autowire 屬性指明自動裝配的依據(jù):
byName--- id=property
byType--- 屬性的類型=當(dāng)前工廠中bean的類型
constructor--構(gòu)造方法參數(shù)的類型=當(dāng)前工廠中bean的類型
autodetect-- constructor ---> byType
autowire-candidate 屬性
指明是否作為 autowire 的候選對象
解決多個候選對象的沖突
true ---
false ---
4 讓容器檢測 bean 所有的依賴是否都已經(jīng)滿足
某個 bean 需要設(shè)置好所有屬性
防止遺漏裝配,在運(yùn)行后出現(xiàn)莫名奇妙的情況
dependency-check 屬性指明應(yīng)檢查的目標(biāo)類型
simple -- 基本類型+字符串+集合
objects --- 對其他bean的依賴
all
none -- 默認(rèn)值
管理 Bean 生命周期
生命周期
構(gòu)造
set
回調(diào)初始化方法
getBean 返回
回調(diào)方法:
兩個屬性指明
init-method
destroy-method
或?qū)崿F(xiàn)兩個接口:
InitiallizingBean
DisposableBean
重用 bean 定義
parent -- 繼承 bean 定義
bean 之間不一定有繼承關(guān)系
abstract --- 只作為模板,不可以被實(shí)例化
補(bǔ)充:
name
id=""
name="/myBean"
name="a b c"
延遲加載bean
bean 的加載時機(jī)
預(yù)先加載
構(gòu)造 bean 工廠時實(shí)例化所有bean
延遲加載
getBean 時構(gòu)造
先構(gòu)造依賴的bean
BeanFactory 總是延遲加載的
ApplicationContext
BeanFactory 的擴(kuò)展
預(yù)先加載 單例 bean
lazy-init (true|false)
3、ApplicationContext
BeanFactory 的擴(kuò)展,為應(yīng)用提供國際化和事件框架的支持
1)I18N(國際化)
ApplicationContext 可以讀取國際化的消息文件
getMessage();
實(shí)施:
1)注冊消息源
<bean id="messageSource"
class="ResourceBundelMessageSource">
<property name="basename">
<value>MessageResource</value>
</property>
</bean>
bean 的id 必須是"messageSource"
2)讀取消息
ApplicationContext 的方法:
getMessage(String key,String[] args,Locale l);
key - 消息的key
args- 插入到消息中的參數(shù)
l - 區(qū)域
Locale 語言和區(qū)域代碼的封裝對象
locale=new Local("zh","CN");
local=Locale.getDefault();
思考:工廠管理的組件怎樣使用獲得國際化消息
注意:因為AppicationContext包含了BeanFactory所有的功能,所以優(yōu)先選擇 ApplicationContext
2)事件框架
提供了一個觀察者模式的框架,快速實(shí)現(xiàn)組件間的事件通知
實(shí)施:
1 所有想得到通知的對象都實(shí)現(xiàn)ApplicationListener
2 事件源發(fā)出事件:applicationContext.publishEvent(event);
自定義事件類
什么時候需要?
被觀察者在需要傳輸數(shù)據(jù)給觀察者時
怎么做?
自定義事件類 extends ApplicationEvent
day3
三、面向切面編程(Aspect oriented Programming)
1、代理模式
定義
1 A , B 實(shí)現(xiàn)了相同的接口,接口要求方法 m
2 用戶調(diào)用A的m,A又調(diào)用B的m
解決什么問題(什么時候考慮使用代理模式)
1 擴(kuò)展功能,而不修改現(xiàn)有的類
2 職責(zé)具有清晰的劃分
怎么用
Actale--接口 方法 act
Actor---實(shí)現(xiàn)
Test --- 客戶
Broker--實(shí)現(xiàn),Actor 的代理
采用代理實(shí)現(xiàn)日志
IFoo
doA,doB,doC
Foo
Test -- Test
FooLogProxy
注意思考:日志代理的弊端
相同的代碼散落在每一個方法中
2、使用動態(tài)代理解決
下面方法可以直接為接口 Foo 產(chǎn)生代理實(shí)例:
Foo proxy = (Foo) Proxy.newProxyInstance(
Foo.class.getClassLoader(),
new Class[]
{ Foo.class },
handler);
對 proxy 調(diào)用接口定義的方法,都會被分發(fā)給:
handler.invoke()
handler 是實(shí)現(xiàn)InvocationHandler 接口的實(shí)例
這樣就把對多個方法的調(diào)用集中起來了
handler.invoke()然后再分發(fā)請求到目標(biāo)方法
實(shí)施:
1) 實(shí)現(xiàn) InvocationHandler 接口
2)產(chǎn)生代理
3、Spring 的AOP 采用動態(tài)代理實(shí)現(xiàn)
一些別扭的概念:
切面:當(dāng)前關(guān)注的一個代碼的流程,其中可能調(diào)用了多個類的多個方法。
連接點(diǎn):一個代碼流程中的某個步驟,也就是這個代碼流程中對某個方法的調(diào)用。
通知(Advice):對于某個方法(連接點(diǎn)),進(jìn)行攔截的攔截規(guī)則。
切入點(diǎn):對于某個方法(連接點(diǎn)),是否被攔截的判斷(過濾)規(guī)則。
目標(biāo)對象:某個連接點(diǎn)所在的對象。
AOP代理:目標(biāo)對象的代理。
代理的生成:ProxyFactoryBean(org.springframework.aop.framework.ProxyFactoryBean)
工廠類,生產(chǎn)代理
區(qū)別于 BeanFactory
InvocationHandler 的行為 : Advice
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -