学习Spring(六) -- Spring中Bean的作用域以及生命周期

Bean的作用域

    默认情况下,bean的作用域为单例模式(singleton):

  1. 在applicationContext创建时,就将配置文件中的bean加载完毕;

  2. 在调用getBean时,从applicationContext中获取;

    也就是说,在整个应用程序中,bean只存在一个实例,下面写一段代码测试一下,写一个Car类,有一个Name字段:

package cn.net.bysoft.lesson4;

public class Car {

    public Car() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;

}

    在配置文件中,配置这个Car的bean元素:

<bean id="car" class="cn.net.bysoft.lesson4.Car">
</bean>
@Test
    public void testScopeIsDefault() {
        // 在Spring容器初始化时就生成了bean对应的对象。

        // 在调用时,从Spring容器中get一个对象,这个对象是单例的。
        Car car = (Car) ctx.getBean("car");
        car.setName("Audi");

        Car car1 = (Car) ctx.getBean("car");
        car1.setName("BMW");

        // get到的对象都会修改这个单例的bean。
        System.out.println(car);
        System.out.println(car1);

        /**
         * output: 
         * Car [name=BMW] 
         * Car [name=BMW]
         * */
    }

    测试发现,对car设置的name值被car1覆盖了,也就是说,car与car1实际是使用的同一个car实例,car==car1。

    可以改变bean的作用域来解决此问题,将scope=prototype:

<bean id="car2" class="cn.net.bysoft.lesson4.Car" scope="prototype">
</bean>
@Test
    public void testScopeIsPrototype() {
        // 设置了bean的scope=prototype后
        // 在Spring容器初始化时不会自动生成bean对应的对象
        // 而是在get时生成对象,对象不是单例的。
        Car car = (Car) ctx.getBean("car2");
        car.setName("Audi");

        Car car1 = (Car) ctx.getBean("car2");
        car1.setName("BMW");

        System.out.println(car);
        System.out.println(car1);

        /**
         * output: 
         * Car [name=Audi] 
         * Car [name=BMW]
         * */
    }

Bean的生命周期

    正常情况下,spring加载bean时,首先会调用构造函数,接着对property赋值时调用setter方法。

    如果需要对bean有更多的控制,可以设置init-method与destroy-method属性,修改一下car对象,加入init与destory方法:

package cn.net.bysoft.lesson4;

public class Car {

    public Car() {
        System.out.println("1.执行了构造函数。");
    }

    public void init() {
        System.out.println("3.执行初始化。");
    }

    public void destory() {
        System.out.println("5.执行销毁。");
    }

    @Override
    public String toString() {
        System.out.println("4.使用bean方法。");
        return "Car [name=" + name + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("2.调用setter方法。");
        this.name = name;
    }

    private String name;

}

    在配置文件中为bean配置init-method与destory-method:

<bean id="car3" class="cn.net.bysoft.lesson4.Car" init-method="init"
    destroy-method="destory" scope="singleton">
    <property name="name" value="Audi"></property>
</bean>

    在进行测试,看看各个方法的执行顺序:

@Test
    public void testCycle() {
        Car car = (Car) ctx.getBean("car3");
        System.out.println(car);
        ctx.close();
    }

170730_Xksg_2450666.png

  1. 执行了构造函数

  2. 执行了setter()方法

  3. 执行了init()方法

  4. 执行了destory()方法

使用bean的后置处理器

    上面的做法是为单个类进行更多的初始化控制,还可以配置全局的初始化控制,做法为,创建一个类使用实现BeanPostProcessor接口,将该类配置到spring配置文件中即可:

package cn.net.bysoft.lesson4;

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

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    // 后置初始化处理
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("after..." + bean.getClass() + ", " + beanName);
        return bean;
    }

    @Override
    // 前置初始化处理
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("before..." + bean.getClass() + ", " + beanName);
        return bean;
    }

}
<bean id="car4" class="cn.net.bysoft.lesson4.Car" init-method="init"
        destroy-method="destory" scope="singleton">
        <property name="name" value="BMW"></property>
    </bean>
    <bean class="cn.net.bysoft.lesson4.MyBeanPostProcessor"></bean>
@Test
    public void testBeanPostProcessor() {
        Car car = (Car) ctx.getBean("car4");
        System.out.println(car);
        ctx.close();
    }

171446_yIbJ_2450666.png

    通过结果可以看到,配置的处理器before在init方法前被调用,after在init方法后调用。

转载于:https://my.oschina.net/u/2450666/blog/663154

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值