1. Spring IOC基礎
Spring框架IOC實現(xiàn) | JavaSE應用下該IOC容器啟動方式 | JavaWeb應用下該IOC容器啟動方式 |
---|---|---|
純xml | new ClassPathXmlApplicationContext("beans.xml"); 或者new FileSystemXmlApplicationContext("c:/beans.xml"); |
ContextLoaderListener(監(jiān)聽器去加載xml) |
xml+注解 | new ClassPathXmlApplicationContext("beans.xml"); 或者new FileSystemXmlApplicationContext("c:/beans.xml"); |
ContextLoaderListener(監(jiān)聽器去加載xml) |
純注解模式 | new AnnotationConfigApplicationContext("SpringConfig.class"); | ContextLoaderListener(監(jiān)聽器去加載注解配置類) |
1.1 BeanFactory與ApplicationContext區(qū)別
?BeanFactory是Spring框架中IoC容器的頂層接?,它只是?來定義?些基礎功能,定義?些基礎規(guī)范,?ApplicationContext是它的?個?接?,所以ApplicationContext是具備BeanFactory提供的全部功能的漩蟆。
?通常垒探,我們稱BeanFactory為SpringIOC的基礎容器,ApplicationContext是容器的?級接?怠李,?BeanFactory要擁有更多的功能圾叼,?如說國際化?持和資源訪問(xml,java配置類)等等
啟動容器的方式
- Java環(huán)境下啟動IOC容器
- ClassPathXmlApplicationContext:從類的根路徑下加載配置文件(推薦使用)
- FileSystemXmlApplicationContext:從磁盤路徑下加載配置文件
- AnnotationConfigApplicationContext:純注解模式下啟動Spring容器
- Web環(huán)境下啟動IOC容器
- 從xml啟動容器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--配置Spring ioc容器的配置?件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--使?監(jiān)聽器啟動Spring的IOC容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
?2. 從配置類加載啟動容器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--告訴ContextloaderListener知道我們使?注解的?式啟動ioc容器-->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebAppli
cationContext</param-value>
</context-param>
<!--配置啟動類的全限定類名-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.lagou.edu.SpringConfig</param-value>
</context-param>
<!--使?監(jiān)聽器啟動Spring的IOC容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
1.2 純xml形式
- xml文件頭
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
- 實例化bean的三種方式
方式一:使用無參構造函數(shù)
?在默認情況下捺癞,它會通過反射調用無參構造函數(shù)來創(chuàng)建對象夷蚊。如果 類中沒有無參構造函數(shù),將創(chuàng)建失敗髓介。
<!--配置service對象-->
<bean id="userService" class="com.lagou.service.impl.TransferServiceImpl">
</bean>
方式二:使用靜態(tài)方法創(chuàng)建
?在實際開發(fā)中惕鼓,我們使?的對象有些時候并不是直接通過構造函數(shù)就可以創(chuàng)建出來的,它可能在創(chuàng)建的過程 中會做很多額外的操作唐础。此時會提供?個創(chuàng)建對象的?法箱歧,恰好這個?法是static修飾的?法,即是此種情況一膨。
?例如呀邢,我們在做Jdbc操作時,會?到java.sql.Connection接?的實現(xiàn)類豹绪,如果是mysql數(shù)據(jù)庫价淌,那么?的就是JDBC4Connection,但是我們不會去寫 JDBC4Connection connection = new JDBC4Connection() 瞒津,因為我們要注冊驅動蝉衣,還要提供URL和憑證信息,? DriverManager.getConnection ?法來獲取連接巷蚪。
?那么在實際開發(fā)中买乃,尤其早期的項?沒有使?Spring框架來管理對象的創(chuàng)建,但是在設計時使?了??模式解耦钓辆,那么當接?spring之后,??類創(chuàng)建對象就具有和上述例?相同特征,即可采?此種?式配置前联。
<!--使?靜態(tài)?法創(chuàng)建對象的配置?式-->
<bean id="userService" class="com.lagou.factory.BeanFactory"
factory-method="getTransferService"></bean>
方式三:使用實例化方法創(chuàng)建
?此種方式和上?靜態(tài)方法創(chuàng)建其實類似功戚,區(qū)別是用于獲取對象的方法不再是static修飾的了,而是類中的?個普通方法似嗤,且需要配置工廠bean啸臀,并在業(yè)務bean中配置factory-bean,factory-method屬性。
?在早期開發(fā)的項?中烁落,工廠類中的方法有可能是靜態(tài)的乘粒,也有可能是非靜態(tài)方法,當是非靜態(tài)方法時伤塌,即可采用下?的配置方式:
<!--使?實例?法創(chuàng)建對象的配置?式-->
<bean id="beanFactory" class="com.lagou.factory.instancemethod.BeanFactory"></bean>
<bean id="transferService" factory-bean="beanFactory" factory-method="getTransferService"></bean>
- Bean的X以及生命周期
?在spring框架管理Bean對象的創(chuàng)建時灯萍,Bean對象默認都是單例的,但是它?持配置的?式改變作?范圍每聪。作?范圍如下旦棉。
Scope | Description |
---|---|
singleton | 單例模式,使用 singleton 定義的 Bean 在 Spring 容器中只有一個實例药薯,這也是 Bean 默認的作用域绑洛。 |
prototype | 原型模式,每次通過 Spring 容器獲取 prototype 定義的 Bean 時童本,容器都將創(chuàng)建一個新的 Bean 實例真屯。 |
request | 在一次 HTTP 請求中,容器會返回該 Bean 的同一個實例穷娱。而對不同的 HTTP 請求绑蔫,會返回不同的實例,該作用域僅在當前 HTTP Request 內有效鄙煤。晾匠。 |
seesion | 在一次 HTTP Session 中,容器會返回該 Bean 的同一個實例梯刚。而對不同的 HTTP 請求凉馆,會返回不同的實例,該作用域僅在當前 HTTP Session 內有效亡资。 |
application | ServletContext的生命周期澜共。僅在可感知web的Spring應用程序上下文中有效。 |
websocket | websocket的生命周期锥腻。僅在可感知web的Spring應用程序上下文中有效 |
在上圖中提供的這些選項中嗦董,我們實際開發(fā)中?到最多的作?范圍就是singleton(單例模式)和prototype(原型模式,也叫多例模式)瘦黑。配置?式參考下?的代碼:
<!--配置service對象-->
<bean id="transferService"
class="com.lagou.service.impl.TransferServiceImpl" scope="singleton">
</bean>
- 不同作用范圍的生命周期
- 單例模式
對象出生:當創(chuàng)建容器時京革,對象就被創(chuàng)建
對象存活:只要容器在庸毫,對象一直活著
對象死亡:當銷毀容器時,對象就被銷毀了
一句話總結: 單例的bean對象生命周期和容器相同 - 多例模式
對象出生:當使用對象時勋篓,創(chuàng)建新的對象實例
對象存活:只要對象在使用中狮暑,對象一直活著
對象死亡:當對象長時間不用時,被java的垃圾回收哦器回收了
一句話總結: 多例模式的bean對象廊勃,Spring框架只負責創(chuàng)建不負責銷毀懈贺。
- Bean標簽屬性
?在基于xml的IOC配置中,bean標簽是最基礎的標簽坡垫。它表示了IOC容器中的一個對象梭灿。換句話說,如果一個對象想讓Spring管理冰悠,在xml的配置中都需要使用此標簽配置堡妒,Bean標簽的屬性如下:- id屬性:用于給bean提供一個唯一標識。在一個標簽內部屿脐,標識必須唯一涕蚤。
- class屬性:用于指定創(chuàng)建Bean對象的全限定類名。
- name屬性:用于給bean 提供一個或多個名稱的诵,多個名稱用空格分隔万栅。
- factory-bean屬性:用于指定創(chuàng)建當前bean對象的工廠bean的唯一標識。當指定了此屬性之后西疤,class屬性失效烦粒。
- factory-method屬性:用于指定創(chuàng)建當前bean對象的工廠方法,如配合factory-bean使用代赁,則class屬性失效(實例化方法創(chuàng)建)扰她;如配合class屬性使用,則方法必須是static的(靜態(tài)方法創(chuàng)建)芭碍。
- scope屬性:用于指定bean對象的作用范圍徒役。通常情況下就是singleton,當需要用到多例模式時窖壕,可以配置為prototype忧勿。
- init-method屬性:用于指定bean對象的初始化方法,此方法會在bean對象裝配后調用瞻讽。必須是無參方法鸳吸。
- destory-method屬性:用于指定bean對象的銷毀方法,此方法會在bean對象銷毀前執(zhí)行速勇。他只能為scope是singleton時起作用晌砾。
- DI依賴注入的xml配置
- 依賴注入分類
- 按照注入的方式分類
構造函數(shù)注入:顧名思義,就是利用帶參構造函數(shù)實現(xiàn)對類成員的數(shù)據(jù)賦值烦磁。
set方法注入:它是通過類成員的set方法實現(xiàn)數(shù)據(jù)的注入养匈。 - 按照注入的數(shù)據(jù)類型分類
基本類型和String:注入的數(shù)據(jù)類型是基本類型或者是字符串類型的數(shù)據(jù)哼勇。
其他Bean類型:注入的數(shù)據(jù)類型是對象類型,稱為其他的Bean的原因是呕乎,這個對象要求出現(xiàn)在IOC容器中的猴蹂,那么針對當前Bean來說,就是其他Bean了楣嘁。
復雜類型(集合類型):注入的數(shù)據(jù)類型是Array,List珍逸,Set逐虚,Map,Properties中的一種類型谆膳。
- 按照注入的方式分類
- 依賴注入的配置實現(xiàn)之構造函數(shù)注入
顧名思義叭爱,就是利用構造函數(shù)實現(xiàn)對類成員的賦值。它的使用要求是漱病,類中提供的構造函數(shù)參數(shù)個數(shù)必須是配置的參數(shù)個數(shù)一致买雾,且數(shù)據(jù)類型匹配。同時需要注意的是杨帽,當沒有無參構造時漓穿,則必須提供構造函數(shù)參數(shù)的注入,否則Spring框架會報錯注盈。
在使用構造函數(shù)注入時晃危,涉及到的標簽是constructor-arg,該標簽有如下屬性:
name:用于給構造函數(shù)中指定名稱的參數(shù)賦值老客。
index:用于給構造函數(shù)指定索引位置的參數(shù)賦值僚饭。
value:用于指定基本類型或者String類型的數(shù)據(jù)。
ref:用于指定其他Bean類型的數(shù)據(jù)胧砰。寫的是其他bean的唯一標識鳍鸵。 - 依賴注入的配置實現(xiàn)之set方法注入
顧名思義,就是利用字段的set方法實現(xiàn)賦值的注入方式尉间。
在使用set方法注入時偿乖,需要使用的標簽是property,該標簽有如下屬性:
name:指定注入時調用的set方法名稱乌妒。(注:不包含set這三個字母)
value:指定注入的數(shù)據(jù)汹想,它支持基本類型和String類型。
ref:指定注入的數(shù)據(jù)撤蚊,它指定其他bean類型古掏。寫的是其他的bean的唯一標識。 -
復雜數(shù)據(jù)類型注入
?首先說明一下復雜屬性類型侦啸,它指的是集合類型數(shù)據(jù)槽唾。集合分兩類某一類是List結構(數(shù)組結構)丧枪,一類是Map接口(鍵值對)。
?接下來就是注入的方式的選擇庞萍,只能在構造函數(shù)和set方法中選擇拧烦,我們的示例選擇set方法注入。
?在List結構的集合數(shù)據(jù)注?時钝计, array , list , set 這三個標簽通?恋博,另外注值的 value 標簽內部可以直接寫值,也可以使? bean 標簽配置?個對象私恬,或者? ref 標簽引??個已經配合的bean的唯?標識债沮。
?在Map結構的集合數(shù)據(jù)注?時,map 標簽使? entry ?標簽實現(xiàn)數(shù)據(jù)注?本鸣,entry 標簽可以使?key和value屬性指定存?map中的數(shù)據(jù)疫衩。使?value-ref屬性指定已經配置好的bean的引?。同時 entry 標簽中也可以使? ref 標簽荣德,但是不能使? bean 標簽闷煤。? property 標簽中不能使? ref 或者 bean 標簽引?對象。
- 依賴注入分類
1.3 xml與注解相結合模式
注意:
- 實際企業(yè)開發(fā)中涮瞻,純xml模式使?已經很少了
- 引?注解功能鲤拿,不需要引?額外的jar
- xml+注解結合模式,xml?件依然存在饲宛,所以皆愉,spring IOC容器的啟動仍然從加載xml開始
- 哪些bean的定義寫在xml中,哪些bean的定義使?注解
第三?jar中的bean定義在xml艇抠,?如德魯伊數(shù)據(jù)庫連接池??開發(fā)的bean定義使?注解
- xml中標簽與注解的對應(IOC)
xml形式 | 對應的注解形式 |
---|---|
標簽 | @Component("accountDao")幕庐, 注解加在類上,bean的id屬性內容直接配置在注解后面家淤,默認定義這個bean的id是類的類名首字母小寫异剥; 另外,針對分層代碼開發(fā)提供了@Component的三種別名絮重,@Controoler冤寿、@Service、@Repository分別控制層類青伤、服務層類督怜、dao層類的bean定義,這四個注解的用法完全一樣狠角,只是為了更清晰的區(qū)別 |
標簽的scope屬性 | @Scope("prototype")号杠,默認單例,注解加在類上 |
標簽的init-method屬性 | @PostConstruct,注解加在方法上姨蟋,該方法就是初始化后調用的方法 |
標簽的destory-method屬性 | @PreDestory屉凯,注解加在方法上,該方法就是銷毀前調用的方法 |
- DI依賴注入的注解實現(xiàn)方式
- @Autowire(推薦使用)
@Autowired為Spring提供的注解眼溶,需要導?包org.springframework.beans.factory.annotation.Autowired悠砚。
@Autowire采用的策略為按照類型注入。
public class TransferServiceImpl {
@Autowired
private AccountDao accountDao;
}
?如上代碼所示堂飞,這樣裝配回去spring容器中找到類型為AccountDao的類灌旧,然后將其注?進來。這樣會產??個問題绰筛,當?個類型有多個bean值的時候节榜,會造成?法選擇具體注?哪?個的情況,
?這個時候我們需要配合著@Qualifier使?别智。
?@Qualifier告訴Spring具體去裝配那個對象。
public class TransferServiceImpl {
@Autowired
@Qualifier(name="jdbcAccountDaoImpl")
private AccountDao accountDao;
}
這個時候我們就可以通過類型和名稱定位到我們想注入的對象稼稿。
- @Resouce
@Resource 注解由 J2EE 提供薄榛,需要導?包 javax.annotation.Resource。
@Resource 默認按照 ByName ?動注?让歼。
public class TransferService {
@Resource
private AccountDao accountDao;
@Resource(name="studentDao")
private StudentDao studentDao;
@Resource(type="TeacherDao")
private TeacherDao teacherDao;
@Resource(name="manDao",type="ManDao")
private ManDao manDao;
}
- 如果同時指定了name和type敞恋,則從Spring上下文中找到唯一匹配的bean進行裝配。
- 如果指定了name谋右,則從上下文中查找名稱(id)匹配的bean進行裝配硬猫,找不到則拋異常。
- 如果指定了type改执,則從上下文中查找類似匹配的唯一bean進行裝配啸蜜,找不到或找到多個則拋異常。
- 如果既沒有指定name也沒有指定type辈挂,則自動按照byName方式進行裝配衬横。
1.4 純注解模式
改造xm+注解模式,將xml中遺留的內容全部以注解的形式遷移出去终蒂,最終刪除xml蜂林,從Java配置類啟動拇泣。
對應注解
@Configuration注解,表示當前類是一個配置類
@ComponentScan注解霉翔,代替context:componentr-scan
@PropertySource,引入其他配置類
@Import早龟,引入其他配置類
@Value對變量賦值猫缭,可以直接賦值,也可以使用${}讀取資源配置文件中的信息
@Bean將方法返回對象加入Spring IOC容器