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