bean 生命周期13个环节
- 阶段1:bean元信息配置阶段
- 阶段2:bean元信息解析阶段
- 阶段3:将bean注册到容器中
- 阶段4:beanDefinition合并阶段
- 阶段5:bean class加载阶段
- 阶段6:bean 实例化阶段
6.1:bean实例化前阶段
6.2:bean实例化阶段 - 阶段7:合并后的beanDefinition处理
- 阶段8:属性赋值阶段
8.1:bean实例化后阶段
8.2:bean属性赋值前阶段
8.3:bean属性赋值阶段 - 阶段9:bean初始化阶段
9.1:bean aware 接口回调阶段
9.2:bean 初始化前阶段
9.3:bean 初始化阶段
9.4:bean 初始化后阶段 - 阶段10:所有单例bean初始化完成后阶段
- 阶段11:bean的使用阶段
- 阶段12:bean销毁前阶段
- 阶段13:bean销毁阶段
阶段1:Bean元信息配置阶段
Bean 信息定义4中方式
- API的方式
- Xml的方式
- properties文件的方式
- 注解的方式
API方式
我们只说这种方式,因为其他几种方式最终都会采用这种方式来定义bean配置信息。Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。
不管是是通过xml配置文件的标签,还是通过注解配置的@Bean,还是@Compontent标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。
BeanDefinition里面里面包含了bean定义的各种信息,如:bean对应的class、scope、lazy信息、dependOn信息、autowireCandidate(是否是候选对象)、primary(是否是主要的候选者)等信息。
BeanDefinition是个接口,有几个实现类,看一下类图:
BeanDefinition接口:bean定义信息接口,里面定义了一些获取bean定义配置信息的各种方法
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* 设置此bean的父bean名称(对应xml中bean元素的parent属性)
*/
void setParentName(@Nullable String parentName);
/**
* 返回此bean定义时指定的父bean的名称
*/
@Nullable
String getParentName();
/**
* 指定此bean定义的bean类名(对应xml中bean元素的class属性)
*/
void setBeanClassName(@Nullable String beanClassName);
/**
* 返回此bean定义的当前bean类名
* 注意,如果子定义重写/继承其父类的类名,则这不一定是运行时使用的实际类名。此外,这可能只是调用工厂方法的类,或者在调用方法的工厂bean引用的情况下,它甚至可能是空的。因此,不要认为这是运行时的最终bean类型,而只将其用于单个bean定义级别的解析目的。
*/
@Nullable
String getBeanClassName();
/**
* 设置此bean的生命周期,如:singleton、prototype(对应xml中bean元素的scope属性)
*/
void setScope(@Nullable String scope);
/**
* 返回此bean的生命周期,如:singleton、prototype
*/
@Nullable
String getScope();
/**
* 设置是否应延迟初始化此bean(对应xml中bean元素的lazy属性)
*/
void setLazyInit(boolean lazyInit);
/**
* 返回是否应延迟初始化此bean,只对单例bean有效
*/
boolean isLazyInit();
/**
* 设置此bean依赖于初始化的bean的名称,bean工厂将保证dependsOn指定的bean会在当前bean初始化之前先初始化好
*/
void setDependsOn(@Nullable String... dependsOn);
/**
* 返回此bean所依赖的bean名称
*/
@Nullable
String[] getDependsOn();
/**
* 设置此bean是否作为其他bean自动注入时的候选者
* autowireCandidate
*/
void setAutowireCandidate(boolean autowireCandidate);
/**
* 返回此bean是否作为其他bean自动注入时的候选者
*/
boolean isAutowireCandidate();
/**
* 设置此bean是否为自动注入的主要候选者
* primary:是否为主要候选者
*/
void setPrimary(boolean primary);
/**
* 返回此bean是否作为自动注入的主要候选者
*/
boolean isPrimary();
/**
* 指定要使用的工厂bean(如果有)。这是要对其调用指定工厂方法的bean的名称。
* factoryBeanName:工厂bean名称
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
/**
* 返回工厂bean名称(如果有)(对应xml中bean元素的factory-bean属性)
*/
@Nullable
String getFactoryBeanName();
/**
* 指定工厂方法(如果有)。此方法将使用构造函数参数调用,如果未指定任何参数,则不使用任何参数调用。该方法将在指定的工厂bean(如果有的话)上调用,或者作为本地bean类上的静态方法调用。
* factoryMethodName:工厂方法名称
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
/**
* 返回工厂方法名称(对应xml中bean的factory-method属性)
*/
@Nullable
String getFactoryMethodName();
/**
* 返回此bean的构造函数参数值
*/
ConstructorArgumentValues getConstructorArgumentValues();
/**
* 是否有构造器参数值设置信息(对应xml中bean元素的<constructor-arg />子元素)
*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/**
* 获取bean定义是配置的属性值设置信息
*/
MutablePropertyValues getPropertyValues();
/**
* 这个bean定义中是否有属性设置信息(对应xml中bean元素的<property />子元素)
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/**
* 设置bean初始化方法名称
*/
void setInitMethodName(@Nullable String initMethodName);
/**
* bean初始化方法名称
*/
@Nullable
String getInitMethodName();
/**
* 设置bean销毁方法的名称
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/**
* bean销毁的方法名称
*/
@Nullable
String getDestroyMethodName();
/**
* 设置bean的role信息
*/
void setRole(int role);
/**
* bean定义的role信息
*/
int getRole();
/**
* 设置bean描述信息
*/
void setDescription(@Nullable String description);
/**
* bean描述信息
*/
@Nullable
String getDescription();
/**
* bean类型解析器
*/
ResolvableType getResolvableType();
/**
* 是否是单例的bean
*/
boolean isSingleton();
/**
* 是否是多列的bean
*/
boolean isPrototype();
/**
* 对应xml中bean元素的abstract属性,用来指定是否是抽象的
*/
boolean isAbstract();
/**
* 返回此bean定义来自的资源的描述(以便在出现错误时显示上下文)
*/
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
RootBeanDefinition类:表示根bean定义信息,通常bean中没有父bean的就使用这种表示
ChildBeanDefinition类:表示子bean定义信息,如果需要指定父bean的,可以使用ChildBeanDefinition来定义子bean的配置信息,里面有个parentName属性,用来指定父bean的名称。
GenericBeanDefinition类:通用的bean定义信息,既可以表示没有父bean的bean配置信息,也可以表示有父bean的子bean配置信息,这个类里面也有parentName属性,用来指定父bean的名称。
BeanDefinitionBuilder:构建BeanDefinition的工具类,spring中为了方便操作BeanDefinition,提供了一个类:BeanDefinitionBuilder,内部提供了很多静态方法,通过这些方法可以非常方便的组装BeanDefinition对象
案例 :组装一个简单的bean
public class Car {
}
@Test
public void testCar(){
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class);
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
System.out.println(beanDefinition);
}
运行结果:
Root bean: class [com.spring.beanLife.Car]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
案例:组装一个有属性的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 + '\'' +
'}';
}
}
@Test
public void testCar(){
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class);
//添加属性
beanDefinitionBuilder.addPropertyValue("name","Audi");
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
//创建spring容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//把beanDefinition注册到容器中
beanFactory.registerBeanDefinition("car",beanDefinition);
Car bean = (Car) beanFactory.getBean("car");
System.out.println(bean);
}
运行结果:
Car{name='Audi'}
案例:组装一个有依赖关系的bean
两个类,一个car , 一个user .
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 + '\'' +
'}';
}
}
public class User {
private Car car;
@Override
public String toString() {
return "User{" +
"car=" + car +
'}';
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
测试:
@Test
public void testUserCar(){
AbstractBeanDefinition carBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Car.class)
.addPropertyValue("name","Audi")
.getBeanDefinition();
AbstractBeanDefinition userBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class)
/**
* <bean id="car" class="xxx.Car">
* <property name="name" value="奥迪"/>
* </bean>
*
* <bean id="user" class="xxx.User">
* <property name="car" ref="car"/>
* </bean>
*/
.addPropertyReference("car","car")
.getBeanDefinition();
//创建spring容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("car",carBeanDefinition);
beanFactory.registerBeanDefinition("user",userBeanDefinition);
System.out.println(beanFactory.getBean("user"));
System.out.println(beanFactory.getBean("car"));
}
运行结果:
User{car=Car{name='Audi'}}
Car{name='Audi'}
小结
bean注册者只识别BeanDefinition对象,不管什么方式最后都会将这些bean定义的信息转换为BeanDefinition对象,然后注册到spring容器中。
阶段2:Bean元信息解析阶段
Bean元信息的解析就是将各种方式定义的bean配置信息解析为BeanDefinition对象。
Bean元信息的解析主要有3种方式
- xml文件定义bean的解析
- properties文件定义bean的解析
- 注解方式定义bean的解析
XML方式解析:XmlBeanDefinitionReader
spring中提供了一个类XmlBeanDefinitionReader,将xml中定义的bean解析为BeanDefinition对象。
这里,我只提供一段代码,可以新建xml进行测试:
@Test
public void testXmlRead(){
//定义spring容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//定义一个xml的BeanDefinition读取器
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//定义xml路径,然后读取
String path = "";
xmlBeanDefinitionReader.loadBeanDefinitions(path);
//从容器中获取bean
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
}
注意:这种方式,获取的BeanDefinition都是GenericBeanDefinition这种类型的,也就是说xml中定义的bean被解析之后都是通过GenericBeanDefinition这种类型表示的。
properties文件定义bean的解析:PropertiesBeanDefinitionReader
spring中提供了一个类PropertiesBeanDefinitionReader,将properties中定义的bean解析为BeanDefinition对象,过程和xml的方式类似。
@Test
public void testProperties(){
//定义spring容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
PropertiesBeanDefinitionReader definitionReader = new PropertiesBeanDefinitionReader(beanFactory);
String path = "";
definitionReader.loadBeanDefinitions(path);
//从容器中获取bean
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
}
**注解方式:AnnotatedBeanDefinitionReader **
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Primary
@Lazy
public class Service1 {
}
public class Service2 {
@Autowired
Service1 service1;
@Override
public String toString() {
return "Service2{" +
"service1=" + service1 +
'}';
}
}
@Test
public void testAnn(){
//定义spring容器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
AnnotatedBeanDefinitionReader definitionReader = new AnnotatedBeanDefinitionReader(factory);
definitionReader.register(com.spring.beanLife.Service1.class, com.spring.beanLife.Service2.class);
//打印出注册的bean的配置信息
for (String beanName : new String[]{"service1", "service2"}) {
//通过名称从容器中获取对应的BeanDefinition信息
BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);
//获取BeanDefinition具体使用的是哪个类
String beanDefinitionClassName = beanDefinition.getClass().getName();
//通过名称获取bean对象
Object bean = factory.getBean(beanName);
//打印输出
System.out.println(beanName + ":");
System.out.println(" beanDefinitionClassName:" + beanDefinitionClassName);
System.out.println(" beanDefinition:" + beanDefinition);
System.out.println(" bean:" + bean);
}
}
输出结果:
service1:
beanDefinitionClassName:org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
beanDefinition:Generic bean: class [com.spring.beanLife.Service1]; scope=prototype; abstract=false; lazyInit=true; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
bean:com.spring.beanLife.Service1@24aed80c
14:13:35.579 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'service2'
service2:
beanDefinitionClassName:org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
beanDefinition:Generic bean: class [com.spring.beanLife.Service2]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
bean:Service2{service1=null}
输出中可以看出service1这个bean的beanDefinition中lazyInit确实为true,primary也为true,scope为prototype,说明类Service1注解上标注3个注解信息被解析之后放在了beanDefinition中。
注意下:最后一行中的service1为什么为null,不是标注了@Autowired么?大家先想下,随后我们在说。然后下个阶段:Bean注册
阶段3:Spring Bean注册阶段
bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry
BeanDefinitionRegistry:
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);
}
BeanDefinitionRegistry唯一实现:DefaultListableBeanFactory
我们经常用到的AnnotationConfigApplicationContext,但实际上其内部是转发给了DefaultListableBeanFactory进行处理的,所以真正实现这个接口的类是DefaultListableBeanFactory。
案例
@Test
public void testBeanDefinitionRegistry() {
//创建一个bean工厂,这个默认实现了BeanDefinitionRegistry接口,所以也是一个bean注册器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//定义一个bean
GenericBeanDefinition nameBdf = new GenericBeanDefinition();
nameBdf.setBeanClass(String.class);
nameBdf.getConstructorArgumentValues().addIndexedArgumentValue(0, "Java");
//将bean注册到容器中
factory.registerBeanDefinition("name", nameBdf);
//通过名称获取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"));
}
下面要介绍的从阶段4到阶段14,也就是从:BeanDefinition合并阶段到Bean初始化完成阶段,都是在调用getBean从容器中获取bean对象的过程中发送的操作,要注意细看了,大家下去了建议去看getBean这个方法的源码,以下过程均来自于这个方法:
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean