1. Spring IOC基礎(chǔ)
| Spring框架IOC實現(xiàn) | JavaSE應(yīng)用下該IOC容器啟動方式 | JavaWeb應(yīng)用下該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容器的頂層接?,它只是?來定義?些基礎(chǔ)功能,定義?些基礎(chǔ)規(guī)范,?ApplicationContext是它的?個?接?,所以ApplicationContext是具備BeanFactory提供的全部功能的。
?通常,我們稱BeanFactory為SpringIOC的基礎(chǔ)容器,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的三種方式
方式一:使用無參構(gòu)造函數(shù)
?在默認情況下,它會通過反射調(diào)用無參構(gòu)造函數(shù)來創(chuàng)建對象。如果 類中沒有無參構(gòu)造函數(shù),將創(chuàng)建失敗。
<!--配置service對象-->
<bean id="userService" class="com.lagou.service.impl.TransferServiceImpl">
</bean>
方式二:使用靜態(tài)方法創(chuàng)建
?在實際開發(fā)中,我們使?的對象有些時候并不是直接通過構(gòu)造函數(shù)就可以創(chuàng)建出來的,它可能在創(chuàng)建的過程 中會做很多額外的操作。此時會提供?個創(chuàng)建對象的?法,恰好這個?法是static修飾的?法,即是此種情況。
?例如,我們在做Jdbc操作時,會?到j(luò)ava.sql.Connection接?的實現(xiàn)類,如果是mysql數(shù)據(jù)庫,那么?的就是JDBC4Connection,但是我們不會去寫 JDBC4Connection connection = new JDBC4Connection() ,因為我們要注冊驅(qū)動,還要提供URL和憑證信息,? DriverManager.getConnection ?法來獲取連接。
?那么在實際開發(fā)中,尤其早期的項?沒有使?Spring框架來管理對象的創(chuàng)建,但是在設(shè)計時使?了??模式解耦,那么當接?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è)務(wù)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 內(nèi)有效。。 |
| seesion | 在一次 HTTP Session 中,容器會返回該 Bean 的同一個實例。而對不同的 HTTP 請求,會返回不同的實例,該作用域僅在當前 HTTP Session 內(nèi)有效。 |
| application | ServletContext的生命周期。僅在可感知web的Spring應(yīng)用程序上下文中有效。 |
| websocket | websocket的生命周期。僅在可感知web的Spring應(yīng)用程序上下文中有效 |
在上圖中提供的這些選項中,我們實際開發(fā)中?到最多的作?范圍就是singleton(單例模式)和prototype(原型模式,也叫多例模式)。配置?式參考下?的代碼:
<!--配置service對象-->
<bean id="transferService"
class="com.lagou.service.impl.TransferServiceImpl" scope="singleton">
</bean>
- 不同作用范圍的生命周期
- 單例模式
對象出生:當創(chuàng)建容器時,對象就被創(chuàng)建
對象存活:只要容器在,對象一直活著
對象死亡:當銷毀容器時,對象就被銷毀了
一句話總結(jié): 單例的bean對象生命周期和容器相同 - 多例模式
對象出生:當使用對象時,創(chuàng)建新的對象實例
對象存活:只要對象在使用中,對象一直活著
對象死亡:當對象長時間不用時,被java的垃圾回收哦器回收了
一句話總結(jié): 多例模式的bean對象,Spring框架只負責(zé)創(chuàng)建不負責(zé)銷毀。
- Bean標簽屬性
?在基于xml的IOC配置中,bean標簽是最基礎(chǔ)的標簽。它表示了IOC容器中的一個對象。換句話說,如果一個對象想讓Spring管理,在xml的配置中都需要使用此標簽配置,Bean標簽的屬性如下:- id屬性:用于給bean提供一個唯一標識。在一個標簽內(nèi)部,標識必須唯一。
- 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對象裝配后調(diào)用。必須是無參方法。
- destory-method屬性:用于指定bean對象的銷毀方法,此方法會在bean對象銷毀前執(zhí)行。他只能為scope是singleton時起作用。
- DI依賴注入的xml配置
- 依賴注入分類
- 按照注入的方式分類
構(gòu)造函數(shù)注入:顧名思義,就是利用帶參構(gòu)造函數(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了。
復(fù)雜類型(集合類型):注入的數(shù)據(jù)類型是Array,List,Set,Map,Properties中的一種類型。
- 按照注入的方式分類
- 依賴注入的配置實現(xiàn)之構(gòu)造函數(shù)注入
顧名思義,就是利用構(gòu)造函數(shù)實現(xiàn)對類成員的賦值。它的使用要求是,類中提供的構(gòu)造函數(shù)參數(shù)個數(shù)必須是配置的參數(shù)個數(shù)一致,且數(shù)據(jù)類型匹配。同時需要注意的是,當沒有無參構(gòu)造時,則必須提供構(gòu)造函數(shù)參數(shù)的注入,否則Spring框架會報錯。
在使用構(gòu)造函數(shù)注入時,涉及到的標簽是constructor-arg,該標簽有如下屬性:
name:用于給構(gòu)造函數(shù)中指定名稱的參數(shù)賦值。
index:用于給構(gòu)造函數(shù)指定索引位置的參數(shù)賦值。
value:用于指定基本類型或者String類型的數(shù)據(jù)。
ref:用于指定其他Bean類型的數(shù)據(jù)。寫的是其他bean的唯一標識。 - 依賴注入的配置實現(xiàn)之set方法注入
顧名思義,就是利用字段的set方法實現(xiàn)賦值的注入方式。
在使用set方法注入時,需要使用的標簽是property,該標簽有如下屬性:
name:指定注入時調(diào)用的set方法名稱。(注:不包含set這三個字母)
value:指定注入的數(shù)據(jù),它支持基本類型和String類型。
ref:指定注入的數(shù)據(jù),它指定其他bean類型。寫的是其他的bean的唯一標識。 -
復(fù)雜數(shù)據(jù)類型注入
?首先說明一下復(fù)雜屬性類型,它指的是集合類型數(shù)據(jù)。集合分兩類某一類是List結(jié)構(gòu)(數(shù)組結(jié)構(gòu)),一類是Map接口(鍵值對)。
?接下來就是注入的方式的選擇,只能在構(gòu)造函數(shù)和set方法中選擇,我們的示例選擇set方法注入。
?在List結(jié)構(gòu)的集合數(shù)據(jù)注?時, array , list , set 這三個標簽通?,另外注值的 value 標簽內(nèi)部可以直接寫值,也可以使? bean 標簽配置?個對象,或者? ref 標簽引??個已經(jīng)配合的bean的唯?標識。
?在Map結(jié)構(gòu)的集合數(shù)據(jù)注?時,map 標簽使? entry ?標簽實現(xiàn)數(shù)據(jù)注?,entry 標簽可以使?key和value屬性指定存?map中的數(shù)據(jù)。使?value-ref屬性指定已經(jīng)配置好的bean的引?。同時 entry 標簽中也可以使? ref 標簽,但是不能使? bean 標簽。? property 標簽中不能使? ref 或者 bean 標簽引?對象。
- 依賴注入分類
1.3 xml與注解相結(jié)合模式
注意:
- 實際企業(yè)開發(fā)中,純xml模式使?已經(jīng)很少了
- 引?注解功能,不需要引?額外的jar
- xml+注解結(jié)合模式,xml?件依然存在,所以,spring IOC容器的啟動仍然從加載xml開始
- 哪些bean的定義寫在xml中,哪些bean的定義使?注解
第三?jar中的bean定義在xml,?如德魯伊數(shù)據(jù)庫連接池??開發(fā)的bean定義使?注解
- xml中標簽與注解的對應(yīng)(IOC)
| xml形式 | 對應(yīng)的注解形式 |
|---|---|
| 標簽 | @Component("accountDao"), 注解加在類上,bean的id屬性內(nèi)容直接配置在注解后面,默認定義這個bean的id是類的類名首字母小寫; 另外,針對分層代碼開發(fā)提供了@Component的三種別名,@Controoler、@Service、@Repository分別控制層類、服務(wù)層類、dao層類的bean定義,這四個注解的用法完全一樣,只是為了更清晰的區(qū)別 |
| 標簽的scope屬性 | @Scope("prototype"),默認單例,注解加在類上 |
| 標簽的init-method屬性 | @PostConstruct,注解加在方法上,該方法就是初始化后調(diào)用的方法 |
| 標簽的destory-method屬性 | @PreDestory,注解加在方法上,該方法就是銷毀前調(diào)用的方法 |
- DI依賴注入的注解實現(xiàn)方式
- @Autowire(推薦使用)
@Autowired為Spring提供的注解,需要導(dǎo)?包org.springframework.beans.factory.annotation.Autowired。
@Autowire采用的策略為按照類型注入。
public class TransferServiceImpl {
@Autowired
private AccountDao accountDao;
}
?如上代碼所示,這樣裝配回去spring容器中找到類型為AccountDao的類,然后將其注?進來。這樣會產(chǎn)??個問題,當?個類型有多個bean值的時候,會造成?法選擇具體注?哪?個的情況,
?這個時候我們需要配合著@Qualifier使?。
?@Qualifier告訴Spring具體去裝配那個對象。
public class TransferServiceImpl {
@Autowired
@Qualifier(name="jdbcAccountDaoImpl")
private AccountDao accountDao;
}
這個時候我們就可以通過類型和名稱定位到我們想注入的對象。
- @Resouce
@Resource 注解由 J2EE 提供,需要導(dǎo)?包 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中遺留的內(nèi)容全部以注解的形式遷移出去,最終刪除xml,從Java配置類啟動。
對應(yīng)注解
@Configuration注解,表示當前類是一個配置類
@ComponentScan注解,代替context:componentr-scan
@PropertySource,引入其他配置類
@Import,引入其他配置類
@Value對變量賦值,可以直接賦值,也可以使用${}讀取資源配置文件中的信息
@Bean將方法返回對象加入Spring IOC容器



