文章目录
- 一、作用域
- 1.1 xml文件中配置
- 1.2 注解配置
- 二、生命周期
- 2.1 四个阶段
- 2.2 添加后置处理器
- 2.3 实现aware类型接口
- 2.4 Bean 初始化的方式
- 2.5 Bean 销毁的方式
- 2.6 测试程序
学习视频🎥:https://www.bilibili.com/video/BV1Vf4y127N5
一、作用域
❓ 引入概念
- 单实例对象:对于所有的请求都是同一个对象去处理,相当于静态代码,只加载一次,使用多次。spring 中创建的bean默认是单例实例的
- 多实例对象:对于多次请求,创建多个对象去处理
1.1 xml文件中配置
🔑 修改spring 中的bean 作用域(设置单例还是多例):在<bean>
标签中添加属性——scope,scope 的值由多种选择
① singleton
- 默认值,表示创建的对象是单实例的
- 将scope 属性这是为 singleton 后,加载spring 配置文件时就会把对象创建出来
② prototype
- 将创建的对象设置为多实例
- 将scope 属性这是为 prototype 后,加载spring 配置文件时不会创建对象,在获取对象或使用对象的时候才会创建
③ request:将对象的作用域设置为request 域
④ session:将对象的作用域设置为session 域
<bean id="u" class="com.Key.spring.bean.User" scope="prototype"></bean>
1.2 注解配置
在需要修改的作用域的类上添加@Component
和@Scope
注解,注解中直接添加值即可,值的选择和默认值同上
💡 需要Bean 需要被创建后才能修改其作用域,所以必须先添加
@Component
注解(其他创建对象的注解也可)
@Component
@Scope("prototype")
public class User {
// code...
}
二、生命周期
👀参考博文:谈谈你对Spring Bean生命周期的理解【面试】
2.1 四个阶段
bean 的声明周期可初步分为四个阶段
① Bean 的实例化阶段:执行Bean 的无参构造器
② Bean 的属性注入阶段:执行Bean 的所有成员变量对应的set 方法
③ Bean 的初始化阶段:执行自定义的初始化方法或Java 接口内部方法
❓ 获取Bean阶段:在Bean 的初始化阶段后、销毁阶段前还有获取和使用Bean 的阶段
// 获取对象 BeanLifeDemo lifeDemo = context.getBean("bl", BeanLifeDemo.class); // 使用对象 System.out.println(lifeDemo);
④ Bean 的销毁阶段:执行自定义的销毁方法或Java 接口内部方法(需要手动执行)
2.2 添加后置处理器
- 后置处理器:创建一个类实现
BeanPostProcessor
接口,并实现接口的两个方法 - 执行时间:在Bean 初始化阶段的前后分别执行后置处理器的
postProcessBeforeInitialization()
方法和postProcessAfterInitialization()
方法
2.3 实现aware类型接口
-
aware类型接口:能感知到所有
Aware
前面的含义的接口,如BeanNameAwar
e、ApplicationContextAware
等 -
接口的作用:加载资源到Spring中,
Aware
前面的名字对应加载的资源 -
执行时间:Bean 属性注入阶段之后、后置处理器的
postProcessBeforeInitialization()
方法之前 -
各个aware 接口的执行顺序以及各自对应的执行方法(去掉
Aware
,前面加上set
)① BeanNameAware -->
setBeanName()
② BeanClassLoaderAware -->setBeanClassLoader()
③ BeanFactoryAware -->setBeanFactory()
④ EnvironmentAware -->setEnvironment()
⑤ ResourceLoaderAware -->setResourceLoader()
⑥ ApplicationEventPublisherAware -->setApplicationEventPublisher()
⑦ ApplicationContextAware -->setApplicationContex()
❓
BeanFactory
和ApplicationContext
的区别:BeanFactoryAware
接口之前加载的资源都是公共的,之后加载的资源都是ApplicationContext
独有的
2.4 Bean 初始化的方式
- 基于xml 文件:在Bean 对应的类中自定义一个初始化方法,并在配置文件的
<bean>
标签中添加init-method
属性,值为自定义的初始化方法名 - 基于注解:在Bean 对应的类中自定义一个初始化方法,方法上添加注解
@PostConstruct
- 实现接口(基于Java):让Bean 对应的类实现
InitializingBean
接口,并实现接口的afterPropertiesSet()
方法
💡 常用的方法是前面两种,即自定义初始化方法,销毁方法也一样
2.5 Bean 销毁的方式
- 基于xml 文件:在Bean 对应的类中自定义一个销毁方法,并在配置文件的
<bean>
标签中添加destroy-method
属性,值为自定义的销毁方法名 - 基于注解:在Bean 对应的类中自定义一个销毁方法,方法上添加注解
@PreDestroy
- 实现接口(基于Java):让Bean 对应的类实现
DisposableBean
接口,并实现接口的destroy()
方法
💡 Bean 的销毁不会自动执行,需要手动调用工厂对象的
close()
方法/* 创建工厂对象 - 注意这里是直接采用ClassPathXmlApplicationContext作为对象类型,而不是Application接口 - 因为close()方法是在ClassPathXmlApplicationContext中创建的,不是实现于Application接口 */ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLifeDemo.xml"); // code... // 关闭工厂对象,同时销毁Bean(执行对应的销毁方法) context.close();
2.6 测试程序
-
测试Bean --> BeanLifeDemo.java
public class BeanLifeDemo implements InitializingBean, DisposableBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, ResourceLoaderAware, ApplicationEventPublisherAware, ApplicationContextAware { /*+---------------------------------------实例化阶段---------------------------------------------+*/ public BeanLifeDemo() { System.out.println("一、实例化 --> 执行无参构造器..."); } /*+---------------------------------------注入属性阶段---------------------------------------------+*/ private String name; private int age; public void setName(String name) { System.out.println("二、注入属性 --> 2.1 执行setName()"); this.name = name; } public void setAge(int age) { System.out.println("二、注入属性 --> 2.2 执行setAge()"); this.age = age; } @Override public String toString() { return "BeanLifeDemo{" + "name='" + name + '\'' + ", age=" + age + '}'; } /*+---------------------------------------实现各个aware 接口的各个set方法---------------------------------------------+*/ @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("三、实现aware 接口 --> 3.2 对应BeanClassLoaderAware接口"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("三、实现aware 接口 --> 3.3 对应BeanFactoryAware接口"); } @Override public void setBeanName(String s) { System.out.println("三、实现aware 接口 --> 3.1 对应BeanNameAware接口"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("三、实现aware 接口 --> 3.7 对应ApplicationContextAware接口"); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { System.out.println("三、实现aware 接口 --> 3.6 对应ApplicationEventPublisherAware接口"); } @Override public void setEnvironment(Environment environment) { System.out.println("三、实现aware 接口 --> 3.4 对应EnvironmentAware接口"); } @Override public void setResourceLoader(ResourceLoader resourceLoader) { System.out.println("三、实现aware 接口 --> 3.5 对应ResourceLoaderAware接口"); } /*+---------------------------------------初始化阶段---------------------------------------------+*/ /** * 自定义初始化方法 * - 基于xml文件:在<bean>中添加 init-method 属性,属性值为方法名 * - 基于注解:在方法上添加注解 @PostConstruct */ public void initMethod() { System.out.println("五、初始化 --> 5.2 自定义初始化方法"); } /** * 实现Java 接口内部的初始化方法 * - 实现 InitializingBean 接口 * - 不用配置和添加注解 */ @Override public void afterPropertiesSet() throws Exception { System.out.println("五、初始化 --> 5.1 Java接口内部的初始化方法"); } /*+---------------------------------------销毁阶段---------------------------------------------+*/ /** * 自定义销毁方法 * - 基于xml文件:在<bean>中添加 destroy-method 属性,属性值为方法名 * - 基于注解:在方法上添加注解 @PreDestroy */ public void destroyMethod() { System.out.println("八、销毁 --> 8.2 自定义销毁方法"); } /** * 实现Java 接口内部的销毁方法 * - 实现 DisposableBean 接口 * - 不用配置和添加注解 */ @Override public void destroy() throws Exception { System.out.println("八、销毁 --> 8.1 Java接口内部的销毁方法"); } }
-
自定义后置处理器 --> MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor { /** * 在Bean 初始化前执行的方法 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("四、将Bean交给后置处理器 --> Bean初始化前执行..."); return bean; } /** * 在Bean 初始化后执行的方法 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("六、将Bean交给后置处理器 --> Bean初始化后执行..."); return bean; } }
-
基于xml 文件配置 --> beanLifeDemo.xml
<!-- 创建自定义的后置处理器对象(配置后置处理器) --> <bean id="myBeanPost" class="com.Key.spring.ioc.beanlife.MyBeanPostProcessor"></bean> <!-- 创建bean生命周期演示对象 - 注入属性 - 配置自定义的初始化方法和销毁方法 --> <bean id="bl" class="com.Key.spring.ioc.beanlife.BeanLifeDemo" init-method="initMethod" destroy-method="destroyMethod"> <property name="name" value="宋江"></property> <property name="age" value="54"></property> </bean>
-
测试方法
@Test public void testBeanLife() { // 加载spring配置文件,获取工厂对象 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLifeDemo.xml"); // 获取对象 BeanLifeDemo lifeDemo = context.getBean("bl", BeanLifeDemo.class); System.out.println("七、获取实例化对象 --> " + lifeDemo); // 关闭工厂对象,即销毁Bean,spring bean不会自动销毁,必须调用工厂对象的close() 方法 context.close(); }
-
测试打印结果