1. 程式人生 > >3.spring:自動裝配/Bean之間的關系/作用域/外部文件/spel/

3.spring:自動裝配/Bean之間的關系/作用域/外部文件/spel/

depends ... 完全 構造器 外部文件 conn wire odi host

1.自動裝配/手動裝配

xml配置文件裏的bean自動裝配
Spring IOC 容器裏可以自動的裝配Bean,需要做的僅僅是在<bean>的autowire屬性裏面指定自動裝配模式
->byType(根據類型自動進行裝配):若IOC容器裏需要有多個與目標Bean類型一樣的Bean,在這種情況子下,Spring無法判定那個Bean合適,所以不能執行自動裝配
->byName(根據名稱自動裝配):必須將目標Bean的名稱和屬性名設置完全相同,
->constuuctor(通過是構造器自動裝配):當bean中存在多個構造器時,這個方法將會復雜,不建議使用
一般情況下很少進行使用這個屬性

Car.java

public class Car {
    private String brand;
    private int price;
  //...
}

Person .java

public class Person {
    private String name;
    private Address address;
    private Car car;
  //...
}

Address .java

public class Address {
    private String city;
    private String street;
  //...
}

applicationContext.xml

<!-- 自動裝配 -->
<bean id="address" class="com.MrChengs3.autowire.Address" p:city="BeiJing" p:street="sanqing_Street"></bean>
<bean id="car" class="com.MrChengs3.autowire.Car" p:brand="BMW" p:price="10000"></bean>
    <!-- 根據名字進行裝配和setter方式類似    
        byName根據bean的setter風格進行裝配,將address改為address1則不能自動進行,沒有匹配的則不裝配
        byType:假設我們配了兩個address的變量,此時不唯一,不知道裝配那個
     
--> <bean id="person" class="com.MrChengs3.autowire.Person" p:name="MrChengs" autowire="byType"></bean> <!-- 手動裝配 --> <bean id="person" class="com.MrChengs3.autowire.Person" p:name="MrChengs" p:car-ref="car" p:address-ref="address"></bean>

測試:

Person p = (Person) ctx.getBean("person");
System.out.println(p);
Person [name=MrChengs, address=Address [city=BeiJing, street=sanqing_Street],
car=Car [brand=BMW, price=10000]]

2.Bean之間的關系

繼承:

Spring允許繼承bean之間的配置,被繼承的bean稱為父類bean,繼承這個父bean的bean稱為字bean
子bean從父類中繼承配置,包括父類的屬性配置
子bean也可以覆蓋從父類繼承過來的配置
父類可以作為模板,也可以作為bean實例,若相把父類的作為模板,可以設置父類bean的abstract屬性為true,這樣spring將不會實例化這個Bean
並不是bean元素裏的屬性都會被繼承,比如autowire,abstract等
也可以忽略父bean的class屬性,讓子類指定子的類,面向共享的配置,但是此時abstract必須設為true

1、父bean是一個實例時。它本身是一個完整的bean

2、父bean是模板,抽象bean,不能被實例化,只是來被繼承。

父bean一定不能實例化,因為它沒有class屬性,實例化會跑異常。那就一定要寫abstract屬性,讓spring不實例化它。

當遇到一個類要實例化出很多相似的bean對象時,看起來是不是很不簡潔。

applicationContext.xml

<bean id="address"   p:city="ShangHai" p:street="LaoRenJie" abstract="true"></bean>
<!-- 配置的繼承,使用bean -->
<bean id="address1" class="com.MrChengs3.autowire.Address"   parent="address"></bean>
Address address1 = (Address) ctx.getBean("address1");

依賴:

Spring允許用戶通過depend-on屬性設置bean前置依賴關系,前置以來的bean會在本bean實例化之前創建好
如果依賴多個bean,則可以使用逗號,空格或的方式配置bean的名稱

我們需要讓某個屬性必須存在,就像必填項一樣。 用depends-on 依賴

這樣,依賴存在了,就可以正常實例化了

<bean id="car" class="com.MrChengs3.autowire.Car" p:brand="BMW" p:price="1234" ></bean>
<!-- 配置Person,並且必須有一個關聯的car,就是說person這個bean依賴於car -->
<bean id="person" class="com.MrChengs3.autowire.Person" p:name="MrChengs" 
    p:address-ref="address1" depends-on="car"></bean>

3.bean的作用域

作用域:
singleton:單例,整個應用中只創建一個實例(默認)

prototype:原型,每次註入時都新建一個實例

session:會話,每個會話創建一個實例,在一個session會話中,是同一個bean,不同session就是不同bean

request:請求,每個請求創建一個實例,每一個HTTP請求生成一個新的bean

applicationContext.xml

<!-- bean的作用域 -->
<!-- 
    scope:bean的作用域
    singleton(默認值):在容器初始化的時候創建bean的實例,整個容器的生命周期裏面僅僅只創建一個bean,單列的
    prototype:原型的,容器創建初始化時,不創建bean的實例,而每次請求時都會創建一個新的bean實例,並返回
 -->
<bean id="car" class="com.MrChengs3.autowire.Car" p:brand="Ford" 
p:price="4321" scope="singleton"></bean>

測試:

        Car car = (Car) ctx.getBean("car");
        Car car2 = (Car) ctx.getBean("car");
        System.out.println(car ==car2);
true
scope="prototype"則為false

4.使用外部文件

propertie.properties

user=root
password=1234
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc\:mysql\://localhost\:3307/shijian

applicationContext.xml

<!-- 使用外部的屬性文件 -->
<!-- 需要導入context命名空間 -->
<context:property-placeholder location="classpath:propertie.properties"/>


<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- 使用外部話屬性文件 -->
    <property name="username" value="${user}"></property>
    <property name="password" value="${password}"></property>
    <property name="driverClassName" value="${driverClass}"></property>
    <property name="url" value="${jdbcUrl}"></property>

</bean>
            DataSource dataSource = (DataSource) ctx.getBean("dataSource",DataSource.class);
            System.out.println("執行中");
            System.out.println(dataSource.getConnection());
            System.out.println("結束");

${},代表引用外部的變量

通過把配置信息獨立到一個文件裏面,bean用${}方式引用, 便於維護、更清晰

如果響應修改只需要修改配置文件即可!

5.SpEl

SpEL---Spring Expression Language:

是一個支持運行時查詢和操作對象圖表達式語言、使用#{...}作為定界符,為bean屬性動態賦值提供了便利。

1) 為屬性賦值字面值

<bean id="address" class="com.MrChengs7.spel.Address">
    <!-- 為屬性賦值字面值 -->
    <property name="city" value="#{‘beijing‘}"></property>
    <property name="street" value="Shangye"></property>
</bean>
        Address address= (Address) ctx.getBean("address");
        System.out.println(address);
Address [city=beijing, street=Shangye]

2)引用 類的靜態屬性,用T()調用一個類的靜態方法,它將返回一個Class Object,然後再調用相應的方法或屬性

<bean id="car" class="com.MrChengs7.spel.Car">
    <property name="brand" value="Aodi"></property>
    <property name="price" value="12345"></property>
    <!-- 引用 類的靜態屬性 -->
    <property name="circle" value="#{T(java.lang.Math).PI * 80}"></property>
</bean>
        Car car = (Car) ctx.getBean("car");
        System.out.println(car);
Car [brand=Aodi, price=12345.0, circle=251.32741228718345]

3)其他

<bean id="person" class="com.MrChengs7.spel.Person">
    <!-- 引用其他的bean -->
    <property name="car" value="#{car}"></property>
    <!-- 其他bean的屬性 -->
    <property name="city" value="#{address.city}"></property>
    <!-- 運算符的使用 -->
    <property name="info" value="#{car.price > 1000 ? ‘有錢‘ : ‘沒錢‘}"></property>
    <property name="name" value="MrChengs"></property>
</bean>
        Person p = (Person) ctx.getBean("person");
        System.out.println(p);
Person [name=MrChengs, car=Car [brand=Aodi, price=12345.0, circle=251.32741228718345], city=beijing, info=有錢]

等待還有很多其他的....

3.spring:自動裝配/Bean之間的關系/作用域/外部文件/spel/