spring知識三-----SpEL&生命週期&bean配置方式

SpEL—–熟悉

SpEL概述

spring的表達式語言。用在配置文件中,是一個支持運行時查詢和操作對象圖的強大的表達式語言。他的語法類似於EL表達式。SpEL使用 #{ } 作爲定界符,所有在大框號中的字符都將被認爲是 SpEL。SpEL 爲 bean 的屬性進行動態賦值提供了便利。

SpEL可以實現的功能:

1、通過 bean 的 id 對 bean 進行引用
2、引用對象中的屬性以及調用方法
3、計算表達式的值
4、正則表達式的匹配

    <!-- 爲字面賦值 -->
<bean id="address" class="com.wf.springspel.Address">
    <property name="city" value="#{'henan'}"></property>
    <property name="street" value="luoyang"></property>
</bean>

<!-- 引用類的靜態屬性 -->
<bean id="car" class="com.wf.springspel.Car">
    <property name="brand" value="Audi"></property>
    <property name="price" value="1000000"></property>
    <property name="carlength" value="#{T(java.lang.Math).PI*8 }"></property>
</bean>

<bean id="user" class="com.wf.springspel.User">
    <property name="name" value="tom"></property>
    <!-- 引用其他bean對象 -->
    <property name="car" value="#{car}"></property>
    <!-- <property name="car" ref="car"></property> -->
    <!-- 引用其他bean對象的屬性 -->
    <property name="city" value="#{address.city}"></property>
    <!-- el表達式進行選擇 -->
    <property name="info" value="#{car.price>30000?'老闆':'員工'}"></property>

</bean>

SpEL 語法

SpEL:字面量

字面量的表示:
整數:<property name="count" value="#{5}"/>
小數:<property name="frequency" value="#{89.7}"/>
科學計數法:<property name="capacity" value="#{1e4}"/>
String可以使用單引號或者雙引號作爲字符串的定界符號:
<property name=“name” value="#{'Chuck'}"/> 或 <property name='name' value='#{"Chuck"}'/>
Boolean:<property name="enabled" value="#{false}"/>

引用 Bean、屬性和方法

<!--引用其他對象:通過value屬性和SpEL 配置Bean之間的應用關係 -->
<property name="car" value="#{car}"></property>
<!--引用其他對象的屬性-->
<property name="city" value="#{address.city}"></property>
<!--調用其他方法,記得括號-->
<property name="city" value="#{address.toString()}"></property>
<!--鏈式調用其他方法,記得括號-->
<property name="city" value="#{address.toString().toUpperCase()}"></property>

運算符的操作

<!--算數運算符的操作 【+、-、*、/、%、^】 -->
<property name="add" value="#{account.count+125}"></property>
<property name="remainder" value="#{account.total % account.count}"></property>

<!--加號作爲連接符-->
<construtor-arg name="name" value="#{performer.fisrtName+':'+performer.lasrName}" />
<!--比較運算符 <、>、==、<=、>=、lt、gt、eq、le、ge -->
<property name="equal" value="#{account.count == 125}"></property>
<property name="hasCapacity" value="#{account.count le 125}"></property>
<!--邏輯運算符 and、or、not-->
<property name="largeCircle" value="#{shape.kind == 'circle' and shape.perimeter gt 1000}"></property>
<!--if  else 運算符 -->
<property name="info" value="#{car.price>30000?'老闆':'員工'}"></property>
<!--正則表達式 matches -->
<construtor-arg name="email" value="#{admin.email matches '[a-z0-9]' " />

靜態方法或靜態屬性操作

<!--調用靜態方法或靜態屬性,通過 T() 調用一個類的靜態方法,它將返回一個 Class Object,然後再調用相應的方法或屬性-->
<property name="carlength" value="#{T(java.lang.Math).PI*8 }"></property>

Bean生命週期—–瞭解

簡單的生命週期過程

類似於Servlet,spring也可以進行生命週期管理。
Spring IOC 容器可以管理 Bean 的生命週期, Spring 允許在 Bean 生命週期的特定點執行定製的任務。
Spring IOC 容器對 Bean 的生命週期進行管理的過程:
1、通過構造器或工廠方法創建 Bean 實例(構造器調用);
2、爲 Bean 的屬性設置值和對其他 Bean 的引用(setter方法調用);
3、調用 Bean 的初始化方法;
4、Bean 的使用;
5、當容器關閉時, 調用 Bean 的銷燬方法;
注意:在 Bean 的聲明裏設置 init-method 和 destroy-method 屬性, 爲 Bean 指定初始化和銷燬方法。
注意:ApplicationContext沒有提供close方法,我們可以利用他的實現類進行來關閉。
【ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext(“beans-cycle.xml”);】

//  類
public class Car {

    private String brand;

    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        System.out.println("setter value.....");
        this.brand = brand;
    }

    public Car() {
        System.out.println("Car constructors...... ");
}
    public void init(){ // 名稱不固定init2也是可以
        System.out.println("Car init.....");
    }
    public void destory(){
        System.out.println("car destory......");
    }

    @Override
    public String toString() {
        return "Car [brand=" + brand + "]";
    }
}

// 配置
<!-- 先調用構造器,然後setter方法,然後init方法,然後destory -->   
<bean id="car" class="com.wf.springcycle.Car" init-method="init" destroy-method="destory">
    <property name="brand" value="Auto"></property>
</bean>

創建 Bean 後置處理器的生命週期過程

Bean 後置處理器允許在調用初始化方法前後對 Bean 進行額外的處理。
Bean 後置處理器對 IOC 容器裏的所有 Bean 實例逐一處理, 而非單一實例。
其典型應用是: 檢查 Bean 屬性的正確性或根據特定的標準更改 Bean 的屬性.
對Bean 後置處理器應用,需要實現【BeanPostProcessor 】接口,在初始化方法被調用前後, Spring 將把每個 Bean 實例分別傳遞給上述接口的以下兩個方法【postProcessAfterInitialization】和【postProcessBeforeInitialization】中。
Spring IOC 容器對 Bean 的生命週期進行管理的過程:
1、通過構造器或工廠方法創建 Bean 實例;
2、爲 Bean 的屬性設置值和對其他 Bean 的引用;
3、將 Bean 實例傳遞給 Bean 後置處理器的 postProcessBeforeInitialization 方法;
4、調用 Bean 的初始化方法;
5、將 Bean 實例傳遞給 Bean 後置處理器的 postProcessAfterInitialization方法;
6、Bean 的使用;
7、當容器關閉時, 調用 Bean 的銷燬方法;

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override //bean代表容器創建的實例,beanName代表bean的id 
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("後置處理器postProcessAfterInitialization"+bean+"..."+beanName);
        if("car".equals(beanName)){
            System.out.println("car is changing");
            Car car = (Car) bean;
            car.setBrand("DaBen");
        }       
        return bean;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("前置處理器postProcessAfterInitialization"+bean+"..."+beanName);
        return bean;
    }
}

// 配置

<!-- 後置處理器的配置不需要Id,spring容器會根據BeanPostProcessor接口進行自動識別
    後置處理器類需要實現BeanPostProcessor,然後重寫
    postProcessAfterInitialization(Object bean, String beanName) Init之前
    postProcessBeforeInitialization(Object bean, String beanName) Init之後
    方法。
    bean代表容器創建的實例,beanName代表bean的id ,可以在這兩個方法進行一些條件判斷,
    過濾出要進行修改的bean實例。

 -->
<bean class="com.wf.springcycle.MyBeanPostProcessor">
</bean>

Bean的配置方式——熟悉

通過全類名進行反射配置—掌握

我們對於bean的配置一般都是利用全類名進行反射。【常用的,最基本的】

通過工廠方法—熟悉

【靜態工廠方法&實例工廠方法,我們需要額外的創建一個工廠類

靜態工廠方法
調用靜態工廠方法創建 Bean是將對象創建的過程封裝到靜態方法中. 當客戶端需要對象時, 只需要簡單地調用靜態方法, 而不同關心創建對象的細節,要聲明通過靜態方法創建的 Bean, 需要在 Bean 的 class 屬性裏指定擁有該工廠的方法的類, 同時在 factory-method 屬性裏指定工廠方法的名稱. 最後, 使用 【constrctor-arg】元素爲該方法傳遞方法參數

//創建工廠類
/*靜態工廠方法:通過調用靜態的工廠方法,進行初始化bean*/
public class CarStaticFactory {
    static Map<String, Car> cars=new HashMap<String, Car>();
    // 謹記在聲明集合時,進行初始化。。
    static{
        cars.put("Audi", new Car("Audi", 30000));
        cars.put("DaZh", new Car("DaZh", 30000));
        cars.put("XianDai", new Car("XianDai", 30000));
    }
    //封裝到靜態方法中獲取對象
    public static Car getCar(String name){      
        return cars.get(name);
    }   
}


//配置
    <!-- 通過靜態工廠方法進行配置bean,
    class屬性:指向靜態工廠的類名, 
    factory-method屬性:指向靜態工廠方法,
    constructor-arg屬性 : 指向要傳遞的參數,
     -->

<bean id="car01" class="com.wf.springfactory.CarStaticFactory" factory-method="getCar">
    <constructor-arg name="name" value="Audi"></constructor-arg>    
</bean>

實例工廠方法
實例工廠方法: 將對象的創建過程封裝到另外一個對象實例的方法裏. 當客戶端需要請求對象時, 只需要簡單的調用該實例方法而不需要關心對象的創建細節.
要聲明通過實例工廠方法創建的 Bean需要在 bean 的 factory-bean 屬性裏指定擁有該工廠方法的 Bean,在 factory-method 屬性裏指定該工廠方法的名稱,使用 construtor-arg 元素爲工廠方法傳遞方法參數。

/*實例工廠方法:通過創建實例工廠,然後調用工廠的實例方法,進行初始化bean*/

public class CarInstanceFactory {

    static Map<String, Car> cars=new HashMap<String, Car>();    
    public  Car getCar(String name){        
        return cars.get(name);
    }
    public CarInstanceFactory() {
        cars.put("Audi", new Car("Audi", 30000));
        cars.put("DaZh", new Car("DaZh", 30000));
        cars.put("XianDai", new Car("XianDai", 30000));
    }
}

<!--  通過工廠的實例配置bean
        首先設定  CarInstanceFactory 實例工廠 bean
-->
<bean id="CarInstanceFactory" class="com.wf.springfactory.CarInstanceFactory" >
</bean>
<!-- 
        factory-bean屬性:指向實例工廠的bean, 
        factory-method屬性:指向實例工廠方法,
        constructor-arg屬性 : 指向要傳遞的參數, -->
<bean id="car02" factory-bean="CarInstanceFactory" factory-method="getCar">
    <constructor-arg value="Audi"> </constructor-arg>
</bean>


FactoryBean —掌握

【整合其餘框架會利用, quartz】需要自定義 FactoryBean
Spring 中有兩種類型的 Bean, 一種是普通Bean, 另一種是工廠Bean, 即FactoryBean。
工廠 Bean 跟普通Bean不同, 其返回的對象不是指定類的一個實例, 其返回的是該工廠 Bean 的 getObject 方法所返回的對象

在利用FactoryBean配置時,我們需要實現Spring給我們提供的FactoyBean接口。,並且重寫其中的方法。

//自定義FactoryBean需要實現spring提供的FactoryBean接口
// 如果設置有屬性,可以通過配置文件的property屬性進行賦值
//  整合quartz需要使用
public class CarFactoryBean implements FactoryBean<Car> {
    @Override  // 返回  bean 對象
    public Car getObject() throws Exception {
        // TODO Auto-generated method stub
        return new Car("BMW", 200000)  ;
    }
    @Override   // 返回bean的類型
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Car.class;
    }
    @Override   //  是否是單例
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return true;
    }
}
<!-- 通過FactoryBean 進行配置bean
     class:指向自定義的FactoryBean全類名
     property :配置自定義的factoryBean的屬性
     實際返回的實例是FactoryBean 的getObject()方法返回的實例,
 -->
<bean id="car03" class="com.wf.springfactory.CarFactoryBean">
</bean>

源碼可以在我的資源中查看 或者 github地址
https://github.com/wangfa1994/SpringLearning/tree/spring003

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章