spring控制反轉ioc
在項目中,常用mvc設計模式來解耦。
mvc:模型Model,視圖View,控制器Controller
視圖負責頁面的顯示,與用戶的交互。
控制器負責將視圖與模型一一對應起來。相當于一個模型分發(fā)器。所謂分發(fā)就是:①接收請求,并將該請求跳轉(轉發(fā),重定向)到模型進行處理。②模型處理完畢后,再通過控制器,返回給視圖中的請求處。一般使用Servlet實現(xiàn)控制器。
模型負責實現(xiàn)功能,簡單理解為javabean
三層架構:一種用于解耦合提升代碼復用率的軟件架構。可以分為表現(xiàn)層,業(yè)務邏輯層(service),數(shù)據(jù)訪問層(dao),最后加上實體類庫。

?

但某些代碼里,ui調用業(yè)務層,業(yè)務層又調用持久層。層層調用下來導致耦合度非常高


解決辦法:使用工廠模式創(chuàng)建bean對象
????bean:可重用組件,比如一個service可以被很多serverlet使用,一個dao可以被很多service使用
????javabean:很容易簡單理解成實體類,但實際上概念遠大于實體類。用java編寫的可重用組件都是javabean。
所以該工廠就是用來創(chuàng)建我們的service和dao對象。
如何創(chuàng)建?
????1,需要一個配置文件來配置service和dao
????????配置文件內容:唯一表示=全限定類名(key = value的形式)
????2,通過讀取配置文件中配置的內容,反射創(chuàng)建bean對象





此時若是少了實現(xiàn)類,不會引起編譯期異常,而是轉換成運行期異常。

但上述工廠模式解耦依然存在一些問題,如果連續(xù)打印五次service實現(xiàn)類,會發(fā)現(xiàn)這五個實現(xiàn)類都有不同的內存地址,為五個不同的實現(xiàn)類

但此處不需要用多例模式,多個實現(xiàn)類的生成,是因為用了newInstance;這段代碼每次都會調用默認構造函數(shù)創(chuàng)建對象。
調整方法:只使用newInstance一次創(chuàng)建對象,再馬上存起來,這就需要一個容器。
創(chuàng)建容器的過程:于是定義一個map,用于存放創(chuàng)建的對象→實例化容器→取出配置文件中所有的key→根據(jù)key獲取value→反射創(chuàng)建對象

控制反轉(inversion of control),把創(chuàng)建對象的權力交給框架。
使用spring的ioc解決程序的耦合。


ApplicationContext就是spring的核心容器對象,有三個常用實現(xiàn)類:
ClassPathXmlApplicationContext:它可以加載類路徑下的配置文件,要求配置文件必須在類路徑下,否則無法加載
FileSystemXmlApplicationContext:可以加載磁盤任意路徑下的配置文件(必須有訪問權限)
AnnotationConfigApplicationContext:用于讀取注解創(chuàng)建容器
核心容器的兩個接口引發(fā)出的問題:
ApplicationContext:它在構建核心容器時,它創(chuàng)建對象時的策略是立即加載,即只要一讀取完配置文件,馬上創(chuàng)建配置文件中配置的對象。(單例對象適用)
????在說工廠模式解耦時,說過我們的service也好dao也好,都是沒有類成員的,所以沒有線程安全問題。所以我們可以直接使用單例模式,創(chuàng)建service和dao。又因為service和dao都是單例的,所以傾向于用ApplicationContext馬上創(chuàng)建對象,創(chuàng)建一次就再也不用創(chuàng)建了。
BeanFactory:它在構建核心容器時,采取延遲加載的方式。當什么時候根據(jù)id獲取對象了,什么時候才真正的創(chuàng)建對象。
????什么時候用,什么時候創(chuàng)建,適合多例模式。
BeanFactory是一個頂層接口,功能不夠完善,實際開發(fā)中更多使用它的子接口或者ApplicationContext

<把對象的創(chuàng)建交給spring管理>
spring對bean的管理細節(jié):
1創(chuàng)建bean的三種方式:
????第一種:使用默認構造函數(shù)創(chuàng)建
????????????在spring的配置文件中使用bean標簽,配以id和class屬性,且沒有其他屬性和標簽時,采用的就是默認的構造函數(shù)創(chuàng)建bean對象。如果類中沒有默認構造函數(shù),則對象無法創(chuàng)建
????第二種:使用普通工廠中的方法創(chuàng)建對象(使用某個類中的方法創(chuàng)建對象,并存入spring容器)實現(xiàn)代碼如下:
????????????<bean id = "instanceFactory" class="com.itheima.Factory.InstanceFactory"></bean>
????????????<bean id = "accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
????有了instanceFactory,他是一個工廠,可以為我們創(chuàng)建對象。我們就是要用它里面的方法去創(chuàng)建,這是時候需要定義一個service,等下可以用id取出
,這個service對象是怎么來的?是通過id所指向的工廠-bean對象里面的工廠-method方法來獲得的。
????第三種:使用工廠中的靜態(tài)方法創(chuàng)建對象(使用某個類中的靜態(tài)方法創(chuàng)建對象,并存入spring容器)
????<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService>??</bean>
2bean對象的作用范圍?
????bean標簽的scope屬性:
????????作用:用于指定bean的作用范圍
????????取值:常用前兩個單例和多例的
????????????singleton:單例(默認值)
????????????prototype:多例
????????????request:作用于web應用的請求范圍
????????????session:作用于web應用的會話范圍
????????????global-session:作用于集群環(huán)境的會話范圍(全局會話范圍),當不是集群環(huán)境時,他就是session
3bean對象的生命周期
????單例:
????????出生:容器創(chuàng)建時對象出生
????????活著:容器還在,對象就活著
????????死亡:容器被銷毀,對象消亡
????????故可以說對象的生命周期和容器相同
????多例:
????????出生:使用對象時,spring框架會創(chuàng)建
????????活著:使用過程中對象一直活著
????????死亡:長時間不用且沒有別的對象引用,由java的垃圾回收機制回收

spring中的依賴注入dependency injection
依賴注入能注入的數(shù)據(jù)類型有三類:
1基本類型和string
2其他bean類型(在配置文件中或者注解配置過的bean)
3復雜類型,也叫集合類型
注入的方式也有三種:
1使用構造函數(shù)提供:

????使用的標簽constructor-arg,標簽位于bean標簽的內部,里面的屬性有type,index,name,這三個用于指定給構造函數(shù)中的某個參數(shù)賦值。value用于提供基本類型和string類型的數(shù)據(jù),ref用于指定其他的bean類數(shù)據(jù)(指的是核心容器中出現(xiàn)過的bean)。所以只要是xml配置過的或者注解配置過的,都能引用

可以用now這個id取出來,接收則不能用value,需要用到ref
優(yōu)勢:獲取bean對象時,注入數(shù)據(jù)是必須的操作,否則對象無法創(chuàng)建成功,這就更不易被遺忘忽略
弊端:改變了bean對象的實例化方式,使創(chuàng)建對象時就算用不到這些數(shù)據(jù),也必須提供
2使用set方法提供:

涉及的標簽:property,出現(xiàn)的位置:bean內部
標簽的屬性只有name,value,ref。name用于指定注入時所調用的set方法名稱。value:基本類型數(shù)據(jù)和string。ref:指定其他的bena類型數(shù)據(jù)
注:property標簽里面的屬性名并不管你定義的變量名,而是關心set方法叫什么名稱,去掉set把首字母變小寫
優(yōu)勢:創(chuàng)建對象沒有明確限制,可以直接使用默認構造函數(shù)
弊端:如果某個成員變量必須有值,則獲取對象時有可能set方法沒有執(zhí)行
3使用注解提供:下一節(jié)
============================
關于集合類型數(shù)據(jù)的注入

用于給List結構集合注入的標簽:list,array,set
用于給Map結構集合注入的標簽:map,props
結構相同可以互換