<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Spring之IOC(容器,控制反轉(zhuǎn))

      1、IOC(容器)

      什么是容器?容器是一種為某種特定組件的運行提供必要支持的一個軟件環(huán)境。例如,Tomcat就是一個Servlet容器,它可以為Servlet的運行提供運行環(huán)境。通常來說,使用容器運行組件,除了提供一個組件運行環(huán)境之外,容器還提供了許多底層服務(wù)。例如,Servlet容器底層實現(xiàn)了TCP連接,解析HTTP協(xié)議等非常復(fù)雜的服務(wù),如果沒有容器來提供這些服務(wù),我們就無法編寫像Servlet這樣代碼簡單,功能強大的組件。

      Spring的核心就是提供了一個IoC容器,它可以管理所有輕量級的JavaBean組件,提供的底層服務(wù)包括組件的生命周期管理、配置和組裝服務(wù)、AOP支持,以及建立在AOP基礎(chǔ)上的聲明式事務(wù)服務(wù)等。

       

      1.1、IOC的基本介紹

      Spring提供的容器又稱為IoC容器,IoC全稱Inversion of Control,直譯為控制反轉(zhuǎn)。IOC 是面向?qū)ο缶幊讨械囊环N設(shè)計原則,可以用來減低代碼之間的耦合度。在 spring 中,控制反轉(zhuǎn)把對象創(chuàng)建和對象之間的調(diào)用過程,交給 spring 進行管理,減低了代碼的耦合度。

       

      誰控制誰,控制什么:傳統(tǒng)Java SE程序設(shè)計,我們直接在對象內(nèi)部通過new進行創(chuàng)建對象,是程序主動去創(chuàng)建依賴對象;而IoC是有專門一個容器來創(chuàng)建這些對象,即由Ioc容器來控制對象的創(chuàng)建;誰控制誰?當(dāng)然是IoC 容器控制了對象;控制什么?那就是主要控制了外部資源獲取(不只是對象包括比如文件等)。

      為何是反轉(zhuǎn),哪些方面反轉(zhuǎn)了:有反轉(zhuǎn)就有正轉(zhuǎn),傳統(tǒng)應(yīng)用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉(zhuǎn);而反轉(zhuǎn)則是由容器來幫忙創(chuàng)建及注入依賴對象;為何是反轉(zhuǎn)?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉(zhuǎn);哪些方面反轉(zhuǎn)了?依賴對象的獲取被反轉(zhuǎn)了。

      在IoC模式下,控制權(quán)發(fā)生了反轉(zhuǎn),即從應(yīng)用程序轉(zhuǎn)移到了IoC容器,所有組件不再由應(yīng)用程序自己創(chuàng)建和配置,而是由IoC容器負責(zé),這樣,應(yīng)用程序只需要直接使用已經(jīng)創(chuàng)建好并且配置好的組件。

       

      用圖例說明一下,傳統(tǒng)程序設(shè)計如圖2-1,都是主動去創(chuàng)建相關(guān)對象然后再組合起來:

      當(dāng)有了IoC/DI的容器后,在客戶端類中不再主動去創(chuàng)建這些對象了,如圖2-2所示:

      IoC不是一種技術(shù),只是一種思想,一個重要的面向?qū)ο缶幊痰姆▌t,它能指導(dǎo)我們?nèi)绾卧O(shè)計出松耦合、更優(yōu)良的程序。傳統(tǒng)應(yīng)用程序都是由我們在類內(nèi)部主動創(chuàng)建依賴對象,從而導(dǎo)致類與類之間高耦合,難于測試;有了IoC容器后,把創(chuàng)建和查找依賴對象的控制權(quán)交給了容器,由容器進行注入組合對象,所以對象與對象之間是松散耦合,這樣也方便測試,利于功能復(fù)用,更重要的是使得程序的整個體系結(jié)構(gòu)變得非常靈活。

      參考:http://www.rzrgm.cn/NancyStartOnce/p/6813162.html

       

      1.2、IOC的基本使用

      下載完 sprig 解壓文件后可以看到很多jar 包,將 spring 所必需的四個包和 commons-logging 包導(dǎo)入項目當(dāng)中:

      spring 框架依賴的jar包有 commons-logging,如果不添加的話會報錯。

       

      先編寫一個簡單的 User 類,然后在 src 目錄下新建一個spring的配置文件即 xml 文件,該配置文件可自定義,比如 bean01.xml。

      User 類:

      package test;
      
      public class User {
          public void add() {
              System.out.println("add。。。");
          }
      }

      spring 配置文件 bean01.xml 如下,class 里面寫的是完整類名。

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <!-- 配置創(chuàng)建的對象-->
          <bean id="user" class="test.User"></bean>
      </beans>

      然后就可以隨便建一個測試類來進行測試:

      package test.testDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import test.User;
      
      public class Test01 {
      
          public static void main(String[] args) {
              //加載spring配置文件,并創(chuàng)建了配置文件中配置的類的實例對象)
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取bean,即配置創(chuàng)建的對象
              User user = (User) context.getBean("user");   //getBean()方法里面的參數(shù)是 xml 配置文件中的bean節(jié)點的id
      //調(diào)用 user.add(); } }

      執(zhí)行上面代碼可以看到輸出 User 類中的 add() 方法。

      默認情況下,通過 bean 獲取到的實例對象是單例的,即多次通過 getBean() 方法獲取同一個 bean 時(在不同配置文件中,即使 bean 標(biāo)簽的 class 指向的是同一個類,也不是同一個bean,此時創(chuàng)建的不是同一個實例對象),獲取到的實例對象實際上都是同一個對象。

       

      1.3、IOC底層原理

      原理:通過解析 xml 配置文件獲取類名,然后通過反射來創(chuàng)建該類的一個實例對象并返回。

      如果后面類發(fā)生了改變,比如類名改了,只需修改配置文件即可,所以大大降低了耦合度。(因為如果是傳統(tǒng)程序,類名發(fā)生修改,在所有引用到該類的地方都需要進行修改)

       

      2、Spring 中Bean相關(guān)基本介紹

      在 Spring 框架中,Bean 是由 Spring IoC(Inversion of Control,控制反轉(zhuǎn))容器管理的對象。Spring 容器負責(zé)創(chuàng)建、初始化、配置和銷毀這些 Bean。一個 Java 類只要被 Spring 容器管理,就可以被稱為 Spring Bean。

      (只要是一個普通的 Java 類,Spring 就可以對其進行管理,并不要求該類嚴(yán)格遵循 JavaBean 規(guī)范。)

      2.1、spring對于bean的操作

      bean 管理指的是兩個操作:

      1. spring 創(chuàng)建對象
      2. spring 注入屬性

      IoC又稱為依賴注入(DI:Dependency Injection),依賴注入就是注入屬性,注入屬性是在創(chuàng)建對象的基礎(chǔ)之上完成的,先創(chuàng)建對象,實際上是然后再注入屬性。

       

      bean 實現(xiàn)上述兩個操作有兩種方式:

      1. 基于xml配置文件方式實現(xiàn)
      2. 基于注解方式實現(xiàn)

      Spring 的 IoC 容器同時支持屬性注入和構(gòu)造方法注入,并允許混合使用。

      在設(shè)計上,Spring的IoC容器是一個高度可擴展的無侵入容器。所謂無侵入,是指應(yīng)用程序的組件無需實現(xiàn)Spring的特定接口,或者說,組件根本不知道自己在Spring的容器中運行。這種無侵入的設(shè)計有以下好處:

      1. 應(yīng)用程序組件既可以在Spring的IoC容器中運行,也可以自己編寫代碼自行組裝配置;
      2. 測試的時候并不依賴Spring容器,可單獨進行測試,大大提高了開發(fā)效率。

       

      2.2、FactoryBean(工廠bean)

      在普通的 bean 當(dāng)中,class屬性指的是什么類,則取到的就是該類的實例對象。但通過 FactoryBean 我們可以自定義 bean 的創(chuàng)建過程,包括自定義返回的類、是否單例、bean的類型。

      定義一個工廠 bean,MyBean.java如下,可以看到,實際返回的是 User  bean:

      package test;
      
      import org.springframework.beans.factory.FactoryBean;
      
      public class Mybean implements FactoryBean {
      
          @Override
          public User getObject() throws Exception {  //實際返回的對象實例
              User user = new User();
              return user;
          }
      
          @Override
          public Class<?> getObjectType() {  //Bean的類型
              return null;
          }
      
          @Override
          public boolean isSingleton() {  //是否為單例,true為單例,false為非單例
              return false;
          }
      }

      配置文件:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean id="mybean" class="test.Mybean"></bean>
      </beans>

      測試代碼:

      定義FactoryBean后,Spring創(chuàng)建的Bean實際上是這個FactoryBeangetObject()方法返回的Bean。

      package test.testDemo;
      
      import dao.UserDao;
      import dao.impl.UserDaoImpl;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.UserService;
      import service.impl.UserServiceImpl;
      import test.Mybean;
      import test.User;
      import test.User02;
      
      public class Test01 {
      
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean04.xml");
      
              //獲取配置創(chuàng)建的對象,實際將返回User類實例。這里的 getBean() 方法要同時寫上 id 和類.class,否則可能報錯
              User user = context.getBean("mybean", User.class);
              user.setName("wen");
              System.out.println(user);
          }
      }

       

      2.3、bean的作用域(作用范圍)

      bean 的作用域可以理解為 bean 的作用范圍。Spring3 中為 Bean 定義了5種作用域,分別為 singleton(單例,默認值)、prototype、request、session 和 global session。

       

      2.3.1、singleton作用域(單例,默認值)

      singleton:單例模式,Singleton 作用域是Spring 中的默認作用域。在單例模式下,多次通過 getBean() 方法獲取同一個 bean 時,獲取到的實例對象實際上都是同一個對象。在不同配置文件中,即使 bean 標(biāo)簽的 class 指向的是同一個類,也不是同一個bean,此時創(chuàng)建的不是同一個實例對象。在同一個配置文件中,指向的是不同的class,也不會是同一個實例對象。

      Singleton 是單例類型,在加載配置文件時即創(chuàng)建 bean 對象,不管你是否使用,他都存在了,每次獲取到的對象都是同一個對象。

      該模式在多線程下是不安全的。Singleton 作用域是Spring 中的缺省作用域,也可以顯示的將 Bean 定義為 singleton 模式,配置為:

      <bean id="..." class="..." scope="singleton"></bean>

       

      2.3.1、prototype作用域

      prototype:原型模式,多實例。在每次通過 Spring 容器獲取 prototype 定義的 bean 時,容器都會創(chuàng)建一個新的 Bean 實例,每個 Bean 實例都有自己的屬性和狀態(tài)。跟單例 singleton 不同, singleton 全局只有一個對象。

      <bean id="SingletonBean" class="com.spring.demo.SingletonBean" scope="prototype"></bean>

       

      2.4、bean的生命周期

      bean 的生命周期,即 bean 從創(chuàng)建到銷毀的過程。

      bean 的生命周期如下:

      1. 實例化。通過構(gòu)造器創(chuàng)建 bean 實例
      2. 屬性賦值。設(shè)置 bean 的屬性(依賴注入)
      3. 調(diào)用后置處理器的 postProcessBeforeInitialization() 方法(需在 xml 中配置后置處理器,跟配置一個bean一樣,class指向后置處理器即可。后置處理器實際上就是一個實現(xiàn)了BeanPostProcessor接口的類)
      4. 初始化。調(diào)用 bean 標(biāo)簽 init-method 指定的類的方法,init-method 指定的方法由類定義,可進行一些初始化操作(需手動配置)。初始化完成后 bean 就可以使用了
      5. 調(diào)用后置處理器的 postProcessAfterInitialization() 方法
      6. 銷毀。當(dāng)容器關(guān)閉時,調(diào)用 bean 標(biāo)簽 destroy-method 指定的類的方法,destroy-method 指定的方法由類定義。(可調(diào)用ApplicationContextObj.close()方法來手動銷毀bean)

       

      3、IOC創(chuàng)建對象

      3.1、基于XML配置文件創(chuàng)建對象

      在spring配置文件中,使用 bean 標(biāo)簽就可以實現(xiàn)對象的創(chuàng)建。如下:

      <bean id="user" class="test.User"></bean>

      基于 xml 配置文件創(chuàng)建對象時,默認情況下是執(zhí)行該類的無參數(shù)構(gòu)造函數(shù)來創(chuàng)建對象的,所以如果該類沒有無參構(gòu)造函數(shù)程序?qū)箦e。

       

      bean 標(biāo)簽常見屬性:

      • id:給該類指定一個唯一標(biāo)識。每個<bean ...>都有一個id標(biāo)識,相當(dāng)于Bean的唯一ID。
      • class:類的完整類名

       

      3.2、注解方式創(chuàng)建對象(@Component、@Service、@Controller、@Repository

      使用Spring的IoC容器,實際上就是通過類似XML這樣的配置文件,把我們自己的Bean的依賴關(guān)系描述出來,然后讓容器來創(chuàng)建并裝配Bean。一旦容器初始化完畢,我們就直接從容器中獲取Bean使用它們。使用XML配置的優(yōu)點是所有的Bean都能一目了然地列出來,并通過配置注入能直觀地看到每個Bean的依賴。它的缺點是寫起來非常繁瑣,每增加一個組件,就必須把新的Bean配置到XML中。我們可以使用注解的方式進行配置,讓Spring自動掃描Bean并組裝它們。

      spring 針對 bean 管理中創(chuàng)建對象提供了四種注解:

      1. @Component
      2. @Service 業(yè)務(wù)層
      3. @Controller web層
      4. @Repository 持久層

      創(chuàng)建對象有四種注解,但目前來說,這四個注解的功能都是一樣的。只是建議 @Service 用在業(yè)務(wù)層,@Controller 用在 web 層,@Repository 用在持久層,但并不是強制的,可以混用。有四個注解只是為了后續(xù)的版本當(dāng)中進行功能擴展 。

       

      使用注解創(chuàng)建對象:

      先導(dǎo)入依賴包,除了 spring 的幾個基本包外,還需要導(dǎo)入 aop 包:

      然后需要開啟組件掃描。開啟組件掃描需要先引入命名空間,然后就可以使用 <context:component-scan base-package="要掃描的包路徑"></context:component-scan> 標(biāo)簽開啟組件掃描:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      
          <!--開啟組件掃描。base-package寫包名,若要掃描多個包,可以用逗號隔開,或者直接寫多個包共用的上級目錄-->
          <context:component-scan base-package="test, service.impl"></context:component-scan>
      </beans>

      開啟組件掃描后就可以給類添加注解了,下面的@Component可以換成 @Service等其它的幾個注解,效果都一樣。

      package test;
      
      import org.springframework.stereotype.Component;
      
      
      //注解里面value屬性名及值都可以省略不寫,即寫成@Compnent,此時bean的id默認是類名首字母小寫后的名稱
      @Component(value = "user")   //相當(dāng)于<bean id="user" class="完整類名"></bean>
      public class User {
          public void add() {
              System.out.println("add...");
          }
      }

      驗證,使用bean:

      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import test.User;
      
      public class Test {
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              User user = (User) context.getBean("user");
              System.out.println(user);
              user.add();
          }
      }

       

      3.2.1、組件掃描配置

      開啟組件掃描后,默認情況是配置的包下的所有類、所有注解都會掃描。我們可以配置只掃描哪些注解,或者不掃描哪些注解。

      配置只掃描 @Controller 注解,注意,要加上user-default-filters標(biāo)簽:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      
          <context:component-scan base-package="test, service" use-default-filters="false">   <!--use-default-filters表示不使用默認filter-->
              <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
          </context:component-scan>
      
      </beans>

      配置了只掃描 @Controller 注解后,其他注解將不會被掃描到,如果使用其他注解的 bean 程序?qū)箦e:No bean named 'xxx' available...

       

      配置不掃描@Controller 注解,注意,不能加上user-default-filters標(biāo)簽:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      
          <context:component-scan base-package="test, service">
              <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
          </context:component-scan>
      
      </beans>

       

      3.2.2、注解配置bean作用域(@Scope())

      對于Spring容器來說,當(dāng)我們把一個Bean標(biāo)記為添加注解比如@Component后,它就會自動為我們創(chuàng)建一個單例(Singleton),即容器初始化時創(chuàng)建Bean,容器關(guān)閉前銷毀Bean。在容器運行期間,我們調(diào)用getBean(Class)獲取到的Bean總是同一個實例。

      我們可以通過 @Scope() 注解來配置 bean 的作用域:

      比如聲明為 prototype 作用域:

      @Component
      @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // @Scope("prototype")
      public class MailSession {
          ...
      }

       

      4、IOC依賴注入(注入屬性)

      4.1、基于XML配置文件的依賴注入

      我們可以在 xml 文件中直接配置在創(chuàng)建該類的對象時,同時給該類配置屬性。

      基于 xml 配置文件來注入類屬性有兩種方式:

      1. 通過類的 set() 方法注入屬性。類似 setName() 等等
      2. 通過類的有參構(gòu)造函數(shù)注入屬性

       

      4.1.1、通過set()方法注入屬性(property標(biāo)簽)

      我們在類中定義了 setter,就可以在 spring 的配置文件中通過配置直接給該類實例指定屬性值。代碼示例如下:

      User類:

      public class User {
          private String name;
      
          private int age;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      }

      配置文件:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <!-- 配置創(chuàng)建的對象-->
          <bean id="user" class="springtest.User">
              <property name="name" value="wen"></property>
              <property name="age" value="12"></property>
          </bean>
      </beans>

      使用上述配置后,在創(chuàng)建 User 類時會自動給該類注入屬性。

      測試代碼:

      package test;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import springtest.User;
      
      public class test01 {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              User user = (User) context.getBean("user");
      
              System.out.println(user.getName() + user.geAge());  //輸出 wen12
          }
      }

       

      4.1.2、通過有參構(gòu)造函數(shù)注入屬性(constructor-arg標(biāo)簽)

      如果一個類中有有參構(gòu)造函數(shù),我們就可以通過有參構(gòu)造來給該類的實例注入屬性。當(dāng)類中有有參構(gòu)造函數(shù),我們也只能使用有參構(gòu)造來注入屬性,否則將會報錯。

      代碼示例如下:

      User 類:

      package springtest;
      
      public class User {
          private String name;
      
          private int age;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          //有參構(gòu)造。定義了有參構(gòu)造則編譯器不會自動創(chuàng)建無參構(gòu)造,所以配置文件中如果不使用有參構(gòu)造來注入屬性的話程序會報錯
          public User(String name, int age) {
              this.name = name;
              this.age = age;
          }
      }

      配置文件:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean id="user" class="springtest.User">
              <!-- 也可以使用索引的形式 <constructor-arg index="0" value="wen"></constructor-arg> -->
              <constructor-arg name="name" value="wen"></constructor-arg>   
              <constructor-arg name="age" value="11"></constructor-arg>
          </bean>
      </beans>

      使用上述配置后,在創(chuàng)建 User 類時會自動調(diào)用該類的有參構(gòu)造來給該類注入屬性。

      測試代碼:

      package test;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import springtest.User;
      
      public class test01 {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              User user = (User) context.getBean("user");
              System.out.println(user.getName() + user.geAge());  //輸出 wen11
          }
      }

       

      4.1.3、注入外部bean(注入類)

      如果注入的屬性值是booleanintString這樣的數(shù)據(jù)類型,可以通過value注入。如果注入的屬性值是類,則可以通過 ref 注入。

      示例:

      UserServiceImpl 類中有一個 setter 需要設(shè)置 userDao 屬性為 UserDao 類:

      public class UserServiceImpl implements UserService {
          private UserDao userDao;
      
          public void setUserDao(UserDao userDao) {
              this.userDao = userDao;
          }
      
          public void add() {
              this.userDao.add();
          }
      }

      在傳統(tǒng)程序中,需要調(diào)用 setUserDao() 方法來主動將一個 UserDao 類注入。寫法如下:

      public class Test01 {
      
          public static void main(String[] args) {
              UserServiceImpl userServiceImpl = new UserServiceImpl();
              UserDao userDao = new UserDaoImpl();
              userServiceImpl.setUserDao(userDao);   //調(diào)用 setUserDao 注入UserDao類
              userServiceImpl.add();
          }
      }

       

      使用spring配置文件可以直接將 UserDao bean作為屬性注入 UserService當(dāng)中,實際上相當(dāng)于調(diào)用了 setUserDao() 方法。配置文件如下:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean name="userdao" class="dao.impl.UserDaoImpl"></bean>
      
          <bean name="userservice" class="service.impl.UserServiceImpl">
              <property name="userDao" ref="userdao"></property>
          </bean>
      </beans>

      Bean的順序不重要,Spring根據(jù)依賴關(guān)系會自動正確初始化。 

      測試代碼:

      package test.testDemo;
      
      import dao.UserDao;
      import dao.impl.UserDaoImpl;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.UserService;
      import service.impl.UserServiceImpl;
      import test.User;
      
      public class Test01 {
      
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean02.xml");
      
              UserServiceImpl userServiceImpl = context.getBean(UserServiceImpl.class);
              userServiceImpl.add();
          }
      }

       

      4.1.4、內(nèi)部bean注入類

      上面注入外部bean,實際上就是在外部建一個bean,然后將該bean賦值給 UserService bean的屬性。除了上面的寫法,我們還可以采用內(nèi)部bean的寫法來將一個類注入給另一個類的屬性。

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean name="userservice" class="service.impl.UserServiceImpl">
              <property name="userDao">
                  <bean id="userdao" class="dao.impl.UserDaoImpl"></bean>   <!--  如果該內(nèi)部bean還需要注入屬性,可以再給該內(nèi)部bean配置property -->
              </property>
          </bean>
      </beans>

       

      4.1.5、注入集合

       給類注入集合,示例如下:

      package test;
      
      import java.util.*;
      
      public class User02 {
          private String[] myArr;
          private List<String> myList;
          private Set<String> mySet;
          private Map<String, String> myMap;public void setMyArr(String[] myArr) {
              this.myArr = myArr;
          }
      
          public void setMyList(List<String> myList) {
              this.myList = myList;
          }
      
          public void setMySet(Set<String> mySet) {
              this.mySet = mySet;
          }
      
          public void setMyMap(Map<String, String> myMap) {
              this.myMap = myMap;
          }
      }

      配置文件:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean id="user02" class="test.User02">
              <!-- 給數(shù)組注入數(shù)據(jù) -->
              <property name="myArr">
                  <array>
                      <value>AAA</value>
                      <value>BBB</value>
                  </array>
              </property>
      <!-- 注入 list 集合數(shù)據(jù) --> <property name="myList"> <list> <value>AAA</value> <value>BBB</value> </list> </property>
      <!-- 注入 set 集合數(shù)據(jù) --> <property name="mySet"> <set> <value>AAA</value> <value>BBB</value> </set> </property>
      <!-- 注入 Map 數(shù)據(jù) --> <property name="myMap"> <map> <entry key="testA" value="aaa"></entry> <entry key="testB"> <value>bbb</value> </entry> </map> </property> </bean> </beans>

       

      上面的集合當(dāng)中的元素的值都是字符串,如果集合當(dāng)中的元素是類的話,我們可以使用 ref 標(biāo)簽來注入:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean id="user" class="test.User02">
              <!-- myList2集合的元素是User類實例對象 -->
              <property name="myList2">
                  <list>
                      <ref bean="user01"></ref>
                      <ref bean="user02"></ref>
                  </list>
              </property>
          </bean>
      
          <bean id="user01" class="test.User"></bean>
          <bean id="user02" class="test.User"></bean>
      </beans>

       

      上面將集合注入屬性只是注入了某個類當(dāng)中,我們可以把集合提取出來,多個類就可以重用這些集合。

      首先我們需要先導(dǎo)入 util 命名空間,util命名空間提供了集合相關(guān)的配置,在使用命名空間前要導(dǎo)入util命名空間,如下:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
      
      </beans>

      下面提取出一個 List 并在 bean 中注入,代碼示例:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
      
          <util:list id="userList">
              <value>張三</value>
              <value>李四</value>
              <value>王五</value>
          </util:list>
      
          <bean id="user02" class="test.User02">
              <!-- 注入 list 集合數(shù)據(jù) -->
              <property name="myList" ref="userList"></property>
          </bean>
      
      </beans>

       

      4.1.6、注入其它類型值(空值、特殊符號)

      注入空值:

      <bean id="user" class="test.User">
          <property name="name">
              <null></null>
          </property>
          <property name="age" value="12"></property>
      </bean>

      注入特殊符號:

      XML中共有5個特殊的字符,分別是:&<> “’。如果配置文件中的注入值包括這些特殊字符,就需要進行特別處理。

      有兩種解決方法:

      1. 采用本例中的<![CDATA[ ]]>特殊標(biāo)簽,將包含特殊字符的字符串封裝起來。<![CDATA[ ]]>的作用是讓XML解析器將標(biāo)簽中的字符串當(dāng)作普通的文本對待,以防止某些字符串對XML格式造成破壞。
      2. 使用XML轉(zhuǎn)義序列表示這些特殊的字符,這5個特殊字符所對應(yīng)XML轉(zhuǎn)義序列如下:

       示例:給 name 屬性賦值為 <<wen>>

      <bean id="user" class="test.User">
          <property name="name" value="&lt;&lt;wen&gt;&gt;"></property>
          <property name="age" value="12"></property>
      </bean>

       

      <bean id="user" class="test.User">
          <property name="name">
              <value><![CDATA[<<wen>>]]></value>   <!-- 給name賦值為<<wen>> -->
          </property>
          <property name="age" value="12"></property>
      </bean>

       

      4.1.7、自動裝配(autowire)

      傳統(tǒng)的XML方式配置 Bean 組件都是通過 <property> 標(biāo)簽為Bean的屬性注入所需的值,當(dāng)需要維護的Bean組件及需要注入的屬性更多時,勢必會增加配置的工作量,這時我們可以使用自動裝配。

      使用自動裝配只需給 bean 標(biāo)簽添加 autowire 屬性即可。配置示例:

      <bean id="user" class="test.User" autowire="byName"/>

      通過設(shè)置<bean>元素的autowire屬性指定自動裝配,代替了通過<property>標(biāo)簽顯示指定Bean的依賴關(guān)系。由BeanFactory檢查XML配置文件的內(nèi)容,為Bean自動注入依賴關(guān)系。

      Spring提供了多種自動裝配方式,autowire屬性常用的取值如下所示

      • no:不使用自動裝配。Bean依賴關(guān)系必須通過property元素定義。
      • byName:根據(jù)屬性名自動裝配。BeanFactory查找容器中的全部Bean,找出 id 與屬性的 setter 方法入?yún)⑵ヅ涞腂ean。找到即自動注入,否則什么都不做。
      • byType:根據(jù)屬性類型自動裝配。BeanFactory查找容器中的全部Bean,如果正好有一個與依賴屬性類型相同的Bean,就自動裝配這個屬性;但是如果有多個這樣的Bean,Spring無法決定注入哪個Bean,就拋出一個致命異常;如果沒有匹配的Bean,就什么都不會發(fā)生,屬性不會被設(shè)置。
      • constructor:與byType的方式類似,不同之處在于它應(yīng)用于構(gòu)造器參數(shù)。如果在容器中沒有找到與構(gòu)造器參數(shù)類型一致的Bean,那么將會拋出異常

       

      自動裝配的局限性:

      • 不是所有類型都可以使用自動裝配,不能自動裝配的數(shù)據(jù)類型有:Object、基本數(shù)據(jù)類型(Date、CharSequence、Number、URI、URL、Class、String)等等。因為自動裝配是注入了一個bean。
      • 自動裝配不如顯式裝配精確,如果可能的話盡量使用顯式裝配。

       

      實例:

      假設(shè) User 類中有一個屬性類型為 Animal 類:

      public class User {
          private Animal animal;
      
          public Animal getAnimal() {
              return animal;
          }
      
          public void setAnimal(Animal animal) {
              this.animal = animal;
          }
      }

      此時我們可以使用自動裝配:

      <?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean id="user" class="test.User" autowire="byName"></bean>
      
          <bean id="animal" class="test.Animal"></bean>
      </beans>

      上面使用 byName 類型的自動裝配,id 為animal 的 bean 將匹配到 User 類中的 setter,所以會將 animal 類注入 User 中的 animal 屬性當(dāng)中。(上面配置直接改成byType也可以)

      驗證代碼:

      package UnitDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import test.User;
      import test.User02;
      
      public class Test {
          public static void main(String[] args) {
              ApplicationContext context2 = new ClassPathXmlApplicationContext("bean01.xml");
              User user = (User) context2.getBean("user");
              user.getAnimal().setName("cat");
              System.out.println(user.getAnimal().getName());
          }
      }

       

      4.1.8、引入properties配置文件

      如果配置過多,在一個 xml 文件里面維護可能相對比較困難,這時我們可以在一個 propreties 配置文件中配置一些屬性,然后再在 xml 配置文件中引入 propreties 文件的配置。比如可用于連接數(shù)據(jù)庫的配置。

      示例:

      在項目的 src 目錄下建一個 properties 類型文件 jdbc.properties,properties 類型文件的內(nèi)容是鍵值對形式。往該文件寫入以下內(nèi)容:

      prop.driverClass=com.mysql.jdbc.Driver
      prop.url=jdbc:mysql://localhost:3306/userDB
      prop.username=root
      prop.password=123456

      然后就可以在 xml 配置文件中引入該文件,在引入之前我們需要先寫 context 命名空間:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      
      </beans>

      最后就可以通過 <context> 標(biāo)簽將 properties 文件引入,并且可以用 ${} 來使用 properties 文件的值:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      
          <!--引入外部屬性文件-->
          <context:property-placeholder location="classpath:jdbc.properties"/>
          
          <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <property name="driverClassName" value="${prop.driverClass}"></property>  <!--通過${}使用外部配置文件的值-->
              <property name="url" value="${prop.url}"></property>
              <property name="username" value="${prop.username}"></property>
              <property name="password" value="${prop.password}"></property>
          </bean>
      </beans>

       

      4.2、注解方式依賴注入(@Autowired、@Qualifier、@Resource、@Value)

      spring 注解注入屬性提供了幾種注解:

      1. @Autowired:根據(jù)屬性類型進行自動裝配,即 byType
      2. @Qualifier:根據(jù)屬性名稱進行自動裝配,即 byName。需要配合@Autowired進行使用,用于在@Autowired匹配到多個類時,指定究竟使用哪個類來進行注入。
      3. @Resource:既可以根據(jù)類型注入,也可以根據(jù)名稱注入。不指定 name 和 type 則自動按照 byName 方式進行裝配,如果沒有匹配成功,則回退為一個原始類型進行匹配,如果匹配成功則自動裝配。
      4. @Value:注入基本數(shù)據(jù)類型數(shù)據(jù)

      使用注解,比如@Autowired,就相當(dāng)于把指定類型的Bean注入到指定的字段中。和XML配置相比,注解的方式大幅簡化了注入,因為它不但可以寫在set()方法上,還可以直接寫在字段上,甚至可以寫在構(gòu)造方法中。

      @Component
      public class UserService {
          MailService mailService;
      
          public UserService(@Autowired MailService mailService) {
              this.mailService = mailService;
          }
          ...
      }

       

      4.2.1、@Autowired(根據(jù)類型裝配)

      @Autowired 注解會根據(jù)屬性類型進行自動裝配,即 byType。默認情況下它要求依賴對象必須存在,如果不存在,程序?qū)箦e。但我們也可以設(shè)置它的required屬性為false,來讓它的依賴對象如果允許為 null 值,@Autowired(required = false)

       

      實例:比如在 UserServiceImpl 類中的某個屬性注入 UserDaoImpl 類型值。

      UserDaoImpl 代碼:只需給實現(xiàn)類添加注解即可,接口不能添加注解

      package dao.impl;
      
      import dao.UserDao;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public class UserDaoImpl implements UserDao {
      
          @Override
          public void add() {
              System.out.println("userdaoimpl add...");
          }
      }

      UserServiceImpl 代碼:

      package service.impl;
      
      import dao.UserDao;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import service.UserService;
      
      @Service
      public class UserServiceImpl implements UserService {
      
          //不需要添加set方法
          @Autowired
          private UserDao userDao;
      
          @Override
          public void add() {
              System.out.println("userserviceimpl add...");
              userDao.add();
          }
      }

      驗證代碼:

      package UnitDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.UserService;
      import test.User;
      
      public class Test {
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              UserService userService = (UserService) context.getBean("userServiceImpl");
              userService.add();   //將輸出 userserviceimpl add...    userdaoimpl add...
          }
      }

       

      4.2.2、@Qualifier(通過名稱標(biāo)識唯一類注入@Autowired中)

      使用 @Autowired 時,如果某個類有多個實現(xiàn)類,則 spring 無法識別究竟將哪個實現(xiàn)類來進行注入,此時程序?qū)苯訄箦e。此時我們可以將 @Autowired 和 @Qualifier 搭配使用,@Qualifier 可通過名稱來標(biāo)識究竟使用哪個類來進行注入。

      @Qualifier 用法示例:

      假設(shè) UserDao 有多個實現(xiàn)類:UserDaoImpl、UserDaoImpl02,UserDaoImpl02代碼如下:

      package dao.impl;
      
      import dao.UserDao;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public class UserDaoImpl02 implements UserDao {
          @Override
          public void add() {
              System.out.println("userdaoimpl02 add...");
          }
      }

      此時如果我們直接使用 @Autowired 程序?qū)苯訄箦e,因為 spring 無法識別究竟使用哪個類來進行注入。所以我們可以使用 @Qualifier("bean標(biāo)識") 來指定究竟使用哪個類來進行注入:

      package service.impl;
      
      import dao.UserDao;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.stereotype.Service;
      import service.UserService;
      
      @Service
      public class UserServiceImpl implements UserService {
      
          @Autowired
          @Qualifier("userDaoImpl02")
          private UserDao userDao;
      
          @Override
          public void add() {
              System.out.println("userserviceimpl add...");
              userDao.add();
          }
      }

      驗證代碼:

      package UnitDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.UserService;
      import test.User;
      
      public class Test {
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              UserService userService = (UserService) context.getBean("userServiceImpl");
              userService.add();   //將輸出 userserviceimpl add...    userdaoimpl02 add...
          }
      }

       

       4.2.3、@Resource(byType、byName)

      匹配規(guī)則:

      1. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常。
      2. 如果指定了type,則從上下文中找到類似匹配的唯一bean進行裝配,找不到或是找到多個,都會拋出異常。
      3. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常。
      4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配。

      UserDaoImpl02 實現(xiàn)類:

      package dao.impl;
      
      import dao.UserDao;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public class UserDaoImpl02 implements UserDao {
          @Override
          public void add() {
              System.out.println("userdaoimpl02 add...");
          }
      }

      UserServiceImpl 實現(xiàn)類:

      package service.impl;
      
      import dao.UserDao;
      import org.springframework.stereotype.Service;
      import service.UserService;
      
      import javax.annotation.Resource;
      
      @Service
      public class UserServiceImpl implements UserService {
          @Resource(name = "userDaoImpl02")
          private UserDao userDao;
      
          @Override
          public void add() {
              System.out.println("userserviceimpl add...");
              userDao.add();
          }
      }

      驗證代碼:

      package UnitDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.UserService;
      import test.User;
      
      public class Test {
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              UserService userService = (UserService) context.getBean("userServiceImpl");
              userService.add();   //將輸出 userserviceimpl add...   userdaoimpl02 add...
          }
      }

       

      4.2.4、@Value(注入基本數(shù)據(jù)類型)

      @Value 注解即注入一個基本類型數(shù)據(jù)。

      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.stereotype.Component;
      
      @Component(value = "user")
      public class User {
      
          @Value(value = "wen")
          private String name;
      
          public void showName() {
              System.out.println(this.name);
          }
      }

      驗證代碼:

      package UnitDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import service.UserService;
      import test.User;
      
      public class Test {
          public static void main(String[] args) {
              //加載spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean01.xml");
      
              //獲取配置創(chuàng)建的對象
              User user = (User) context.getBean("user");
              user.showName();   //輸出 wen
          }
      }

       

      4.2.5、注入list

      有些時候,我們會有一系列接口相同,不同實現(xiàn)類的Bean。例如,注冊用戶時,我們要對email、password和name這3個變量進行驗證。為了便于擴展,我們先定義驗證接口:

      public interface Validator {
          void validate(String email, String password, String name);
      }

      然后,分別使用3個Validator對用戶參數(shù)進行驗證:

      @Component
      public class EmailValidator implements Validator {
          public void validate(String email, String password, String name) {
              if (!email.matches("^[a-z0-9]+\\@[a-z0-9]+\\.[a-z]{2,10}$")) {
                  throw new IllegalArgumentException("invalid email: " + email);
              }
          }
      }
      
      @Component
      public class PasswordValidator implements Validator {
          public void validate(String email, String password, String name) {
              if (!password.matches("^.{6,20}$")) {
                  throw new IllegalArgumentException("invalid password");
              }
          }
      }
      
      @Component
      public class NameValidator implements Validator {
          public void validate(String email, String password, String name) {
              if (name == null || name.isBlank() || name.length() > 20) {
                  throw new IllegalArgumentException("invalid name: " + name);
              }
          }
      }

      最后,我們通過一個Validators作為入口進行驗證:

      @Component
      public class Validators {
          @Autowired
          List<Validator> validators;
      
          public void validate(String email, String password, String name) {
              for (var validator : this.validators) {
                  validator.validate(email, password, name);
              }
          }
      }

      注意到Validators被注入了一個List<Validator>,Spring會自動把所有類型為Validator的Bean裝配為一個List注入進來,這樣一來,我們每新增一個Validator類型,就自動被Spring裝配到Validators中了,非常方便。

      因為Spring是通過掃描classpath獲取到所有的Bean,而List是有序的,要指定List中Bean的順序,可以加上@Order注解:

      @Component
      @Order(1)
      public class EmailValidator implements Validator {
          ...
      }
      
      @Component
      @Order(2)
      public class PasswordValidator implements Validator {
          ...
      }
      
      @Component
      @Order(3)
      public class NameValidator implements Validator {
          ...
      }

       

      4.2.5、初始化和銷毀

      有些時候,一個Bean在注入必要的依賴后,需要進行初始化(監(jiān)聽消息等)。在容器關(guān)閉時,有時候還需要清理資源(關(guān)閉連接池等)。我們通常會定義一個init()方法進行初始化,定義一個shutdown()方法進行清理,然后,引入JSR-250定義的Annotation:

      在Bean的初始化和清理方法上標(biāo)記@PostConstruct@PreDestroy

      @Component
      public class MailService {
          @Autowired(required = false)
          ZoneId zoneId = ZoneId.systemDefault();
      
          @PostConstruct
          public void init() {
              System.out.println("Init mail service with zoneId = " + this.zoneId);
          }
      
          @PreDestroy
          public void shutdown() {
              System.out.println("Shutdown mail service");
          }
      }

      Spring容器會對上述Bean做如下初始化流程:

      • 調(diào)用構(gòu)造方法創(chuàng)建MailService實例;
      • 根據(jù)@Autowired進行注入;
      • 調(diào)用標(biāo)記有@PostConstructinit()方法進行初始化。

      而銷毀時,容器會首先調(diào)用標(biāo)記有@PreDestroyshutdown()方法。Spring只會根據(jù)注解查找無參數(shù)方法,對方法名不作要求。

       

      4.2.6、完全注解開發(fā)(@Configuration)

      我們可以通過 spring 配置類來實現(xiàn)完全注解開發(fā),即不需要 xml 配置文件。

      用 @Configuration 注解來新建配置類,比如命名為 SpringConfig,以此替代 xml 配置文件:

      import org.springframework.context.annotation.ComponentScan;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      @ComponentScan(basePackages = {"test", "dao", "service"})  //指定 spring 在初始化容器時要掃描的包。作用和在 spring 的 xml 配置文件中的<context:component-scan base-package=“org.woster”/>是一樣的。
      public class SpringConfig {
      }

      使用@ComponentScan來告訴容器需要掃描的包,如果不指定參數(shù),即只有@ComponentScan,則會自動搜索當(dāng)前配置類所在的包以及子包。

      使用配置類獲取 ApplicationContext 對象的語法跟使用配置文件的不太一樣,除此之外,其他情況都一樣:

      package UnitDemo;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import test.SpringConfig;
      import test.User;
      
      public class Test {
          public static void main(String[] args) {
              ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
              User user = (User) context.getBean("user");
              user.showName();
          }
      }

       

      posted @ 2021-03-31 16:20  wenxuehai  閱讀(239)  評論(0)    收藏  舉報
      //右下角添加目錄
      主站蜘蛛池模板: 国精品91人妻无码一区二区三区| 亚洲精品一区二区口爆| 国产在线拍揄自揄视频网试看| 91中文字幕在线一区| 亚洲尤码不卡av麻豆| 久久精品一本到99热免费| 久久久综合香蕉尹人综合网| av明星换脸无码精品区| 亚洲人妻系列中文字幕| 亚洲欧洲日产国码久在线| 亚洲人成小说网站色在线| 1000部拍拍拍18勿入免费视频| 国产精品爆乳在线播放第一人称| 定兴县| 日韩丝袜亚洲国产欧美一区| 亚洲综合一区二区三区视频| 国产精品剧情亚洲二区| 里番全彩爆乳女教师| 九九热精品视频免费在线| 四虎永久免费高清视频| 人人人澡人人肉久久精品| 亚洲国产精品特色大片观看完整版| 精品人妻蜜臀一区二区三区| 亚洲乱理伦片在线观看中字| 国产AV福利第一精品| 亚洲精品成a人在线观看| 成人精品一区日本无码网| 午夜福利yw在线观看2020| 镇巴县| 熟妇激情一区二区三区| 男女性高爱潮免费网站| 精品久久久久中文字幕APP| 中文字幕亚洲综合小综合| 亚洲国产成人无码av在线影院 | 欧美精欧美乱码一二三四区| 长宁县| 在线视频中文字幕二区| 久久精品丝袜高跟鞋| 无码人妻精品一区二区三区下载| 国产精品v片在线观看不卡| 四虎影视www在线播放|