我们来看下 Spring Framework 的官方文档:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.
简而言之,bean 是由 Spring IoC 容器实例化、组装和管理的对象。
在Java Spring中,Bean的生命周期是指一个Bean从被实例化到最终被销毁的整个过程。Spring容器负责管理Bean的生命周期,并在特定时机触发相应的回调方法。
实例化(Instantiation):在这个阶段,Spring容器根据配置或注解创建Bean的实例对象。
属性赋值(Population):在实例化后,Spring容器将通过依赖注入(Dependency Injection)或属性设置将相关属性值传递给Bean。
初始化回调(Initialization Callback):在属性赋值完成后,如果Bean实现了
InitializingBean
接口,Spring容器会调用其afterPropertiesSet()
方法。同时,还可以通过在配置文件中指定init-method
来指定初始化方法。使用中(In Use):在初始化完毕后,Bean可以被应用程序正常使用,执行相应的业务逻辑。
销毁回调(Destruction Callback):当Bean不再需要时,Spring容器会在适当的时候触发销毁回调方法。如果Bean实现了
DisposableBean
接口,Spring容器会调用其destroy()
方法。另外,也可以通过在配置文件中指定destroy-method
来指定销毁方法。
需要注意的是,并非所有Bean都需要实现InitializingBean
和DisposableBean
接口或通过配置指定初始化和销毁方法。这些操作是可选的,可以根据需要选择是否使用。此外,还可以使用注解驱动的方式,如@PostConstruct
和@PreDestroy
注解,来定义初始化和销毁方法。
通过生命周期回调方法,我们可以在Bean的不同阶段执行自定义逻辑,例如进行初始化设置、资源加载、连接数据库等。Spring的生命周期管理能够帮助我们更好地控制Bean的创建、初始化和销毁过程,提高应用程序的灵活性和可维护性。
在Java Spring中,Bean的生命周期可以应用于以下场景:
初始化配置:在Bean实例化和初始化阶段,可以执行一些初始化配置的操作,例如加载配置文件、连接数据库、初始化缓存等。
依赖注入:在Bean的属性赋值阶段,可以进行依赖注入,将其他Bean所需要的依赖项自动注入到目标Bean中。
自定义逻辑:通过在Bean的生命周期中定义回调方法,可以执行自定义的业务逻辑。例如,在初始化前后执行一些额外的逻辑操作,或者在销毁前后进行资源清理。
资源管理:可以在Bean的销毁阶段,释放占用的资源,如关闭数据库连接、释放文件句柄、停止定时任务等。
AOP(面向切面编程):可以利用Bean的生命周期回调方法,在特定的时间点织入AOP切面逻辑,例如在初始化之后执行一些切面操作。
第三方库集成:当使用某些第三方库时,可能需要在Bean的生命周期中进行初始化和销毁操作,以确保库的正确使用和释放。
总结来说,Java Spring中Bean的生命周期可以应用于初始化配置、依赖注入、自定义逻辑、资源管理、AOP和第三方库集成等场景。它可以帮助我们更好地管理和控制Bean的创建、初始化和销毁过程,提高应用程序的可维护性和可扩展性。
该接口只有一个方法 setBeanName(String name),用来获取 bean 的 id 或者 name。
该接口只有一个方法 setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory。
该接口只有一个方法 setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext。
该接口只有一个方法 afterPropertiesSet(),在属性注入完成后调用。
该接口只有一个方法 destroy(),在容器销毁的时候调用,在用户指定的 destroy-method 之前调用。
该接口有两个方法:
postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法
postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法
通过方法签名我们可以知道,我们可以通过 beanName 来筛选出我们需要进行个性化定制的 bean。
该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:
postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用
postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用
会将Bean解析成Spring内部的BeanDefinition结构;
理解为:将spring.xml中的
有点类似于XML解析
scope、ref(依赖的bean)等等。其实就是将bean(例如
存储到这个对应BeanDefinition相应的属性中
例如:
-----> BeanDefinition(id/class/scope)
注意:
4.1BeanFactoryPostProcessor在spring容器加载完BeanDefinition之后,
在bean实例化之前执行的
4.2对bean元数据(BeanDefinition)进行加工处理,也就是BeanDefinition
属性填充、修改等操作
例如:
BeanFactory -> List
BeanDefinition(id/class/scope/init-method)
foreach(BeanDefinition bean : List){
//根据class属性反射机制实例化对象
//反射赋值设置属性
}
例如:BeanNameAware、ApplicationContextAware等等
BeanDefinition 实现了 BeanNameAware、ApplicationContextAware
在显示调用初始化方法的前后添加自定义的逻辑。(类似于AOP的绕环通知)
前提条件:如果检测到Bean对象实现了BeanPostProcessor后置处理器才会执行
Before和After方法
BeanPostProcessor
1)Before
2)调用初始化Bean(InitializingBean和init-method,Bean的初始化才算完成)
3)After
完成了Bean的创建工作
1.xml/annotation/configuation 配置JavaBean
2.BeanDefinitionReader解析配置的Javabean得到BeanDefinition最终得到List集合
3.触发BeanFactoryPostProcessor,在Javabean初始化之前执行自己的业务
spring中的beanFactory,会通过List集合遍历初始化所有的Javabean对象
如果javabean需要调动spring上下文的资源,那么需要实现Aware感知接口
4.如果自己的javabean以及初始化好了,还需要扩展功能,那么还需要借助BeanFactoryPostProcessor来实现
package com.lz.beanLife;
import org.springframework.beans.factory.config.BeanDefinition;
import java.util.ArrayList;
import java.util.List;
/**
* @author lz
* @create 2023-08-18 14:39
*/
public class demo1 {
public static void main(String[] args) {
//解析spring-context 内容
List beans = new ArrayList();
//遍历解析
for (BeanDefinition bean: beans) {
String beanClassName = bean.getBeanClassName();
try {
Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
class User{
}
class Person{
private int pid;
private String pname;
private String sex;
private User user;
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Person(int pid, String pname, String sex) {
this.init();
this.pid = pid;
this.pname = pname;
this.sex = sex;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"pid=" + pid +
", pname='" + pname + '\'' +
", sex='" + sex + '\'' +
'}';
}
public void init() {
}
}
抽烟
烫头
大保健
1.默认是单例,但是可以配置多例
2.单例 的优点是节约内存,弊端有变量污染!
多例 的优点是无变量污染,弊端消耗内存!
3.单例javabean是跟着spring上下文初始化的,同生共死!
多例javabean使用才会初始化