文章目录
- Bean的作用域
- Bean的六种作用域
- 设置Bean的作用域
- Bean的生命周期
- Bean(Spring)的执行流程
- Bean的生命周期
Bean的作用域
我们通过一个例子来认识 Bean 的作用域:
假设现在有一个公共的 Bean 对象提供给用户A和用户B使用,然后在使用的途中用户A却“悄悄”的修改了公共Bean的数据,导致用户B在使用时发送了意料之外的逻辑错误。
//定义Bean对象@Datapublic class User {private int id;private String name;private String password;}//设置初始值@Beanpublic User user(){User user = new User();user.setId(1);user.setName("张三");user.setPassword("123456");return user;}
//用户A使用并修改
@Controller
public class Use1 {@Autowiredprivate User user;public User getUser() {System.out.println("原来的name:" + user.getName());//修改nameuser.setName("李四");System.out.println("现在的name:" + user.getName());return user;}
}//用户B使用
@Controller
public class Use2 {@Autowiredprivate User user;public User getUser() {System.out.println("Use2得到的name:" + user.getName());return user;}
}
//验证结果
public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");Use1 use1 = context.getBean("use1",Use1.class);use1.getUser();//原来的name:张三 现在的name:李四Use2 use2 = context.getBean("use2",Use2.class);use2.getUser();//user2得到的name:李四}
}
原因分析:Bean 默认情况下是单例的,即Bean默认是单例作用域
Bean的作用域是指:Bean在Spring整个框架中的行为模式
Bean的六种作用域
- singleton:单例作用域,Bean在Ioc容器中只存在一个实例,每次获取Bean都获取到同一个对象
- prototype:原型作用域(多例作用域),每次注册Bean都会创建新的实例,获取到的Bean不是同一个对象
- request:请求作用域,每次HTTP请求会创建新的实例
- session:会话作用域,在一个httpSession中定义一个实例
- application:全局作用域,在一个http servlet context中定义一个实例,用来记录一个应用的共享信息
- websocket:websocket作用域,在一个WebSocket的生命周期中定义一个实例
注:
- 在普通的Spring项目中只有前两种作用域
- 后四种作用域存在于 SpringMVC中
设置Bean的作用域
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Scope("prototype")@Beanpublic User user(){User user = new User();user.setId(1);user.setName("张三");user.setPassword("123456");return user;}
注:
@Scope注解既可以修饰方法又可以修饰类
@Scope有两种设置方法:
- 直接设置值:@Scope(“prototype”)
- 使用枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Bean的生命周期
Bean(Spring)的执行流程
- 启动Spring容器:加载配置文件中的Bean注册路径
- 实例化Bean(分配内存空间,从无到有):读取注册路径下的注解
- 将Bean注册到Spring中:存操作
- 把Bean注入到需要它的类中:取操作
Bean的生命周期
- 实例化Bean:为Bean分配内存空间
- 设置属性:Bean注入和装配
- Bean初始化:
- 实现了各种Aware通知的方法
- 执行了 BeanPostProcessor 初始化前置方法
- 执行了 PostConstruct 初始化方法
- 执行自己指定的 init-method 方法
- 执行 BeanPostProcessor 初始化后置方法
- 使用Bean
- 销毁Bean
实例化 VS 初始化:
实例化:是Java级别的系统“事件”,其操作过程不可人工干预和修改
初始化:是给开发者提供的,可以在实例化之后、类加载完成之前进行自定义“事件”处理
为什么要先设置属性再进行初始化呢?
因为初始化中可能会用到设置好的相关属性