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

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