spring学习总结(七):IOC & DI 配置Bean之bean的生命周期及bean的配置方式

本文详细探讨了Spring框架中Bean的生命周期,包括初始化和销毁方法、Bean后置处理器的影响,以及三种不同的Bean配置方式:静态工厂、实例工厂和实现FactoryBean接口。通过这些方式,Spring能够灵活地管理Bean的创建和销毁,增强应用程序的可维护性和灵活性。
摘要由CSDN通过智能技术生成

IOC & DI 配置Bean之bean的生命周期及bean的配置方式


Bean的生命周期

IOC 容器中 Bean 的生命周期方法

  • Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务
  • 在 Bean 的声明里设置 init-methoddestroy-method 属性, 为 Bean 指定初始化和销毁方法.
Car.java
package com.xyc.spring.cycle;

/**
 * 
 * @ClassName:  Car   
 * @Description:Spring IOC容器及生命周期测试
 * @author: xyc 
 * @date:   2016年11月26日 下午4:25:23   
 *
 */
public class Car {

    private String brand;


    public void setBrand(String brand) {
        System.out.println("Car setBrand.........");
        this.brand = brand;
    }


    public void init(){
        System.out.println("Car init...........");
    }
    
    public void destory(){
        System.out.println("Car destory..........");
    }
    
    public Car() {
        System.out.println("Car Contruator...");
    }


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

bean-cycle.xml
<?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 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法. -->
	<bean id="car" class="com.xyc.spring.cycle.Car" init-method="init" destroy-method="destory">
		<property name="brand" value="BMW"></property>
	</bean>

</beans>

ApplicationCycle.java
package com.xyc.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.xyc.spring.cycle.Car;

/**
 * 
 * @ClassName:  ApplicationCycle   
 * @Description:测试spring IOC容器及生命周期
 * @author: xyc 
 * @date:   2016年11月26日 下午4:30:05   
 *
 */
public class ApplicationCycle {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-cycle.xml");
        
        Car car = (Car) context.getBean("car");
        
        System.out.println(car);
        
        //关闭IOC 
        context.close();
    }
    
}

运行结果:


由此可以看出,Spring IOC 容器对 Bean 的生命周期进行管理的过程如下:
  • 通过构造器或工厂方法创建 Bean 实例
  • 为 Bean 的属性设置值和对其他 Bean 的引用
  • 调用 Bean 的初始化方法
  • Bean 可以使用了
  • 当容器关闭时, 调用 Bean 的销毁方法

添加 Bean 后置处理器后 Bean 的生命周期

  • Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.
  • Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.
  • 对Bean 后置处理器而言, 需要实现 BeanPostProcessor接口. 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给BeanPostProcessor接口的两个方法:


MyBeanPostProcessor.java
package com.xyc.spring.cycle;

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

/**
 * 
 * @ClassName:  MyBeanPostProcessor   
 * @Description: Bean 后置处理器
 * @author: xyc 
 * @date:   2016年11月26日 下午4:47:11   
 *
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        
        if("car".equals(beanName)){
            System.out.println("postProcessBeforeInitialization: "+bean+"@"+beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization: "+bean+"@"+beanName);
        
        Car car = new Car();
        car.setBrand("SUV");
        return car;
    }

}


xml中配置:
<!-- 
实现BeanPostProcessor接口,并具体提供
Object postProcessBeforeInitialization(Object bean, String beanName)  init-method之前被调用
Object postProcessAfterInitialization(Object bean, String beanName)   init-method之后被调用

bean: bean实例本身
beanName: IOC 容器中配置bean的id
返回值:是具体返回给用户的那个Bean,注意可以在以上两个方法中修改返回的Bean,甚至可以返回一个全新的bean
 -->
<!-- 配置bean的后置处理器:不需要配置id,IOC容器自动识别一个BeanPostProcessor -->
<bean class="com.xyc.spring.cycle.MyBeanPostProcessor"></bean>

运行结果:



由此可以看出,Spring IOC 容器对 Bean 的生命周期进行管理的过程:
  • 通过构造器或工厂方法创建 Bean 实例
  • 为 Bean 的属性设置值和对其他 Bean 的引用
  • 将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法
  • 调用 Bean 的初始化方法
  • 将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization方法
  • Bean 可以使用了
  • 当容器关闭时, 调用 Bean 的销毁方法

Bean的配置方式

  • 通过全类名(反射),通过反射的方式加载类的全路径,前面一直是这种方式.
  • 通过工厂方法(静态工厂方法 & 实例工厂方法)
  • FactoryBean

通过调用静态工厂方法创建 Bean

  • 调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节.
  • 要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 <constrctor-arg> 元素为该方法传递方法参数.
car.java
package com.xyc.spring.factory;

/**
 * 
 * @ClassName:  Car   
 * @Description:Bean的配置方式   
 * @author: xyc 
 * @date:   2016年11月27日 下午5:06:21   
 *
 */
public class Car {

    private String brand;
    
    private Double price;

    public String getBrand() {
        return brand;
    }

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

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Car(String brand, Double price) {
        this.brand = brand;
        this.price = price;
    }

    public Car() {
    }

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

CarStaticFactory.java
package com.xyc.spring.factory;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @ClassName:  CarStaticFactory   
 * @Description:静态工厂方法:直接调用某一个类的静态方法就可以返回Bean实例
 * @author: xyc 
 * @date:   2016年11月27日 下午5:09:22   
 *
 */
public class CarStaticFactory {

    private static Map<String,Car> map = new HashMap<String, Car>();
    
    static{
        map.put("BYD", new Car("BYD", 300000.00));
        map.put("BMW", new Car("BMW", 500000.00));
    }
    
    public static Car getCar(String brand){
        return map.get(brand);
    }
}




xml中配置
<!-- 通过静态工厂的方式来配置bean,注意不是配置静态工厂方法实例,而是配置bean实例 -->
<!-- 
class: 指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg 来配置参数
 -->
<bean id="car1" class="com.xyc.spring.factory.CarStaticFactory" factory-method="getCar">
	<constructor-arg value="BMW"></constructor-arg>
</bean>

通过调用实例工厂方法创建 Bean

  • 实例工厂方法: 将对象的创建过程封装到另外一个对象实例的方法里. 当客户端需要请求对象时, 只需要简单的调用该实例方法而不需要关心对象的创建细节.
  • 要声明通过实例工厂方法创建的 Bean
  1. --在 bean 的 factory-bean 属性里指定拥有该工厂方法的 Bean
  2. --在 factory-method 属性里指定该工厂方法的名称
  3. --使用 construtor-arg 元素为工厂方法传递方法参数

CarInstanceFactory.java
package com.xyc.spring.factory;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @ClassName:  CarInstanceFactory   
 * @Description:实例工厂方法:实例工厂的方法,即现需要创建工厂本身,再调用工厂的实例来返回bean 的实例 
 * @author: xyc 
 * @date:   2016年11月27日 下午5:22:00   
 *
 */
public class CarInstanceFactory {

    private Map<String,Car> map;
    
    public CarInstanceFactory() {
        map = new HashMap<String, Car>();
        map.put("BYD", new Car("BYD", 300000.00));
        map.put("BMW", new Car("BMW", 300000.00));
    }
    
    
    public Car getCar(String brand){
        return map.get(brand);
    }
}

xml中配置:
<!-- 配置工厂实例 -->
<bean id="carInstanceFactory" class="com.xyc.spring.factory.CarInstanceFactory"></bean>

<!-- 通过实例工厂配置bean -->
<!-- 
factory-bean:指向实例工厂id
factory-method:指向实例工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg 来配置参数
 -->
<bean id="car2" factory-bean="carInstanceFactory" factory-method="getCar">
	<constructor-arg value="BYD"></constructor-arg>
</bean>


实现 FactoryBean 接口在 Spring IOC 容器中配置 Bean

  • Spring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, 即FactoryBean. 
  • 工厂 Bean 跟普通Bean不同, 其返回的对象不是指定类的一个实例, 其返回的是该工厂 Bean 的 getObject 方法所返回的对象
CarBeanFactory.java
package com.xyc.spring.factory;

import org.springframework.beans.factory.FactoryBean;

/**
 * 
 * @ClassName:  CarBeanFactory   
 * @Description:通过FactoryBean工厂创建bean 
 * @author: xyc 
 * @date:   2016年11月27日 下午5:46:52   
 *
 */
public class CarBeanFactory implements FactoryBean<Car>{

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

    /**
     * 
     * <p>Title: getObject</p>   
     * <p>Description: </p>   
     * @return 返回bean的对象
     * @throws Exception   
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    @Override
    public Car getObject() throws Exception {
        return new Car(brand, 300000.00);
    }

    /**
     * 
     * <p>Title: getObjectType</p>   
     * <p>Description: </p>   
     * @return   bean类型
     * @see org.springframework.beans.factory.FactoryBean#getObjectType()
     */
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    /**
     * 
     * <p>Title: isSingleton</p>   
     * <p>Description: </p>   
     * @return   是否单例
     * @see org.springframework.beans.factory.FactoryBean#isSingleton()
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

xml中配置:
<!-- 通过FactoryBean工厂配置Bean的实例
	 class:指向FactoryBean的实现类的全类名
	 property:指向FactoryBean的实现类的属性
	 
	 实际返回的是FactoryBean 的getObject()方法返回的实例
 -->
<bean id="car3" class="com.xyc.spring.factory.CarBeanFactory">
	<property name="brand" value="BMW"></property>
</bean>



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值