Spring4.0 study notes (3)

Spring Expression Language SpEL

  • Spring Expression Language (SpEL for short): is a powerful expression language that supports runtime query and manipulation of object graphs.
  • The syntax is similar to EL: SpEL uses #{…} as a delimiter, all characters in the big box will be considered SpEL
  • SpEL facilitates dynamic assignment of bean properties
  • With SpEL it is possible to:
    • Reference a bean by its id
    • Calling methods and referencing properties in objects
    • evaluate the value of an expression
    • regular expression matching
    • Manipulate literals Integers , decimals, scientific notation, static methods
  • specific code
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="com.anqi.spel.Address">
        <!-- 使用 spel 为属性赋一个字面值 -->
        <property name="city" value="#{'Xinzhou'}"></property>
        <property name="street" value="Wutaishanlu"></property>
    </bean>

    <bean id="car" class="com.anqi.spel.Car">
        <property name="brand" value="Audi"></property>
        <property name="price" value="500000"></property>
        <!-- 使用 SpEL 引用的静态属性 -->
        <property name="tyrePrimeters" value="#{T(java.lang.Math).PI * 80}">
        </property>
    </bean>

    <bean id="person" class="com.anqi.spel.Person">
        <!-- 使用 SpEL 来引用其他的 bean 相当于 value-ref="car" -->
        <property name="car" value="#{car}"></property>
        <!-- 使用 SpEL 来引用其他 Bean 的属性 -->
        <property name="city" value="#{address.city}"></property>
        <!-- 在 SpEL 中使用运算符 -->
        <property name="info" value="#{car.price > 300000 ? '金领':'白领'}"></property>
        <property name="name" value="Tom"></property>
    </bean>
</beans>
public class Person {
    private String name;
    private Car car;

    //引用 address 的 bean 的 city 属性
    private String city;

    //根据 car 的 price 来确定 info : 若 price >300000 则为金领
    //否则为白领
    private String info;
    //..setter getter toString
    }
public class Address {
    private String city;
    private String street;
    //..setter getter toString
    }
public class Car {
    private String brand;
    private double price;
    private double tyrePrimeters;
    //..setter getter toString
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
    public static void main(String[] args) {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-spel.xml");

        Address address = (Address) ctx.getBean("address");
        System.out.println(address);
        //Address [city=Xinzhou, street=Wutaishanlu]

        Car car = (Car) ctx.getBean("car");
        System.out.println(car);
        //Car [brand=Audi, price=500000.0, tyrePrimeters=251.32741228718345]

        Person person = (Person) ctx.getBean("person");
        System.out.println(person);
        //Person [name=Tom, car=Car [brand=Audi, price=500000.0, tyrePrimeters=251.32741228718345], 
        //city=Xinzhou, info=金领]
    }
}

Lifecycle of beans in an IOC container

  • The Spring IOC container can manage the bean lifecycle , and Spring allows custom tasks to be performed at specific points in the bean lifecycle.
  • The process of the Spring IOC container managing the life cycle of beans:
    • Create Bean instance via constructor or factory method
    • Set values ​​for bean properties and references to other beans
    • Call the initialization method of the bean
    • Bean is ready to use
    • When the container is closed, call the destroy method of the bean
  • Set the init-method and destroy-method attributes in the bean declaration to specify the initialization and destruction methods for the bean.

Create Bean Post Processor

  • Bean post-processors allow additional processing of beans before and after invocation of initialization methods.
  • Bean post-processor processes all bean instances in the IOC container one by one, rather than a single instance . Typical applications are: checking the correctness of bean properties or changing bean properties according to specific criteria.
  • For the Bean post-processor, the BaseBeanProcessor interface needs to be implemented. Before and after the initialization method is called, Spring will pass each Bean instance to the following two methods of the above interface.

    public Object postProcessAfterInitialization(Object bean, String beanName)
    public Object postProcessBeforeInitialization(Object bean, String beanName)

  • The life cycle of bean after adding bean post-processor The
    Spring IOC container manages the life cycle of bean:

    • Create Bean instance via constructor or factory method
    • Set values ​​for bean properties and references to other beans
    • Pass the bean instance to the postProcessBeforeInitialization method of the bean post processor
    • Call the initialization method of the bean
    • Pass the bean instance to the postProcessAfterInitialization method of the bean post processor
    • Bean is ready to use
    • When the container is closed, call the destroy method of the bean
  • code
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="com.anqi.cycle.Car" 
        init-method="myInit" destroy-method="myDestroy" >
        <property name="brand" value="fute"></property>
    </bean>

    <!-- 
        实现 BeanPostProcesser 接口, 并具体提供
        Object postProcessAfterInitialization(Object bean, String beanName) 
            init-method 之前调用
        Object postProcessBeforeInitialization(Object bean, String beanName)
            init-method 之后调用

        bean : bean 实例本身
        beanName : IOC 容器配置的 bean 本身的名字
        返回值 : 是实际上返回给用户的那个 Bean, 注意:可以在以上两个方法中修改返回的 bean,
               甚至返回一个新的 bean
     -->

    <!-- 配置 bean 的后置处理器 -->
    <bean class="com.anqi.cycle.MyBeanPostProcessor"></bean>
</beans>
public class Car {

    private String brand;

    public Car() {
        System.out.println("Car Construct..");
    }
    public void myInit() {
        System.out.println("init...");
    }

    public void myDestroy() {
        System.out.println("destroy...");
    }
    //setter、getter、toString
}
package com.anqi.cycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization.."+bean+"-"+beanName);
        return bean;
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization.."+bean+"-"+beanName);

        Car car = (Car)bean;
        car.setBrand("Chngan");
        return car;
    }

}
public class Main {

    public static void main(String[] args) {

        //因为 ApplicationContext 没有 close 方法,所以使用它的实现类
        ClassPathXmlApplicationContext ctx = 
                new ClassPathXmlApplicationContext("bean-cycle.xml");

        Car car = (Car) ctx.getBean("car");
        System.out.println(car);

        ctx.close();
    }
}

Configure beans through factory methods

static factory method

  • Calling the static factory method to create a bean encapsulates the process of object creation into a static method . When the client needs an object, it simply calls the static method, and does not care about the details of creating the object.
  • To declare a bean created by a static method, you need to specify the class with the method of the factory in the class attribute of the bean, and specify the name of the factory method in the factory-method attribute. Finally, use the constructor-arg element to pass the method for the method parameter
  • code
    <!-- 
    通过静态工厂方法来配置 bean, 【注意】不是配置静态工厂方法实例, 而是配置 bean 实例 
    -->
    <!-- 
        class 属性 : 指向静态工厂方法的全类名
        factory-method : 指向静态工厂方法的名字
        construct-arg : 如果工厂方法需要传入参数, 则使用 construct-arg 来配置参数
     -->
    <bean id="car1" class="com.anqi.factory.StaticCarFactory"
        factory-method="getCar">
        <constructor-arg value="audi"></constructor-arg>
    </bean>
/**
 * 静态工厂方法 : 直接调用某一个类的静态方法就可以返回 Bean 的实例
 */
public class StaticCarFactory {

    private static Map<String, Car> cars = 
                        new HashMap<String, Car>();

    static {
        cars.put("audi", new Car("audi",29999));
        cars.put("fute", new Car("fute",39999));
    }

    //静态工厂方法
    public static Car getCar(String brand) {

        return cars.get(brand);
    }
}
public class Main {
    public static void main(String[] args) {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factory.xml");
        Car car1 = (Car) ctx.getBean("car1");
        System.out.println(car1);
        //Car [brand=audi, price=29999.0]
        }
    }

instance factory method

    <!-- 配置工厂的实例 -->
    <bean id="carFactory" class="com.anqi.factory.InstanceCarFactory"></bean>

    <!-- 通过实例工厂方法来配置 bean -->
    <!-- 
        factory-bean 属性 : 指向实例工厂的全类名
        factory-method : 指向静态工厂方法的名字
        construct-arg : 如果工厂方法需要传入参数, 则使用 construct-arg 来配置对象
     -->
    <bean id="car2" factory-bean="carFactory" factory-method="getCar">
        <constructor-arg value="ford"></constructor-arg>
    </bean>
/**
 * 实例工厂方法 : 实例工厂的方法, 即需要创建工厂本身, 
 * 再 调用工厂的实例方法来返回 bean 的实例
 */
public class InstanceCarFactory {
    private Map<String, Car> cars = null;

    public InstanceCarFactory() {
        cars = new HashMap<String, Car>();
        cars.put("audi", new Car("audi", 300000));
        cars.put("ford", new Car("ford", 400000));
    }

    public Car getCar(String brand) {
        return cars.get(brand);
    }

}
public class Main {
    public static void main(String[] args) {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factory.xml");

        Car car2 = (Car) ctx.getBean("car2");
        System.out.println(car2);
        //Car [brand=ford, price=400000.0]
    }
}

Implement the FactoryBean interface to configure beans in the Spring IOC container

  • There are two types of beans in Spring, one is a common bean, and the other is a factory bean, namely FactoryBean.
  • The factory bean is different from the ordinary bean. The object returned is not an instance of the specified class, but the object returned by the getObject method of the factory bean.
    <!-- 
        在 bean 里面要引用其他 bean Factory 是最好的方法

        通过 FactoryBean 来配置 Bean 的实例
        class : 指向 FactoryBean 的全类名
        property : 配置 Factory 的属性

        但实际返回的实例却是 FactoryBean 的 getObject() 方法
     -->
    <bean id="car" class="com.anqi.factorybean.CarFactroyBean">
        <property name="brand" value="BMW"></property>
    </bean>
import org.springframework.beans.factory.FactoryBean;
/**
 * 自定义的 FactoryBean 需要实现 FactoryBean 接口
 */
public class CarFactroyBean implements FactoryBean{

    private String brand;

    public void setBrand(String brand) {
        this.brand = brand;
    }

    /**
     * 返回 bean 的对象
     */
    public Object getObject() throws Exception {
        return new Car(brand,50000);
    }

    /**
     * 返回 bean 的类型
     */
    public Class getObjectType() {
        return Car.class;
    }

    /**
     * 是否是单例的
     */
    public boolean isSingleton() {
        return true;
    }
}
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new 
                ClassPathXmlApplicationContext("bean-factorybean.xml");

        Car car = (Car) ctx.getBean("car");
        System.out.println(car);
        //Car [brand=BMW, price=50000.0]
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324667843&siteId=291194637