跟着剛哥學習Spring框架--通過XML方式配置Bean(三)


Spring配置Bean有兩種形式(XML和注解)

今天我們學習通過XML方式配置Bean

1、 Bean的配置方式

  通過全類名(反射)的方式

    

    √ id:標識容器中的bean。id唯一。

    √ class:bean的全類名,通過反射的方式在IOC容器中創建Bean,所以要求Bean中必須有無參的構造器

2、依賴注入的方式

  1)屬性注入:通過setter方法注入Bean的屬性值或依賴的對象

  

  屬性注入使用<Property>元素,使用name指定Bean的屬性名稱,使用value指定Bean的屬性的值

 

  2)構造器注冊:通過構造方法注入Bean的屬性和值

  首先創建一個Car類

 1 public class Car {
 2     private String brand;
 3     private int speed;
 4     private String color;
 5     public Car(String brand, int speed, String color) {
 6         this.brand = brand;
 7         this.speed = speed;
 8         this.color = color;
 9     }
10     @Override
11     public String toString() {
12         return "Car [brand=" + brand + ", speed=" + speed + ", color=" + color + "]";
13     }
14     
15 }

  然后加入配置文件配置節點

1 <bean id="car" class="com.hzg.spring.beans.Car">
2     <constructor-arg value="Audi"></constructor-arg>
3     <constructor-arg value="120"></constructor-arg>
4     <constructor-arg value="black"></constructor-arg>
5 </bean>

  Main方法開啟Spring容器並使用

1 // 1.創建Spring 的IOC的容器對象
2 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
3         
4 // 2.從IOC容器中獲取bean實例
5 Car car = (Car)ctx.getBean(Car.class);
6         
7// 3、調用hello方法
8 System.out.println(car);

  輸出結果:Car [brand=Audi, speed=120, color=black]

 

  如果想指定給屬性的順序賦值,可以使用index屬性

1 <bean id="car" class="com.hzg.spring.beans.Car">
2     <constructor-arg value="Audi" index="0"></constructor-arg>
3     <constructor-arg value="120" index="1"></constructor-arg>
4     <constructor-arg value="black" index="2"></constructor-arg>
5 </bean>

  如果想指定給屬性的順序賦值,也可以使用type屬性

1 <bean id="car" class="com.hzg.spring.beans.Car">
2     <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
3     <constructor-arg value="120" type="int"></constructor-arg>
4     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
5 </bean>

  3)工廠方法注入

    此方式基本不用

3、引用其他Bean

  1)引用外部Bean

 1 <bean id="car" class="com.hzg.spring.beans.Car">
 2     <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
 3     <constructor-arg value="120" type="int"></constructor-arg>
 4     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
 5 </bean>
 6 
 7 <bean id="person" class="com.hzg.spring.beans.Person">
 8     <property name="name" value="hzg"></property>
 9     <property name="age" value="32"></property>
10     <!-- 使用 property的ref屬性建立Bean之間的引用關系-->
11     <property name="car" ref="car"></property>
12 </bean>
  使用 property的ref屬性建立Bean之間的引用關系

  2)引用內部Bean

 1 <bean id="person" class="com.hzg.spring.beans.Person">
 2     <property name="name" value="hzg"></property>
 3     <property name="age" value="32"></property>
 4     <!-- 內部Bean,不能被外部引用,只能在內部使用-->
 5     <property name="car">
 6         <bean class="com.hzg.spring.beans.Car">
 7             <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
 8             <constructor-arg value="120" type="int"></constructor-arg>
 9             <constructor-arg value="black" type="java.lang.String"></constructor-arg>
10         </bean>
11     </property>
12 </bean>

  因為id是為了讓外部引用,而內部Bean內部只用一次,不能被外部引用,隨意不寫id。

4、級聯屬性

1 <bean id="person" class="com.hzg.spring.beans.Person">
2     <property name="name" value="hzg"></property>
3     <property name="age" value="32"></property>
4     <property name="car" ref="car"></property>
5     <!-- 級聯屬性賦值 -->
6     <property name="car.price" value="30000"></property>
7 </bean>

  注意:屬性想用car.price的級聯,首先car必須要先初始化,否則會有異常

4、集合屬性

當我們的Bean中有集合元素的時候,Spring中可以通過一組內置的xml標簽(<list>、<set>、<map>)來配置集合屬性。

  1)List集合:

   剛才的Person類有一個car屬性,現在我們修改一下,Person類中有一個List<car>,即一個人擁有多輛車。

 1 public class Person {
 2     private String name;
 3     private int age;
 4     private List<Car> cars;
 5     
 6     //為上面的3個屬性設置getter和setter方法
 7     public String getName() {
 8         return name;
 9     }
10     public void setName(String name) {
11         this.name = name;
12     }
13     public int getAge() {
14         return age;
15     }
16     public void setAge(int age) {
17         this.age = age;
18     }
19     public List<Car> getCars() {
20         return cars;
21     }
22     public void setCars(List<Car> cars) {
23         this.cars = cars;
24     }
25 }

  配置文件修改如下:

 1 <bean id="car1" class="com.hzg.spring.beans.Car">
 2     <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
 3     <constructor-arg value="120" type="int"></constructor-arg>
 4     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
 5 </bean>
 6 <bean id="car2" class="com.hzg.spring.beans.Car">
 7     <constructor-arg value="Ford" type="java.lang.String"></constructor-arg>
 8     <constructor-arg value="100" type="int"></constructor-arg>
 9     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
10 </bean>
11 <bean id="car3" class="com.hzg.spring.beans.Car">
12     <constructor-arg value="Toyota" type="java.lang.String"></constructor-arg>
13     <constructor-arg value="95" type="int"></constructor-arg>
14     <constructor-arg value="black" type="java.lang.String"></constructor-arg>
15 </bean>
16 <bean id="person" class="com.hzg.spring.beans.Person">
17     <property name="name" value="hzg"></property>
18     <property name="age" value="32"></property>
19     <!-- 集合屬性(List),使用ref來配置子節點信息 -->
20     <property name="cars">
21         <list>
22             <ref bean="car1"></ref>
23             <ref bean="car2"></ref>
24             <ref bean="car3"></ref>
25         </list>
26     </property>
27 </bean>

   2)Map集合:

   如果是<map>集合的話,只需要把list換成map即可。

1 <!-- 集合屬性(Map),使用entry來配置map的子節點信息 -->
2 <property name="cars">
3   <map>
4    <entry key="A" value-ref="car1" ></entry>
5    <entry key="B" value-ref="car2" ></entry>
6    </map>
7 </property>

 3) 現在這么多集合Bean能不能抽出來,以供多個Bean進行引用,那么就需要使用util

 1 <bean id="person" class="com.hzg.spring.beans.Person">
 2     <property name="name" value="hzg"></property>
 3     <property name="age" value="32"></property>
 4     <!-- 引用util -->
 5     <property name="cars" ref="cars"></property>
 6 </bean>
 7 <util:list id="cars">
 8     <ref bean="car1"></ref>
 9     <ref bean="car2"></ref>
10 </util:list>

 4)使用p命名空間 

  Sping從2.5版本開始引入一個新的P的命名空間,通過使用P命名空間后,使得Xml的配置方式進一步簡化

1 <!-- 通過P命名空間為Bean屬性賦值,相對於傳統的配置方式更加簡潔 -->
2 <bean id="person" class="com.hzg.spring.beans.Person" p:name="hzg" p:age="32" p:cars-ref="cars">
3 </bean>

 5、使用autowire屬性進行Bean的自動裝配

 當我們要往一個bean的某個屬性里注入另外一個bean,我們會使用<property ref=“”>標簽的形式。但是對於大型項目這種方式其實是不可取的。

1 <!-- 
2      大型項目中我們一般使用autowire屬性自動裝備Bean,autowire屬性有兩個值:byName和byType
3         byName:根據Bean的名字和當前的Bean的setter屬性名稱進行裝配
4         byType:根據Bean的類型進行裝配,若有1個以上的類型,則拋異常
5 -->
6 <bean id="person" class="com.hzg.spring.beans.Person" autowire="byType">
7      <property name="name" value="hzg"></property>
8      <property name="age" value="32"></property>
9 </bean>

  自動裝配的特點:

   1)只有引用類型才可以自動裝配。

   2)autowire屬性是在bean的級別上,一旦指定,當前bean的所有引用類型都必須使用自動裝配。

     3)byType和byName的只能選擇其一。

6、配置上的繼承(parent屬性)

  當我們有兩個或者以上的同一個類型的Bean做實例化的時候,我們可以將一些公共的提成通用Bean。這樣其他的Bean繼承它即可以了。

1 <bean id="address1" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YingBing">
2 
3 </bean>
4 <bean id="address2" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YanLing">
5 
6 </bean>
7 <bean id="address3" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YanShun">
8 
9 </bean>

  以上Bean中用的都是address這個類,都是省市街道的賦值,只是在街道上每個不一樣,所以我們完全可以把通用的提出來。

1 <bean id="address" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YingBing">
2 
3 </bean>
4 <bean id="address1" parent="address" p:street="YanLing">
5 
6 </bean>
7 <bean id="address2" parent="address" p:street="YanShun">
8 
9 </bean>

 7、Bean的作用域(scope屬性)

<bean id="address" class="com.hzg.Address" p:provice="Hebei" p:city="LangFang" p:street="YanShun">
 
</bean>
1 ApplicationContext ctx = new ClassPathXmlApplicationContext("configspring.xml");
2 Address address1 = (Address) ctx.getBean("address");
3 Address address2 = (Address) ctx.getBean("address");
4 System.out.println(address1==address2);

  輸出結果為:true

  說明默認為單例模式的,它只要是看scope屬性的。

  使用Bean的scope屬性來配置Bean的作用域的,scope有兩個重要的屬性值。

    singleton默認值,容器初始化時創建Bean實例,在整個容器的生命周期內只創建一個Bean,單例的。

    prototype:原型的,容器初始化時不創建Bean的實例,而在每次請求時都創建一個新的Bean的實例,並返回。

8、使用外部屬性文件(property-placeholder 屬性占位符)

  新建一個db.properties文件

1 user=root
2 password=123456
3 driverClass=com.mysql.jdbc
4 jdbcUrl=jdbc:mysql:///test

  配置上屬性占位符文件的地址,並在使用的過程中使用${}的格式取值

1 <!-- 導入屬性文件 -->
2 <context:property-placeholder location="db.properties"></context:property-placeholder>
3 <bean id="dataSource" class="com.hzg.MyDataSource">
4   <!-- 使用外部屬性文件的屬性值 -->
5   <property name="user" value="${user}"></property>
6   <property name="password" value="${password}"></property>
7    <property name="diverClass" value="${driverClass}"></property>
8    <property name="jdbcUrl" value="${jdbcUrl}"></property>
9 </bean>

  MyDataSource文件:

 1 public class MyDataSource {
 2     private String user;
 3     private String password;
 4     private String diverClass;
 5     private String jdbcUrl;
 6     
 7     public String getUser() {
 8         return user;
 9     }
10 
11     public void setUser(String user) {
12         this.user = user;
13     }
14 
15     public String getPassword() {
16         return password;
17     }
18 
19     public void setPassword(String password) {
20         this.password = password;
21     }
22 
23     public String getDiverClass() {
24         return diverClass;
25     }
26 
27     public void setDiverClass(String diverClass) {
28         this.diverClass = diverClass;
29     }
30 
31     public String getJdbcUrl() {
32         return jdbcUrl;
33     }
34 
35     public void setJdbcUrl(String jdbcUrl) {
36         this.jdbcUrl = jdbcUrl;
37     }
38 
39     @Override
40     public String toString() {
41         return "MyDataSource{" +
42                 "user='" + user + '\'' +
43                 ", password='" + password + '\'' +
44                 ", diverClass='" + diverClass + '\'' +
45                 ", jdbcUrl='" + jdbcUrl + '\'' +
46                 '}';
47     }
48 }

  Main方法:

1 ApplicationContext ctx = new ClassPathXmlApplicationContext("configspring.xml");
2 MyDataSource myDataSource = (MyDataSource) ctx.getBean("dataSource");
3 System.out.println(myDataSource);

  輸出結果:MyDataSource{user='root', password='123456', diverClass='com.mysql.jdbc', jdbcUrl='jdbc:mysql:///test'}

 9、Spring表達式SPEL表達式

 1 <bean id="person" class="com.hzg.Person">
 2  <!-- 使用SpEL 來應用其他的Bean -->
 3  <property name="car" value="#{car}"></property>
 4  <!-- 使用SpEL 來應用其他的Bean的屬性 -->
 5  <property name="city" value="#{address.city}"></property>
 6  <!-- 使用SpEL 中使用運算符 -->
 7  <property name="info" value="#{car.price > 30000 ? '金領' : '白領'}"></property>
 8  <!-- 使用SpEL 引用類的靜態屬性 -->
 9  <property name="yaowei" value="#{T(java.lang.Math).PI * 80}"></property>
10 </bean>

 10、Spring中Bean的生命周期

  1)創建Bean的實例

  2)為Bean的屬性設置值和對其他Bean的引用

  3)Bean后置處理器postProcessBeforeInitialization方法

  4)調用Bean的初始化方法(init-method)

  5)Bean后置處理器的postProcessAfterInitialization方法

  6)Bean正常使用

  7)當容器關閉時,調用Bean的銷毀方法(destroy-method)

  實例:

 1 public class Car {
 2     public Car() {
 3         System.out.println("構造器……");
 4     }
 5     private String brand;
 6 
 7     public void setBrand(String brand) {
 8         System.out.println("設置屬性……");
 9         this.brand = brand;
10     }
11     public void init(){
12         System.out.println("初始化……");
13     }
14     public void destroy(){
15         System.out.println("銷毀……");
16     }
17 }

  MyBeanProcessor必須實現BeanPostProcessor接口的兩個方法

 1 public class MyBeanProcessor implements BeanPostProcessor {
 2     @Override
 3     public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
 4         System.out.println("postProcessBeforeInitialization……");
 5         return o;
 6     }
 7 
 8     @Override
 9     public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
10         System.out.println("postProcessAfterInitialization……");
11         return o;
12     }
13 }

  配置文件

1 <bean id="car" class="com.hzg.Car" p:brand="Audi" init-method="init" destroy-method="destroy"></bean>
2 <!-- 配置Bean的后置處理器 -->
3 <bean class="com.hzg.MyBeanProcessor"></bean>

  Main方法

1 public static void main(String[] args) {
2  //由於ApplicationContext沒有close方法,所以要使用它下面接口ConfigurableApplicationContext
3  ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("configspring.xml");
4  Car car = (Car) ctx.getBean("car");
5  System.out.println("使用Bean:" + car.toString());
6  //關閉IOC容器
7  ctx.close();
8 }

  輸出結果:

postProcessBeforeInitialization……
postProcessAfterInitialization……
構造器……
設置屬性……
postProcessBeforeInitialization……
初始化……
postProcessAfterInitialization……
使用Bean:com.hzg.Car@2d928643
銷毀……

-------------------------------------------------------------------------------------------------------------------------

跟着剛哥學習Spring框架系列:

跟着剛哥學習Spring框架--創建HelloWorld項目(一)

跟着剛哥學習Spring框架--Spring容器(二)

跟着剛哥學習Spring框架--通過XML方式配置Bean(三)

跟着剛哥學習Spring框架--通過注解方式配置Bean(四)

跟着剛哥學習Spring框架--AOP(五)

跟着剛哥學習Spring框架--JDBC(六)

跟着剛哥學習Spring框架--事務配置(七)

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM