一.介绍在Java spring中bean的生命周期
1.什么是 Bean?
我们来看下 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 容器实例化、组装和管理的对象。
2.Java spring中bean的生命周期是什么?
在Java Spring中,Bean的生命周期是指一个Bean从被实例化到最终被销毁的整个过程。Spring容器负责管理Bean的生命周期,并在特定时机触发相应的回调方法。
3.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的创建、初始化和销毁过程,提高应用程序的灵活性和可维护性。
4.Java spring中bean的生命周期会使用到应用场景
在Java Spring中,Bean的生命周期可以应用于以下场景:
初始化配置:在Bean实例化和初始化阶段,可以执行一些初始化配置的操作,例如加载配置文件、连接数据库、初始化缓存等。
依赖注入:在Bean的属性赋值阶段,可以进行依赖注入,将其他Bean所需要的依赖项自动注入到目标Bean中。
自定义逻辑:通过在Bean的生命周期中定义回调方法,可以执行自定义的业务逻辑。例如,在初始化前后执行一些额外的逻辑操作,或者在销毁前后进行资源清理。
资源管理:可以在Bean的销毁阶段,释放占用的资源,如关闭数据库连接、释放文件句柄、停止定时任务等。
AOP(面向切面编程):可以利用Bean的生命周期回调方法,在特定的时间点织入AOP切面逻辑,例如在初始化之后执行一些切面操作。
第三方库集成:当使用某些第三方库时,可能需要在Bean的生命周期中进行初始化和销毁操作,以确保库的正确使用和释放。
总结来说,Java Spring中Bean的生命周期可以应用于初始化配置、依赖注入、自定义逻辑、资源管理、AOP和第三方库集成等场景。它可以帮助我们更好地管理和控制Bean的创建、初始化和销毁过程,提高应用程序的可维护性和可扩展性。
二. Java spring 中常用接口说明
2.1 BeanNameAware
该接口只有一个方法 setBeanName(String name),用来获取 bean 的 id 或者 name。
2.2 BeanFactoryAware
该接口只有一个方法 setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory。
2.3 ApplicationContextAware
该接口只有一个方法 setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext。
2.4 InitializingBean
该接口只有一个方法 afterPropertiesSet(),在属性注入完成后调用。
2.5 DisposableBean
该接口只有一个方法 destroy(),在容器销毁的时候调用,在用户指定的 destroy-method 之前调用。
2.6 BeanPostProcessor
该接口有两个方法:postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法
postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法
通过方法签名我们可以知道,我们可以通过 beanName 来筛选出我们需要进行个性化定制的 bean。
2.7 InstantiationAwareBeanPostProcessor
该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用
postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用
三.如何去验证生命周期
1.关系图
2.对于关系图的解释
2.1Spring Bean的生命周期:
1.通过XML、Java annotation(注解)以及Java Configuration(配置类)
等方式加载Spring Bean
2.BeanDefinitionReader:解析Bean的定义。在Spring容器启动过程中,
会将Bean解析成Spring内部的BeanDefinition结构;
理解为:将spring.xml中的<bean>标签转换成BeanDefinition结构
有点类似于XML解析
3.包含了很多属性和方法。例如:id、class(类名)、
scope、ref(依赖的bean)等等。其实就是将bean(例如<bean>)的定义信息
存储到这个对应BeanDefinition相应的属性中
例如:
<bean id="" class="" scope=""> -----> BeanDefinition(id/class/scope)
4.BeanFactoryPostProcessor:是Spring容器功能的扩展接口。
注意:
4.1BeanFactoryPostProcessor在spring容器加载完BeanDefinition之后,
在bean实例化之前执行的
4.2对bean元数据(BeanDefinition)进行加工处理,也就是BeanDefinition
属性填充、修改等操作
5.BeanFactory:bean工厂。它按照我们的要求生产我们需要的各种各样的bean。
例如:
BeanFactory -> List<BeanDefinition>BeanDefinition(id/class/scope/init-method)<bean class="com.zking.spring02.biz.BookBizImpl"/>foreach(BeanDefinition bean : List<BeanDefinition>){//根据class属性反射机制实例化对象//反射赋值设置属性}
6.Aware感知接口:在实际开发中,经常需要用到Spring容器本身的功能资源
例如:BeanNameAware、ApplicationContextAware等等
BeanDefinition 实现了 BeanNameAware、ApplicationContextAware
7.BeanPostProcessor:后置处理器。在Bean对象实例化和引入注入完毕后,
在显示调用初始化方法的前后添加自定义的逻辑。(类似于AOP的绕环通知)
前提条件:如果检测到Bean对象实现了BeanPostProcessor后置处理器才会执行
Before和After方法
BeanPostProcessor
1)Before
2)调用初始化Bean(InitializingBean和init-method,Bean的初始化才算完成)
3)After
完成了Bean的创建工作
8)destory:销毁
3.spring容器管理javabean的初始化过程
1.xml/annotation/configuation 配置JavaBean
2.BeanDefinitionReader解析配置的Javabean得到BeanDefinition最终得到List<BeanDefinition>集合
3.触发BeanFactoryPostProcessor,在Javabean初始化之前执行自己的业务
spring中的beanFactory,会通过List<BeanDefinition>集合遍历初始化所有的Javabean对象
如果javabean需要调动spring上下文的资源,那么需要实现Aware感知接口
4.如果自己的javabean以及初始化好了,还需要扩展功能,那么还需要借助BeanFactoryPostProcessor来实现
4.通过IDEA模拟测试数据
1.建立一个模拟数据(并且解析spring配置的xml文件)
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<BeanDefinition> beans = new ArrayList<BeanDefinition>();//遍历解析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() {}@Overridepublic String toString() {return "Person{" +"pid=" + pid +", pname='" + pname + '\'' +", sex='" + sex + '\'' +'}';}public void init() {}
}
2.spring需要配置的xml文件
<bean id="paramAction" class="com.lz.beanLife.ParamAction"><constructor-arg name="name" value="刘兵sb"></constructor-arg><constructor-arg name="age" value="21"></constructor-arg><constructor-arg name="hobby"><list><value>抽烟</value><value>烫头</value><value>大保健</value></list></constructor-arg></bean><bean id="instanceFactory" class="com.lz.beanLife.InstanceFactory"scope="prototype" init-method="init" destroy-method="destroy"></bean>
3.响应图片单例模式
5.总结spring中Javabean是单例还是多例
1.默认是单例,但是可以配置多例
2.单例 的优点是节约内存,弊端有变量污染!
多例 的优点是无变量污染,弊端消耗内存!
3.单例javabean是跟着spring上下文初始化的,同生共死!
多例javabean使用才会初始化