Spring 系列(一) IOC應(yīng)用

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容器
    1. ClassPathXmlApplicationContext:從類的根路徑下加載配置文件(推薦使用)
    2. FileSystemXmlApplicationContext:從磁盤路徑下加載配置文件
    3. AnnotationConfigApplicationContext:純注解模式下啟動Spring容器
  • Web環(huán)境下啟動IOC容器
    1. 從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>
  • 不同作用范圍的生命周期
  1. 單例模式
    對象出生:當創(chuàng)建容器時,對象就被創(chuàng)建
    對象存活:只要容器在,對象一直活著
    對象死亡:當銷毀容器時,對象就被銷毀了
    一句話總結(jié): 單例的bean對象生命周期和容器相同
  2. 多例模式
    對象出生:當使用對象時,創(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é)合模式

注意:

  1. 實際企業(yè)開發(fā)中,純xml模式使?已經(jīng)很少了
  2. 引?注解功能,不需要引?額外的jar
  3. xml+注解結(jié)合模式,xml?件依然存在,所以,spring IOC容器的啟動仍然從加載xml開始
  4. 哪些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)方式
  1. @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;
}

這個時候我們就可以通過類型和名稱定位到我們想注入的對象。

  1. @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容器

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容