1. 程式人生 > >Spring定義bean的三種方式和自動注入

Spring定義bean的三種方式和自動注入

前言:隨著一個專案規模的增大,我們不得不引入許多Java bean物件,而這些物件一般來說是在Spring的配置檔案applicationContext.xml中進行配置的,這樣就聲明瞭這是一個由Spring容器管理的bean物件。這種做法必然會導致Spring的配置檔案的可讀性很差。在Spring中,我們有一些小技巧可以避免這種情況。這就是本篇文章所討論的。

1、定義bean的三種途徑:

方法一:基於XML的bean定義(需要提供setter方法)
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.     <beanid="student"class="test.Student">
  6.         <propertyname="name"value="張三"/>
  7.         <propertyname="teacher"
    ref="teacher"/>
  8.     </bean>
  9.     <beanid="teacher"class="test.Teacher">
  10.         <propertyname="name"value="李四"/>
  11.     </bean>
  12. </beans>
  13. 方法二:基於註解的bean定義(不需要提供setter方法)
Spring為此提供了四個註解,這些註解的作用與上面的XML定義bean效果一致,在於將元件交給Spring容器管理。元件的名稱預設是類名(首字母變小寫),也可以自己修改: @Component:當對元件的層次難以定位的時候使用這個註解 @Controller:表示控制層的元件 @Service:表示業務邏輯層的元件 @Repository:表示資料訪問層的元件 使用這些註解的時候還有一個地方需要注意,就是需要在applicationContext.xml中宣告<contex:component-scan...>一項,指明Spring容器掃描元件的包目錄。
  1. @Component
    ("teacher")  
  2. publicclass Teacher {  
  3.     @Value("李四")  
  4.     private String name;  
  5.     public String getName() {  
  6.         return name;  
  7.     }  
  8. }  
  1. @Component("student")  
  2. publicclass Student {  
  3.     @Value("張三")  
  4.     private String name;  
  5.     @Resource
  6.     private Teacher teacher;  
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.     public Teacher getTeacher() {  
  11.         return teacher;  
  12.     }  
  13. }  
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xmlns:context="http://www.springframework.org/schema/context"
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.        http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.        http://www.springframework.org/schema/context  
  8.        http://www.springframework.org/schema/context/spring-context.xsd">
  9.     <!--掃描元件的包目錄-->
  10.     <context:component-scanbase-package="test"/>
  11. </beans>
  1. publicclass Main {  
  2.     publicstaticvoid main(String args[]){  
  3.         FileSystemXmlApplicationContext context=new FileSystemXmlApplicationContext("applicationContext.xml的絕對路徑");  
  4.         Student student= (Student) context.getBean("student");  
  5.         Teacher teacher= (Teacher) context.getBean("teacher");  
  6.         System.out.println("學生的姓名:"+student.getName()+"。老師是"+student.getTeacher().getName());  
  7.         System.out.println("老師的姓名:"+teacher.getName());  
  8.     }  

方法三:基於Java類的bean定義(需要提供setter方法)
  1. @Configuration
  2. publicclass BeansConfiguration {  
  3.     @Bean
  4.     public Student student(){  
  5.         Student student=new Student();  
  6.         student.setName("張三");  
  7.         student.setTeacher(teacher());  
  8.         return student;  
  9.     }  
  10.     @Bean
  11.     public Teacher teacher(){  
  12.         Teacher teacher=new Teacher();  
  13.         teacher.setName("李四");  
  14.         return teacher;  
  15.     }  
  16. }  
  1. publicclass Main {  
  2.     publicstaticvoid main(String args[]){  
  3.         AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(BeansConfiguration.class);  
  4.         Student student= (Student) context.getBean("student");  
  5.         Teacher teacher= (Teacher) context.getBean("teacher");  
  6.         System.out.println("學生的姓名:"+student.getName()+"。老師是"+student.getTeacher().getName());  
  7.         System.out.println("老師的姓名:"+teacher.getName());  
  8.     }  

二、Spring的自動注入

  • Spring提供了五種自動裝配的型別
no:顧名思義, 顯式指明不使用Spring的自動裝配功能 byName:根據屬性和元件的名稱匹配關係來實現bean的自動裝配 byType:根據屬性和元件的型別匹配關係來實現bean的自動裝配,有多個適合型別的物件時裝配失敗 constructor:與byType類似是根據型別進行自動裝配,但是要求待裝配的bean有相應的建構函式 autodetect:利用Spring的自省機制判斷使用byType或是constructor裝配
  • 基於XML的自動裝配
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.        http://www.springframework.org/schema/beans/spring-beans.xsd">
  6.     <beanid="student"class="test.Student"autowire="byName">
  7.         <propertyname="name"value="張三"/>
  8.     </bean>
  9.     <beanid="teacher"class="test.Teacher">
  10.         <propertyname="name"value="李四"/>
  11.     </bean>
  12. </beans>
這裡我並沒有顯式為Student物件注入Teacher屬性,而是使用autowired="byName"代替,這樣一來Spring會幫我們處理這些細節,將名字是teacher的元件注入到Student物件中。
  • 基於註解的自動裝配
其實上面已經應用過了,這裡再提一下@Resource和@Autowired的區別。@Resource預設是使用byName進行裝配,@Autowired預設使用byType進行裝配。
  1. @Component("teacher")  
  2. publicclass Teacher {  
  3.     @Value("李四")  
  4.     private String name;  
  5.     public String getName() {  
  6.         return name;  
  7.     }  
  8.     publicvoid setName(String name) {  
  9.         this.name = name;  
  10.     }  
  11. }  
  1. @Component("student")  
  2. publicclass Student {  
  3.     @Value("張三")  
  4.     private String name;  
  5.     @Resource
  6.     private Teacher teacher;  
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.     publicvoid setName(String name) {  
  11.         this.name = name;  
  12.     }  
  13.     public Teacher getTeacher() {  
  14.         return teacher;  
  15.     }  
  16.     publicvoid setTeacher(Teacher teacher) {  
  17.         this.teacher = teacher;  
  18.     }  


三、如何進行選擇?

其實說了這麼多,我們應該如何對這些不同方式進行權衡和選擇呢?這個見仁見智,我說說我常用的方式。
  • 定義bean:一般我使用基於註解的bean定義。這樣可以擺脫使用XML或是Java類對大量bean進行配置的噩夢,讓程式變得簡潔。註解還可以清楚地指明元件所在的層次。但是也有特殊的情況,比如說配置資料來源,也許某個元件並不是你寫的(來自於Spring或是第三方jar包裡面的元件等),你沒有辦法在這些元件裡面加上這些註解使之成為Spring容器管理的bean(別人也不會為你加上這些註解,因為他們不知道你會使用到哪些元件)。這種情況下就得使用XML或是Java類進行配置了,個人比較喜歡XML配置。如下例子:
  1. <beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  2.         <propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>
  3.         <propertyname="url"value="jdbc:mysql://localhost:3306/study"/>
  4.         <propertyname="username"value="賬號"/>
  5.         <propertyname="password"value="密碼"/>
  6.     </bean>

  • 自動裝配:一般我使用基於註解的自動裝配。同樣也是為了減少XML配置檔案的“篇幅”。
  • 通過使用基於註解的bean定義和自動裝配,大大減少了XML配置檔案的長度,增加了程式的可讀性。