一.bean生命周期的理解
spring把放到容器里的简单的java对象(pojo)称作bean。bean生命周期大概就是从一个bean信息定义到bean注册到bean实例化到bean初始化到bean销毁的过程。而spring为我们提供了一个BeanPostProcessor接口。还有很多子接口,这些接口中提供了很多方法,spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展和对bean的生命周期进行干预。
1,bean信息定义阶段
spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。不管是是通过xml
配置文件的 标签,还是通过注解配置的 @Bean ,还是 @Compontent 标注的类,还是扫描得到
的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义
信息,对bean进行实例化、初始化等等操作。你可以把BeanDefinition丢给Bean工厂,然后Bean工厂就会根据这个信息帮你生产一个Bean实例,拿
去使用。
BeanDefinition里面里面包含了bean定义的各种信息,如:bean对应的class、scope、lazy信息、
dependOn信息、autowireCandidate(是否是候选对象)、primary(是否是主要的候选者)等信
息。
## 1.1 BeanDefinition相关的几个类和接口:
RootBeanDefinition类
表示根bean定义信息通常bean中没有父bean的就使用这种表示
ChildBeanDefinition类
表示子bean定义信息如果需要指定父bean的,可以使用ChildBeanDefinition来定义子bean的配置信息,里面有个parentName 属性,用来指定父bean的名称。
GenericBeanDefinition类
通用的bean定义信息既可以表示没有父bean的bean配置信息,也可以表示有父bean的子bean配置信息,这个类里面也有parentName属性,用来指定父bean的名称。
ConfigurationClassBeanDefinition类
表示通过配置类中@Bean方法定义bean信息,可以通过配置类中使用@Bean来标注一些方法,通过这些方法来定义bean,这些方法配置的bean信息最后会转换为ConfigurationClassBeanDefinition类型的对象
AnnotatedBeanDefinition接口
表示通过注解的方式定义的bean信息
BeanDefinitionBuilder
构建BeanDefinition的工具类,spring中为了方便操作BeanDefinition,提供了一个类BeanDefinitionBuilder ,内部提供了很多静态方法,通过这些方法可以非常方便的组装BeanDefinition对象。
1.2 来几个案列
/**
* 简单一个bean
*
*/
public class Car {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
'}';
}
}
例1:组装一个简单的bean
public class Test1 {
public static void main(String[] args) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class.getName());
//获取BeanDefinition
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
System.out.println(beanDefinition);
}
}
输出:Root bean: class [beanLife.bean.Car]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
例2: 组装一个有属性的bean
public class Test2 {
public static void main(String[] args) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class.getName())
.addPropertyValue("name","大众").setLazyInit(true);
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
System.out.println(beanDefinition);
//创建spring容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//调用registerBeanDefinition向容器中注册bean
beanFactory.registerBeanDefinition("MyCar",beanDefinition);
Car bean = beanFactory.getBean("MyCar", Car.class);
System.out.println(bean);
}
}
输出:
`Root bean: class [beanLife.bean.Car]; scope=; abstract=false; lazyInit=true; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
Car{name='大众'}`
2,bean注册阶段
bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry。这个接口中定义了注册bean常用到的一些方法,如下:
public interface BeanDefinitionRegistry extends AliasRegistry {
/**
* 注册一个新的bean定义
* beanName:bean的名称
* beanDefinition:bean定义信息
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
/**
* 通过bean名称移除已注册的bean
* beanName:bean名称
*/
void removeBeanDefinition(String beanName) throws
NoSuchBeanDefinitionException;
/**
* 通过名称获取bean的定义信息
* beanName:bean名称
*/
BeanDefinition getBeanDefinition(String beanName) throws
NoSuchBeanDefinitionException;
/**
* 查看beanName是否注册过
*/
boolean containsBeanDefinition(String beanName);
/**
* 获取已经定义(注册)的bean名称列表
*/
String[] getBeanDefinitionNames();
/**
* 返回注册器中已注册的bean数量
*/
int getBeanDefinitionCount();
/**
* 确定给定的bean名称或者别名是否已在此注册表中使用
* beanName:可以是bean名称或者bean的别名
*/
boolean isBeanNameInUse(String beanName);
}
spring中BeanDefinitionRegistry接口有一个唯一的实现类:
org.springframework.beans.factory.support.DefaultListableBeanFactory
例:
@Test
public void test1(){
//创建一个bean工厂,这个默认实现了BeanDefinitionRegistry接口,所以也是一个bean注册器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//定义一个bean
GenericBeanDefinition nameBdf = new GenericBeanDefinition();
nameBdf.setBeanClass(String.class);
nameBdf.getConstructorArgumentValues().addIndexedArgumentValue(0,"刘德华");
//将bean注册到容器中
factory.registerBeanDefinition("name",nameBdf);
//通过bean名获取BeanDefinition
System.out.println(factory.getBeanDefinition("name"));
//通过名称判断是否注册过BeanDefinition
System.out.println(factory.containsBeanDefinition("name"));
//获取所有注册的名称
System.out.println(Arrays.asList(factory.getBeanDefinitionNames()));
//获取已注册的BeanDefinition的数量
System.out.println(factory.getBeanDefinitionCount());
//判断指定的name是否使用过
System.out.println(factory.isBeanNameInUse("name"));
//别名相关方法
//为name注册2个别名
factory.registerAlias("name","alias-name-1");
factory.registerAlias("name","alias-name-2");
////判断alias-name-1是否已被作为别名使用
System.out.println(factory.isAlias("alias-name-1"));
//通过名称获取对应的所有别名
System.out.println(Arrays.asList(factory.getAliases("name")));
//最后我们再来获取一下这个bean
System.out.println(factory.getBean("name"));
}
输出:
Generic bean: class [java.lang.String]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
true
[name]
1
true
true
[alias-name-2, alias-name-1]
刘德华
3,bean实例化阶段
分2个小的阶段
- Bean实例化前操作
- Bean实例化操作
3.1Bean实例化前操作
Bean实例化之前会调用一段代码:
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?>
beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass,beanName);
if (result != null) {
return result;
}
}
}
return null;
}
这段代码在bean实例化之前给开发者留了个口子,开发者自己可以在这个地方直接去创建一个对象作
为bean实例,而跳过spring内部实例化bean的过程。该代码轮询 beanPostProcessors 列表,如果类型是
InstantiationAwareBeanPostProcessor , 尝试调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring自带的实例化bean的过程就被跳过了。
来个案例:
public class InstantiationAwareBeanPostProcessorTest {
@Test
public void test1() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//添加一个BeanPostProcessor:InstantiationAwareBeanPostProcessor
factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
//@1
@Nullable
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass,
String beanName) throws BeansException {
System.out.println("调用postProcessBeforeInstantiation()");
//发现类型是Car类型的时候,硬编码创建一个Car对象返回
if (beanClass == Car.class) {
Car car = new Car();
car.setName("保时捷");
return car;
}
return null;
}
});
//定义一个car bean,车名为:奥迪
AbstractBeanDefinition carBeanDefinition = BeanDefinitionBuilder.
genericBeanDefinition(Car.class).
addPropertyValue("name", "奥迪"). //@2
getBeanDefinition();
factory.registerBeanDefinition("car", carBeanDefinition);
//从容器中获取car这个bean的实例,输出
System.out.println(factory.getBean("car"));
}
}
输出:
调用postProcessBeforeInstantiation()
Car{name='保时捷'}
3.2 Bean实例化操作
这个过程会通过反射来调用bean的构造器来创建bean的实例。
具体需要使用哪个构造器,spring为开发者提供了一个接口,允许开发者自己来判断用哪个构造器。
这个过程会调用 SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors 方
法,这个方法会返回候选的构造器列表,也可以返回空。源码如下:
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass,
String beanName)
throws BeansException {
return null;
}
我们可以重写InstantiationAwareBeanPostProcessor#determineCandidateConstructors方法来决定使用bean的哪个构造方法来实例化我们的bean。
4,Bean初始化阶段
这个阶段分为几个小的阶段:
1.Bean Aware接口回调
2.Bean初始化前操作
3.Bean初始化操作
4.Bean初始化后操作
## 4.1 Bean Aware接口回调
我们的bean可以实现BeanNameAware, BeanClassLoaderAware,BeanFactoryAware 这些接口,这些接口会按照下面顺序依次进行调用并可以帮助我们在bean创建完成后注入:
BeanNameAware:将bean的名称注入进去
BeanClassLoaderAware:将BeanClassLoader注入进去
BeanFactoryAware:将BeanFactory注入进去
比如:
public class AwareBean implements BeanNameAware, BeanClassLoaderAware,
BeanFactoryAware {
@Override
public void setBeanName(String name) {
System.out.println("setBeanName:" + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory:" + beanFactory);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("setBeanClassLoader:" + classLoader);
}
}
## 4.2 Bean初始化前操作
这个阶段会调用 BeanPostProcessor的postProcessBeforeInitialization 方法,若返回null,当前方法将结
束。
接口BeanPostProcessor有两个实现类:
org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
如果bean实现了下面的接口 ,org.springframework.context.support.ApplicationContextAwareProcessor这个接口的#postProcessBeforeInitialization 中会依次调用下面接口中的方法,将 Aware 前缀对应的对象注入到bean实例中。
EnvironmentAware:注入Environment对象
EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
ResourceLoaderAware:注入ResourceLoader对象
ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
MessageSourceAware:注入MessageSource对象
ApplicationContextAware:注入ApplicationContext对象
如:
public class Bean1 implements EnvironmentAware, EmbeddedValueResolverAware,
ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,
ApplicationContextAware {
@PostConstruct
public void postConstruct1() {
System.out.println("postConstruct1()");
}
@PostConstruct
public void postConstruct2() {
System.out.println("postConstruct2()");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
System.out.println("setApplicationContext:" + applicationContext);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher
applicationEventPublisher) {
System.out.println("setApplicationEventPublisher:" +
applicationEventPublisher);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println("setEmbeddedValueResolver:" + resolver);
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("setEnvironment:" + environment.getClass());
}
@Override
public void setMessageSource(MessageSource messageSource) {
System.out.println("setMessageSource:" + messageSource);
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("setResourceLoader:" + resourceLoader);
}
}
## 4.3 Bean初始化阶段
2个步骤
- 调用InitializingBean接口的afterPropertiesSet方法
- 调用定义bean的时候指定的初始化方法。
InitializingBean接口
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
如:
public class Service implements InitializingBean{
public void init() {
System.out.println("调用init()方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用afterPropertiesSet()");
}
}
## 4.4 Bean初始化后阶段
会调用BeanPostProcessor接口的postProcessAfterInitialization方法 ,返回null的时候,会中断上
面的操作。
5,Bean销毁阶段
触发bean销毁的几种方式
- 调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
- 调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
- 调用ApplicationContext中的close方法
Bean销毁阶段会依次执行
- 轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调
用其内部的postProcessBeforeDestruction方法. - 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中
的destroy方法 - 调用bean自定义的销毁方法
DestructionAwareBeanPostProcessor接口:
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
/**
* bean销毁前调用的方法
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
/**
* 用来判断bean是否需要触发postProcessBeforeDestruction方法
*/
default boolean requiresDestruction(Object bean) {
return true;
}
}
DisposableBean接口:
public interface DisposableBean {
void destroy() throws Exception;
}
触发@PreDestroy标注的方法被调用:
这个注解是在 CommonAnnotationBeanPostProcessor#postProcessBeforeDestruction 中
被处理的
如:
public class ServiceA implements DisposableBean {
public ServiceA() {
System.out.println("创建ServiceA实例");
}
@PreDestroy
public void preDestroy1() {
System.out.println("preDestroy1()");
}
@PreDestroy
public void preDestroy2() {
System.out.println("preDestroy2()");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean接口中的destroy()");
}
//自定义的销毁方法
public void customDestroyMethod() { //@1
System.out.println("我是自定义的销毁方法:customDestroyMethod()");
}
}
本文详细阐述了Spring容器中Bean从定义、注册、实例化、初始化到销毁的全过程,包括BeanDefinition的类别、注册操作、BeanPostProcessor的作用以及不同阶段的回调方法。重点介绍了如何通过BeanPostProcessor干预Bean的生命周期和使用自定义构造器实例化。
3万+

被折叠的 条评论
为什么被折叠?



