赞
踩
通过一个案例来看Bean的作用域。假设有一个公共的Bean对象,提供给A类和B类使用,然而在A类使用的过程中,修改了Bean的数据,导致B类在使用Bean的时候产生了预期之外的逻辑错误。
预期结果是公共Bean可以在各自类中被修改,但不能影响其他类使用(使用时还是Bean的初始数据)。
公共Bean:
@Component
public class Users {
@Bean
public User user1(){
User user = new User();
user.setName("zhangsan");//注意 初始化为 zhangsan
user.setId(1);
return user;
}
}
User对象:
public class User { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
A类使用时,修改了数据:把name修改成了Lisi
@Controller
public class AController {
@Autowired
private User user;
public User getUser1(){
System.out.println("Bean 原 name :"+user.getName());
user.setName("Lisi");//A类修改了Bean原生数据
return user;
}
}
B类再去使用公共Bean时:
@Controller
public class BController {
@Autowired
private User user1;
public User getUser1(){
User user = user1;
return user;
}
}
打印A和B类使用公共Bean 的值:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.config.xml");
AController aController = context.getBean(AController.class);
System.out.println("A类修改后 name :"+aController.getUser1().toString());
BController bController = context.getBean(BController.class);
System.out.println("B读取到的 name :"+bController.getUser1().toString());
}
}
运行结果:
原因分析:
以上运行结果的原因是:因为Bean默认情况下是单例模式(singleton),也就是所有人使用的都是同一个Bean对象。因为使用单例模式可以很大程度上提高性能,所以在spring中Bean的作用域默认也是singleton单例模式。
程序中变量的可用范围就叫做作用域,或者说在源代码中定义某个变量在某个区域就叫做作用域。而Bean的作用域是指Bean在Spring整个框架中的某种行为模式,比如singleton单例作用域,就表示Bean在spring中只有一份,全局共享的,当A修改了这个值后,那么B再使用时就是修改后的值。
Spring容器在初始化一个Bean对象时,会指定该实例的作用域。spring有6种作用域,最后4种是基于Spring MVC生效的:
1. singleton:单例模式
2. prototype:原型作用域(多例作用域)
3. request:请求作用域
4. session:会话作用域
5. application:全局作用域
6. websocket:HTTP WebSocket 作用域
注意后4种是SpringMVC中的值,在普通的Spring项目中只有前两种。
描述:在⼀个http session中,定义⼀个Bean实例
场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息
备。
备注:限定SpringMVC中使⽤
@Scope既可以修饰方法也可以修饰类
@Component
public class Users {
@Scope("prototype")//设置为 prototype 全局作用域
@Bean
public User user1(){
User user = new User();
user.setName("zhangsan");//注意 初始化为 zhangsan
user.setId(1);
return user;
}
}
运行结果:此时A修改数据,不会影响B读取的数据。
@Component
public class Users {
//@Scope("prototype")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean
public User user1(){
User user = new User();
user.setName("zhangsan");//注意 初始化为 zhangsan
user.setId(1);
return user;
}
}
运行结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。