从前面的课程可以看出Spring是用来存储和读取Bean的,因此在Spring中Bean是最核心的操作资源,所以我们将从Bean的作用域和生命周期进一步学习一下Bean对象。

1、Bean的作用域

假设现在有一个公共的Bean,提供给用户A和用户B来使用,然而A悄悄地修改了公共的Bean的数据,导致B在使用时发生了预期之外的逻辑错误,我们预期是:公共Bean可以在各自类中进行修改,但不影响其他类的使用。案例如下:

@Component
public class UserBeans {
   @Bean(name = "user1")
    public User getUser(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setPassword("123");
        return user;
    }

A: 在UserController6中注入user1,然后对其name属性进行修改:

@Controller
public class UserController6 {

    @Autowired
    private User user1;

    public User getUser(){
        User user = user1;
        user.setName("唐僧");   
        return user;
    }
}

 B:使用公共Bean 

@Controller
public class UserController7 {

    @Autowired
    private User user1;

    public User getUser(){
        return user1;
    }
}

进行运行结果如下:

 

spring替换jar包中的配置bean spring运行期间替换bean_java

 结果却与我们的预期大相径庭,这是为什么呢?

操作以上问题的原因是因为Bean默认状态下为单例状态(singleton),也就是所有类使用的都是同一个对象,之前我们学过,单例模式不用重复new对象,不用耗费过多的资源,能在很大程度上提高性能,所以在Spring中Bean 的默认作用域就是单例模式。

Bean的作用域是指Bean 在Spring 整个框架中的某种行为模式,比如singleton 单例作用域,就表示在整个Spring中只有一份,它是全局共享的,那么其他人修改了这个值之后,那么另一个人读取到的也是被修改过的值。

 解决此问题只需要在注册Bean时,设置Bean的作用域为多例作用域:prototype

@Component
public class UserBeans {
   @Bean(name = "user1")
   @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User getUser(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setPassword("123");
        return user;
    }

2、Bean的生命周期

所谓Bean的生命周期是指一个Bean从诞生到销毁的整个生命过程,我们把这个过程就叫做Bean的生命周期。Bean的生命周期分为以下5大部分:

1、实例化(不等于初始化):只执行分配内存空间的功能

2、设置属性(执行依赖类的注入  A需要使用B的方法,先初始化并将B加载到当前类中)

3、初始化

        a)各种Aware通知方法

        b)初始化前置方法

        c)执行初始化方法(核心)

        d)初始化后置方法

4、使用Bean

5、销毁Bean

实例化和初始化的区别


实例化和属性设置是java级别的系统“事件”,其操作过程不可人工干预和修改;而初始化时给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理。