从前面的课程可以看出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;
}
}
进行运行结果如下:
结果却与我们的预期大相径庭,这是为什么呢?
操作以上问题的原因是因为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级别的系统“事件”,其操作过程不可人工干预和修改;而初始化时给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理。