bean的生命周期详解
beanFactory容器启动之后,首先解析配置文件,生成并注册beanDefinition对象。beanDefinition包含了bean的实例化阶段所必需的信息。只有通过getBean方法来获取某个对象的实例使,容器才实例化这个对象。这一点更ApplicationContext容器不同,在getBean方法调用之前就将所有的类实例化。但是这两个容器都有一个特点,只要实例化一个对象,并且这个对象是单例模式,那么容器就有指向这个对象的引用,该对象的生命周期就由容器管理。接下来将详细介绍bean的生命周期的各个阶段。
Bean实例化过程图
实例化bean对象
容器实例化bean是采用“策略模式”来决定采用何种方式来初始化bean实例。可以通过反射或CGLIB动态字节码来生成初始化相应bean实例或则动态生成其子类。InstantiationStrategy接口定义了实例化策略的抽象接口。其子类SimpleInstantiationStrategy实现了简单的对象实例化功能,可以通过反射来支持对象实例化,但不支持方法注入方式。CglibSubclassInstantiationStrategy继承了SimpleInstantiationStrategy类的以反射方式来实例化对象,并且使用cglib动态字节码生成技术,动态生成某个类的子类,从而支持方法注入方式。实例化之后,并不是直接返回bean对象,而是返回一个BeanWrapper对象,该对象封装了bean实例。之所以封装成BeanWrapper对象,是方便第二部的为对象赋值的操作。
InstantiationStrategy接口方法全是对象实例化方法,入参都含有BeanDefinition对象。可以看出,spring容器实例化对象都要使用BeanDefinition对象。
如果对方法注入不是很熟悉,请点击这里
public interface InstantiationStrategy {
Object instantiate(RootBeanDefinition var1, String var2, BeanFactory var3) throws BeansException;
Object instantiate(RootBeanDefinition var1, String var2, BeanFactory var3, Constructor<?> var4, Object... var5) throws BeansException;
Object instantiate(RootBeanDefinition var1, String var2, BeanFactory var3, Object var4, Method var5, Object... var6) throws BeansException;
}
InstantiationStrategy接口实现图:
SimpleInstantiationStrategy类的instantiate方法解析:
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
if (bd.getMethodOverrides().isEmpty()) {
Constructor constructorToUse;
synchronized(bd.constructorArgumentLock) {
//获取配置文件中设置的构造器方法
constructorToUse = (Constructor)bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
//获取beanDefinition对象中的类对象
final Class<?> clazz = bd.getBeanClass();
//如果类对象是接口则抛出异常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = (Constructor)AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
public Constructor<?> run() throws Exception {
//调用class对象的无参构造器,使用java反射机制实例化对象
return clazz.getDeclaredConstructor((Class[])null);
}
});
} else {
constructorToUse = clazz.getDeclaredConstructor((Class[])null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
} catch (Throwable var9) {
throw new BeanInstantiationException(clazz, "No default constructor found", var9);
}
}
}
/调用class对象的无参构造器,使用java反射机制实例化对象
return BeanUtils.instantiateClass(constructorToUse, new Object[0]);
} else {
//使用方法注入方式注入属性,在SimpleInstantiationStrategy类中调用此方法会抛出异常,SimpleInstantiationStrategy不支持方法注入方式
return this.instantiateWithMethodInjection(bd, beanName, owner);
}
}
CglibSubclassCreator是CglibSubclassingInstantiationStrategy的内部类,其功能是创间bean实例,支持方法注入
private static class CglibSubclassCreator {
private static final Class<?>[] CALLBACK_TYPES = new Class[]{NoOp.class, CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor.class, CglibSubclassingInstantiationStrategy.ReplaceOverrideMethodInterceptor.class};
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}
public Object instantiate(Constructor<?> ctor, Object... args) {
Class<?> subclass = this.createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
//如果没传构造器,则使用子类的无参构造器创建实例
instance = BeanUtils.instantiateClass(subclass);
} else {
try {
//根据传入的构造器,查找子类的对应构造器
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
//使用子类有参构造器,通过反射创建实例
instance = enhancedSubclassConstructor.newInstance(args);
} catch (Exception var6) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", var6);
}
}
Factory factory = (Factory)instance;
//设置回调
factory.setCallbacks(new Callback[]{NoOp.INSTANCE, new CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), new CglibSubclassingInstantiationStrategy.ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
//创建增强代理类
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
if (this.owner instanceof ConfigurableBeanFactory) {
ClassLoader cl = ((ConfigurableBeanFactory)this.owner).getBeanClassLoader();
enhancer.setStrategy(new CglibSubclassingInstantiationStrategy.ClassLoaderAwareGeneratorStrategy(cl));
}
enhancer.setCallbackFilter(new CglibSubclassingInstantiationStrategy.MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
}
属性设置
初始化bean之后,返回的是bean的包装对象BeanWrapperImpl对象,BeanWrapperImpl类间接实现了PropertyAccessor接口和TypeConverter接口,其中PropertyAccessor接口是用来为对象设置属性和获取属性值得。
public interface PropertyAccessor {
String NESTED_PROPERTY_SEPARATOR = ".";
char NESTED_PROPERTY_SEPARATOR_CHAR = '.';
String PROPERTY_KEY_PREFIX = "[";
char PROPERTY_KEY_PREFIX_CHAR = '[';
String PROPERTY_KEY_SUFFIX = "]";
char PROPERTY_KEY_SUFFIX_CHAR = ']';
boolean isReadableProperty(String var1);
boolean isWritableProperty(String var1);
Class<?> getPropertyType(String var1) throws BeansException;
TypeDescriptor getPropertyTypeDescriptor(String var1) throws BeansException;
Object getPropertyValue(String var1) throws BeansException;
void setPropertyValue(String var1, Object var2) throws BeansException;
void setPropertyValue(PropertyValue var1) throws BeansException;
void setPropertyValues(Map<?, ?> var1) throws BeansException;
void setPropertyValues(PropertyValues var1) throws BeansException;
void setPropertyValues(PropertyValues var1, boolean var2) throws BeansException;
void setPropertyValues(PropertyValues var1, boolean var2, boolean var3) throws BeansException;
}
使用接口的复制方法,只要指定属性名称和属性值,便可以为接口中的包装对象设置值,因为不用j直接使用java 反射api就可以简单实现。大大简化了属性赋值操作。
检测Aware接口实现类
当对象实例化后,并完成相关属性设置,spring容器开始检测该bean是否实现了Aware接口,,如果实现了Aware接口,则将接口规定的依赖注入给当前对象。Aware接口为如下几个:
- BeanNameAware:会将对象实例对应的bean定义对应的beanName设置到当前对象中去。
- BeanClassLoaderAware:将加载当前bean的classLoader设置到对象中去。
- BeanFactoryAware:beanFactory容器会将自身设置到当前对象中去
- ResourceLoaderAware:ApplicationContext会将自身设置到当前对象中去。
- ApplicationEventPublisherAware:会将ApplicationEventPublisher设置到当前对象中去(ApplicationContext实现了ApplicationEventPublisher接口,因此这时候ApplicatonContext容器会将自身设置到当前对象中去)。
- MessageSourceAware:将MessageSource对象设置到当前实例中去(ApplicationContext实现了MessageSource接口,因此这时候ApplicatonContext容器会将自身设置到当前对象中去)
- ApplicationContextAware:会将自身设置到当前对象中去。
上面的这些规则读起来十分绕缺口,简单来说,如果你定义了一个类,在对象的使用过程中你会用到BeanFactory对象,那么你就只需要实现BeanFactoryAware接口,同时在定义的类中增加一个BeanFactory属性。由于你实现了BeanFactoryAware接口,因此自定义类中也会有一个接口方法setBeanFactory(BeanFactory var1),在该方法中,你字需要将传入的参数赋给自定义类的对应属性即可。自定义类实例化完成后,容器会自动调用该方法,完成属性的赋值工作。代码如下:
public class People implements BeanFactoryAware {
private BeanFactory beanFactory;
//容器会自动调用该方法,完成赋值工作
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
BeanPostProcessor接口
讲到BeanPostProcessor接口,首先要和BeanFactoryPostProcessor接口区分开来,想了解BeanFactoryPostProcessor接口的朋友请点击这里,BeanPostProcessor接口方法调用时在对象实例化之后,而BeanFactoryPostProcessor接口方法调用是在容器启动阶段,对所有满足条件的beanDefinition做操作,此时bean还没有实例化。BeanPostProcessor接口又两个接口方法,分别为:postProcessBeforeInitialization(又称为前置处理方法),postProcessAfterInitialization(又称为后置处理方法)。两个方法都将bean实例的引用当做参数传入。
public interface BeanPostProcessor {
//前置处理方法
Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
//后置处理方法
Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}
BeanPostProcessor接口通常用来处理标记接口实现类或则为当前接口实现代理。上面讲的Aware接口处理实际上就是使用BeanPostProcessor方式进行处理的。当容器中的对象走到BeanPostProcessor的前置处理器这一步时,ApplicationContext容器就会检测之前注册到容器中的ApplicationContextAwareProcessor类(此类是BeanPostProcessor接口的实现类),然后调用前置处理方法,检测并设置Aware相关依赖。
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
//检测Aware接口并设置相关依赖
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
//检测Aware接口并设置相关依赖
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
//如果当前实例实现Aware接口
if (bean instanceof Aware) {
//如果实现
if (bean instanceof EnvironmentAware) {
//为当前实例设置environment依赖
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
//如果实现EmbeddedValueResolverAware
if (bean instanceof EmbeddedValueResolverAware) {
//为当前实例设置embeddedValueResolver依赖
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
//如果实现ResourceLoaderAware
if (bean instanceof ResourceLoaderAware) {
//为当前实例设置applicationContext依赖
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
//如果实现ApplicationEventPublisherAware
if (bean instanceof ApplicationEventPublisherAware) {
//为当前实例设置applicationContext依赖
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
//如果实现MessageSourceAware
if (bean instanceof MessageSourceAware) {
//为当前实例设置applicationContext依赖
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
//如果实现ApplicationContextAware
if (bean instanceof ApplicationContextAware) {
//为当前实例设置applicationContext依赖
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
BeanPostProcessor是spring为开发者提供的一个非常有用的拓展点,我们可以通过实现BeanPostProcessor接口,实现接口方法,从而对满足条件的bean实例进行修改或则替换,比如对当前对象进行增强操作。创建好自定义类之后,将该类注册到容器中即可。
检测是否为InitializingBean实现类
这里手下说明一下,实现InitializingBean接口和在配置文件中配置init-method属性的作用是一样的,两者都是在执行完Aware接口处理之后,会调用InitializingBean实现类的afterPropertySet方法或者执行init-method指定的方法。但是通过实现InitializingBean接口的方式具有侵入性,因此在实际开发中,我们更倾向于使用init-method配置的方式。
spring.xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="user" class="springBeanTest.User" init-method="init">
</bean>
</beans>
User类:
public class User {
private String username;
private String password;
public void init(){
this.username = "ranxiaochuan";
this.password = "123";
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
测试类
public class LifeCycleTest {
@Test
public void test1(){
//创建bean的工厂类
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//创建一个xml文件的reader类,将bean工厂传入reader中
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
//加载xml未配置文件,并将配置文件解析成BeanDefinition对象保存在工厂类中
reader.loadBeanDefinitions("classpath:/spring.xml");
User user = (User) beanFactory.getBean("user");
System.out.println(user.getPassword());
System.out.println(user.getUsername());
}
}
测试结果:
BeanPostProcessor后置处理
BeanPostProcessor后置处理跟BeanPostProcessor前置处理思路一样,只是调用时间有差别。这里就不再赘述。
检查是否实现DisposableBean接口或则是否配置destroy方法
实现DisposableBean接口和配置destroy方法的作用是一样的,前者有侵入性,后者没有。他们的作用都是在对象销毁前做一些清理工作,比如说对与数据库连接对象,在销毁之前应该关闭数据库连接。这里需要主要一点,无论是BeanFactory容器还是ApplicationContext容器,如果要调用销毁方法,都必须在主程序执行结束之前显示的调用容器的销毁方法。BeanFactory容器调用distroySingletons()方法;ApplicationContext容器调用registerShutDownHook()方法。到此,bean的生命周期就结束了。