目录
Bean的作用域
作用域
设置作用域
Spring的执行流程和Bean的生命周期
Bean的生命周期
BeanApplication类会将一个User对象注册进入Spring
@Controller
public class BeanApplication {
@Bean(name = "user")
public User init() {
User user = new User();
user.setName("李四");
return user;
}
}
UserApplication类对从框架中获取到的User对象进行修改
@Controller
public class UserApplication {
@Autowired
private User user;//这里会获取到Spring内的一个 User对象
public void getUser() {
User user1 = user;
System.out.println("原来的 user " + user1);
user1.setName("孙悟空");
}
}
Text类会从框架中拿到User对象,进行打印
@Controller
public class Text {
@Autowired
private User user;
public void print() {
System.out.println("user :->" + user);
}
}
按照我们的预期, UserApplication只是应该修改自己的代码,不应该让这个修改作用于框架内的User对象
产生这个问题的原因是,Spring默认使用单例模式
Bean对象的作用域就是对象的作用范围
Spring框架的Bean对象有6种
前两种是普通spring项目中的,后四个是Spring MVC的值
1、singleton:单例作用域(默认单例模式)
2、prototype:原型作用域(多例模式)
3、request:请求作用域
4、session:回话作用域
5、application:全局作用域
6、websocket:HTTP WebSocket作用域
作用范围 | 描述 |
---|---|
singleton | 默认值,单例模式,表示在 Spring 容器中只有一个 Bean 实例 |
prototype | 原型模式,表示每次通过 Spring 容器获取 Bean 时,容器都会创建一个新的 Bean 实例。 |
request | 每次 HTTP 请求,容器都会创建一个 Bean 实例。该作用域只在当前 HTTP Request 内有效。 |
session | 同一个 HTTP Session 共享一个 Bean 实例,不同的 Session 使用不同的 Bean 实例。该作用域仅在当前 HTTP Session 内有效。 |
application | 同一个 Web 应用共享一个 Bean 实例,该作用域在当前 ServletContext 内有效。 与 singleton 类似,但 singleton 表示每个 IoC 容器中仅有一个 Bean 实例,而一个 Web 应用中可能会存在多个 IoC 容器,但一个 Web 应用只会有一个 ServletContext,也可以说 application 才是 Web 应用中货真价实的单例模式。 |
websocket | websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效。 |
在对象存入框架之前,使用Scope注解设置对象的作用域
执行流程:1、启动容器2、加载配置文件3、创建Bean对象4、Bean对象注册到容器(存对象)5、Bean对象装配到其他类(取对象)
对象的生命周期就是对象创建和删除的过程
1、实例化Bean对象(分配内存)
2、设置属性(Bean注入和装配)
3、Bean初始化
执行各种Aware通知的方法,例如生成BeanName的BeanNameAware接口方法
若容器中有BeanPostProcessor,则调用,执行初始化前置方法
执行构造方法,有两种形式:@PostConstruct初始化构造,另一种是执行指定了Bean的init-method方法(在配置文件设置)如果两个都有,注解优先执行
执行初始化的后置方法 BeanPostProcessor
4、使用Bean
5、销毁Bean:可以有三种方法,@PreDestory、DisposableBean接口方法,destory-method
Bean创建过程中的“实例化”与“初始化”名词
BeanPostProcessor :
发生在 BeanDefiniton 加工Bean 阶段. 具有拦截器的含义. 可以拦截BeanDefinition创建Bean的过程, 然后插入拦截方法,做扩展工作
postProcessBeforeInitialization初始化前置处理 (对象已经生成)
postProcessAfterInitialization初始化后置处理 (对象已经生成)
我们使用代码,检验上述过程
1、在Text包下,创建PostProcessor类,实现BeanPostProcessor接口,实现接口中的postProcessBeforeInitialization,postProcessAfterInitialization方法
@Controller
public class PostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("对象" + beanName + "开始实例化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("对象" + beanName + "实例化完成");
return bean;
}
}
2、创建类BeanLife
public class BeanLife implements BeanNameAware {
//1、执行通知
@Override
public void setBeanName(String s) {
System.out.println("执行了BeanName这个通知方法 beanName=" + s);
}
//3、执行构造方法
@PostConstruct
public void Construct() {
System.out.println("执行PostConstruct构造方法");
}
//4、有两个构造方法 先执行上一个
public void init() {
System.out.println("执行init-method指定的方法");
}
//5、执行初始化的后置方法
//6、销毁
@PreDestroy
public void destory() {
System.out.println("执行 PreDestroy 方法");
}
}
4、测试类
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
PostProcessor postProcessor=context.getBean(PostProcessor.class);
BeanLife life=context.getBean(BeanLife.class);
context.destroy();
}
}
ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它