目录
2.1.5 application 全局作用域 (了解即可)
有一个公共的Bean ,A 用户和B用户共同使用, 如果A在使用的时候,将公共资源Bean修改了,会导致B用户在使用时发生错误。
A用户(Controller9)使用的时候进行了修改操作:
- @Controller
- public class UserController9 {
- @Autowired
- private User user1;
-
- public User getUser() {
- User user = user1;
- user.setName("唐僧");
- return user;
- }
- }
B用户(Controller9) 使用公共资源:
- @Controller
- public class UserController10 {
- @Autowired
- private User user1;
-
- public User getUser() {
- return user1;
- }
- }
- public class User {
- private int id;
- private String name;
- private String password;
-
- 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;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- @Override
- public String toString() {
- return "User{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", password='" + password + '\'' +
- '}';
- }
- }
- public class App {
- public static void main(String[] args) {
- // 1. 获取spring上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
-
- UserController9 userController9 = context.getBean(UserController9.class);
- System.out.println("Controller9 : " + userController9.getUser());
-
- UserController10 userController10 = context.getBean(UserController10.class);
- System.out.println("Controller10 : " + userController10.getUser());
- }
- }
-
- 输出:Controller9 : User{id=1, name='唐僧', password='123'}
- Controller10 : User{id=1, name='唐僧', password='123'}
实际上我们想让Controller10 输出 :Controller10 : User{id=1, name='张三', password='123'}
- public class App {
- public static void main(String[] args) {
- // 1. 获取spring上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
-
- if(userController9 == userController9_2) {
- System.out.println("内存地址相等,单例模式");
- System.out.println(userController9);
- System.out.println(userController9_2);
- } else {
- System.out.println("内存地址不相等,非单例模式");
- System.out.println(userController9);
- System.out.println(userController9_2);
- }
- }
- }
-
- 输出:
- 内存地址相等,单例模式
- com.beans.controller.UserController9@161479c6
- com.beans.controller.UserController9@161479c6
使用单例模式会很大程度上提高性能,所以spring中Bean的作用域默认是单例模式(singleton)。也就是所有的人都是用的是同一个对象。
经过上述问题的发生,限定了程序中变量的可用范围,即就是定义了作用域。
Bean的作用域是指 Bean在Spring 整个框架中的某种行为模式,比如单例作用域,就表示Bean在整个Spring 中只有一份,并且它是全局共享的,别人修改了这个值之后,后面的人读取到的都是被修改之后的值。
Spring 容器在初始化一个Bean 的实例时,同时会指定该实例的作用域。
💫 1. singleton :单例作用域
💫 2. prototype :原型作用域(多例作用域)
💫 3. request :请求作用域
💫 4. session : 会话作用域
💫 5. application :全局作用域
💫 6. websocket :HTTP WebSocket 作用域
前两种是Spring核心作用域,后四种是Spring MVC 中的作用域
💫描述: 该作用域下的Bean在loC容器中只存在一个实例:获取Bean(applicationContext.getBean等方法)及 装配Bean (通过@Autowired注⼊)都是同一个对象。
💫 场景:无状态的Bean 使用该作用域,无状态表示Bean 对象的属性状态不需要更新
💫 Spring 默认选择该作用域
💫 描述:每次对该作用域下的Bean 的请求都会创建新的实例:获取Bean和装配Bean都是心得对象实例。
💫 场景:有状态的Bean 使用该作用域
💫 描述:每次 http 请求会创建新的Bean 实例,类似于prototype
💫 场景:一次http 得请求和响应的共享Bean
💫 在SpringMVC中使用
💫 描述:在一个http session 中定义一个Bean 实例
💫 场景:用户会话的共享Bean ,比如:记录一个用户的登录信息
💫 在SpringMVC中使用
单例作用域(singleton)和全局作用域(application)的区别:
💫 单例作用域是Spring Core (普通项目)的作用域,全局作用域是Spring Web 中的作用域。
💫 单例作用域作用于loC 的容器,而 全局作用域作用于Servlet 容器。
@Scope 标签既可以修饰方法也可以修饰类,@Scope 有两种设置方式:
💫 1. 直接设置值:@Scope("prototype")
💫 2. (常量)类似于枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
- @Component
- public class UserBeans2 {
-
- @Bean(name = "user1")
- @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
- public User user1(){
- User user = new User();
- user.setId(1);
- user.setName("张三");
- user.setPassword("123");
- return user;
- }
- }
- @Controller
- public class UserController9 {
- @Autowired
- private User user1;
-
- public User getUser() {
- User user = user1;
- user.setName("唐僧");
- return user;
- }
- }
- public class App {
- public static void main(String[] args) {
- // 1. 获取spring上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
- UserController9 userController9 = context.getBean(UserController9.class);
- System.out.println("Controller9 : " + userController9.getUser());
-
- UserController10 userController10 = context.getBean(UserController10.class);
- System.out.println("Controller10 : " + userController10.getUser());
-
- }
- }
- }
-
- 输出:Controller9 : User{id=1, name='唐僧', password='123'}
- Controller10 : User{id=1, name='张三', password='123'}

修改UserBeans2代码:
- @Component
- public class UserBeans2 {
-
- @Bean(name = "user1")
- @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
- public User user1(){
- User user = new User();
- user.setId(1);
- user.setName("张三");
- user.setPassword("123");
- return user;
- }
- }
输出:
Controller9 : User{id=1, name='唐僧', password='123'}
Controller10 : User{id=1, name='唐僧', password='123'}

启动Spring 容器 -----》根据配置完成Bean初始化 -----》Bean 对象注册到Spring容器 中 (存)-----》将Bean 装配到需要的类中(取)
一个对象从诞生到销毁的整个生命过程。
💫 1. 实例化
💫 2. 设置属性
💫 3. Bean 初始化
💫 4. 使用Bean
💫 5. 销毁Bean
为Bean分配空间。实例化不等于初始化,只是分配内存空间
执行依赖类的注入和装配(A需要使用B的方法,先初始化,并将B加载到当前类)
(1)实现各种Aware 通知方法
(2)执行初始化前置方法
(3)执行初始化方法(两种实现:注解方式@PostConstruct 或 XML<bean init - method='xxx'>)
(4)执行自己的指定的init - method 方法
(5)执行初始化后置方法
有两种实现:注解方式 @PreDestroy,XML<bean destroy - method='xxx'>
