Spring Bean的3種裝配方式

 

Bean經常使用的裝配方式有3種:java

  • 基於xml的裝配
  • 基於Annotation(註解)的裝配
  • 基於Java類的裝配

 

 

基於xml的裝配

在xml文件中配置Bean。spring

若是依賴不少,xml配置文件會很臃腫,後期維護、升級不方便。自動裝配可解決這一問題。api

 

基於xml的自動裝配

在<bean>中使用autowired屬性完成依賴的自動裝配,再也不使用<property>手動注入setter方法中的依賴,簡化了配置,減小了xml中的代碼量。數組

autowire屬性的4個屬性值:app

  • no   不使用自動裝配。缺省autowire屬性時默認值就是no。
  • byName   根據setter方法的名稱來自動裝配
  • byType  根據所依來的類型(Bean)來自動裝配
  • constructor  根據構造函數的形參表的數據類型進行byType方式的自動裝配
  • default   全局自動裝配

 

一、byName

示例:函數

 1 class Student{
 2 
 3     private String name;
 4 
 5     public Student(String name){
 6         this.name=name;
 7     }
 8 
 9     public String getName(){
10         return name;
11     }
12 }
13 
14 
15 class Teacher{
16     private Student student;
17 
18     public void setStudent(Student student) {
19         this.student = student;
20     }
21 
22     public void say(){
23         System.out.println(student.getName()+",叫家長來一下。");
24     }
25 }

Teacher依賴於Student,依賴的對象要寫成成員變量的形式。若是要使用自動裝配,依賴對象的注入只能使用setter方式。測試

byName,name指的是setXxx()注入依賴的那個xxx,好比setStudent(Student student),name指的是student,將set後面的部分提出來,變成Camel寫法。name不是指形參名的student。this

 

xml中的配置:spa

  <bean id="student" class="my_package.Student">
        <constructor-arg value="張三" />
    </bean>

    <bean id="teacher" class="my_package.Teacher" autowire="byName" />

第一個Bean是基於xml的普通裝配,第二個Bean的配置是byName形式的自動裝配。prototype

byName自動裝配的執行過程:在這個Bean的定義中,找到setter方法,這裏是setStudent(),其name是student(set後面部分提出來,變成Camel寫法),根據這個name(student)找打到id/name是student的Bean實例,將這個實例自動注入。

因此對<bean>的id/name、setter方法的命名有嚴格要求。

 

本來是要用<property name ref="" />子元素注入依賴的,若是依賴較多,會寫一大堆<property>子元素。自動裝配,無論這個一Bean有多少個依賴,一句代碼搞定,減小了代碼量,由Spring容器自動注入依賴。但Spring容器要作更多的工做,裝配速度會變慢。

 

說明:自動裝配只能完成setter形式的依賴注入,不能完成構造器方式的依賴注入,且只能注入其它Bean,不能注入String、數組、集合等Java自帶的類型。

 

測試代碼:

1 public class Test {
2     public static void main(String[] args) {
3         ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
4         Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
5         teacher.say();
6     }
7 }

運行,控制檯打印出"張三,叫家長來一下。"。

 

 

二、byType

根據要注入的Bean的類型來自動裝配。

在上面的例子中,setStudent(Student student),要注入的依賴是Student類型的實例。

byType自動裝配的執行過程:在這個Bean的定義中,找到setter方法,找到setter方法要注入的Bean的類型(Student),在Spring容器中找到Student類型的實例,注入。

 

若是Spring容器中該依賴有多個配置,好比:

  <bean id="student" class="my_package.Student">
        <constructor-arg value="張三" />
    </bean>

    <bean id="student1" class="my_package.Student">
        <constructor-arg value="李四" />
    </bean>

它們都是Student這個Bean的配置,Spring容器不知道要注入的依賴是哪個,會報錯,因此依賴的bean只能有一個配置

 

這種是能夠的:

  <bean id="student" class="my_package.Student" scope="prototype">
        <constructor-arg value="張三" />
    </bean>

雖然Spring容器中可能有這個Bean的多個實例,但這些實例是同樣的。

 

示例:

將byName示例中的xml中的配置修改以下便可

  <bean id="student" class="my_package.Student">
        <constructor-arg value="張三" />
    </bean>
    
    <bean id="teacher" class="my_package.Teacher" autowire="byType" />

 

 

 

三、constructor

 1 class Student{
 2     public String getName(){
 3         return "張三";
 4     }
 5 }
 6 
 7 class Teacher{
 8     private Student student;
 9 
10 public Teacher(Student student){ 11 this.student=student; 12 } 13     
14     public void say(){
15         System.out.println(student.getName()+",叫家長來一下。");
16     }
17 }

須要用構造器注入依賴,Spring容器會自動根據構造器中參數類型,用byType方式注入對應類型的依賴。

只能有一個構造器,不然Spring容器不知道使用哪一個構造器。

 

xml中的配置:

    <bean id="student" class="my_package.Student" />

    <bean id="teacher" class="my_package.Teacher" autowire="constructor" />

 

 

 

四、default

<?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"
       default-autowire="byName">

    <bean id="student" class="my_package.Student">
        <constructor-arg value="張三" />
    </bean>

    <bean id="teacher" class="my_package.Teacher" autowire="default" />

在<beans>中設置默認的自動裝配方式,在須要使用自動裝配的<bean>指定autowire="default",這樣該<bean>使用的自動裝配方式就是<beans>中設置的默認方式。

統一了應用的自動裝配方式。

 

 

 

 

 

基於註解的裝配

基於xml裝配的方式,若是<bean>不少,xml文件依然很臃腫。基於註解的裝配解決了這一問題。

基於註解的裝配是最經常使用的。

 

Spring經常使用的註解:

  • @Autowired    按類型自動裝配(byType)。
  • @Qualifier   按名稱自動裝配,不能單用,須要和@Autowired配合使用(byName)。
  • @Resource    是byName、byType方式的結合。

記法:Autowired——Type,Qualifier——Name,ATQN。

 

示例  @Autowired

 1 class Student{
 2     private String name;
 3 
 4     public Student(String name){
 5         this.name=name;
 6     }
 7 
 8     public String getName(){
 9         return name;
10     }
11 }
12 
13 
14 class Teacher{
15  @Autowired 16     private Student student;
17 
18     public void say(){
19         System.out.println(student.getName()+",叫家長來一下。");
20     }
21 }

 

沒必要寫setter方法,也沒必要寫構造器。在依賴的對象上添加@Autowired註解(固然也能夠在setter方法上寫),即按照類型自動裝配依賴。

上面在Student類型的依賴上添加了@Autowired註解,會自動在Spring容器中,找到Student類型的Bean,注入。至關於byType

 

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"
       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 https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config />

    <bean id="student" class="my_package.Student">
        <constructor-arg value="張三" />
    </bean>

    <bean id="teacher" class="my_package.Teacher"/>

</beans>

 

基於註解的裝配都須要用<context:annotation-config />開啓註解裝配,這句代碼是告訴Spring容器,下面的這些bean使用的是註解裝配。

<bean>中不使用autowire屬性。

 

測試:

1 public class Test {
2     public static void main(String[] args) {
3         ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
4         Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
5         teacher.say();
6     }
7 }

能夠看到控制檯打印出"張三,叫家長來一下。"。

 

 

示例  @Qualifier

修改Teacher類代碼以下,其他不變。

1 class Teacher{
2 @Autowired 3 @Qualifier(value="student") 4     private Student student;
5 
6     public void say(){
7         System.out.println(student.getName()+",叫家長來一下。");
8     }
9 }

在依賴的Bean實例上添加@Qualifier,@Qualifier不能單獨用,還須要添加@Autowired。

@Qualifier是byName方式的自動裝配,須要用value指定依賴Bean的id/name,Spring容器根據這個value找到id/name爲vBean,注入。

可簡寫爲@Qualifier("student")。

 

 

示例  @Resource

1 class Teacher{
2     @Resource(name = "student") 3     private Student student;
4 
5     public void say(){
6         System.out.println(student.getName()+",叫家長來一下。");
7     }
8 }

先根據name找到Spring容器中name/id爲student的Bean,注入。即優先以getName方式。

若是找不到name/id爲指定值的Bean,或缺省name直接寫@Resource,則以默認的getName方式:寫在字段上默認name爲成員變量名(student),寫在setter方法上默認爲set後面部分得Camel寫法,好比setStudent()默認name爲student。

若是仍是找不到依賴的Bean,則以byType方式注入。

 

 

說明

  • 以上註解寫在字段上、setter方法上都可,都是注入一個依賴。
  • Spring提供了@Resource註解,但此註解須要第三方包javax.annotation-api.jar的支持。若是用Maven,會自動添加Spring依賴的第三方包,好比commons-logging.jar、javax.annotation.jar,若是是本身添加Spring的jar庫,則還須要手動添加Spring依賴的第三方jar包。
  • 須要在xml中用<context:annotation-config />開啓註解。

 

 

 

Spring經常使用的其它註解

  • @Service       將業務層(Service層)的類標識爲Spring容器中的Bean
  • @Controller   將控制層的類標識爲Spring容器中的Bean
  • @Repository    將數據訪問層(Dao層)的類標識爲Spring容器中的Bean
  • @Component   將一個類標識爲Spring容器中的Bean,至關於具備以上3個註解的功能。但通常都使用專門的,就是說一般使用上面3個註解,不多使用@Component。

 前3個是專用的,第四個是通用的。這些註解都只能在類(Bean)上使用。

 

示例

 1 @Service  2 class Student{
 3     public String getName(){
 4         return "張三";
 5     }
 6 }
 7 
 8 @Service  9 class Teacher{
10     @Resource(name = "student")
11     private Student student;
12 
13     public void say(){
14         System.out.println(student.getName()+",叫家長來一下。");
15     }
16 }

 

 

xml中的配置:

 <context:component-scan base-package="my_package" />

    <bean id="student" class="my_package.Student" /> 

須要使用 <context:component-scan  base-package="" />指定要掃描的包,這樣會Spring容器會自動掃描指定的包,若是包中有上面4個註解,就將之裝配爲Bean。

<context:component-scan  base-package="" />會自動開啓註解,因此沒必要再寫<context:annotataion-config />。

 

 

其實上面4個註解的做用至關於<bean  class=""   />。

標註了這4個註解的類,Spring會自動在xml中把這個類配置爲Bean,就是說在xml中沒必要寫<bean  class=""   />。

但只能是<bean class=""   />這樣基礎的配置,若是要<constructor-arg>、<property>傳遞Java自帶類型的參數,或其餘Bean必須使用這個Bean的id/name(這個Bean要配置id/name),就不能省略該Bean的配置。

 

上面的例子中,Teacher類缺省了<bean class="my_package.Teacher" />。

@Resource(name = "student")
    private Student student;

Teacher類要用到Student類的id/name,因此Student類寫了配置。

其實不寫Student類的配置,則會使用byType方式向Teacher注入依賴,也能夠。

<context:component-scan base-package="my_package" />這句代碼不能缺省。

 

 

自動裝配簡化了配置,減小了代碼量,但須要Spring容器作更多的工做,因此建立Bean的速度要慢一些。

相關文章
相關標籤/搜索