Spring IOC:Bean的生命周期解剖
1.Bean的创建
传统的bean创建是通过xml加载的,如下xml配置bean:
<bean id="role1" class="com.wbg.springxmlbean.entity.Role">
<!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
相当于:
Role role=new Role();
role.setId(1);
role.setRoleName("高级工程师");
role.setNote("重要人员");-->
<property name="id" value="1"/>
<property name="roleName" value="高级工程师"/>
<property name="note" value="重要人员"/>
</bean>
这里的大致流程是:加载——>解析——>创建实例——>使用——>销毁
我们知道,创建对象的方式有三种:1.直接new,2.通过反射,3.工厂模式
反射创建对象就是通过获取Class对象来获取实例化对象:
获取Class对象的三种方式:
a.Class clazz = Class.forName();
b.Class clazz = 类名.class;
c.Class clazz = 对象名.getClass();
获取构造方法来实例化对象:
Constructor ctor = clazz.getDeclareConstructor();
Object obj = ctor.newInstance();
2.bean的定义信息及对象创建
首先我们需要了解什么是对象的实例化。所谓对象实例化,具体分为对象的实例化和初始化;实例化就是在堆中开辟一块空间,属性都是默认值;初始化是进行属性填充(set方法)以及执行初始化方法(init-method)。
除了用xml配置,我们还可以用注解注入bean,这两种方式都定义了bean的信息,以及还有其他类型的配置文件,比如json都可以配置bean信息。Spring用“BeanDefinitionReader”定义相关规范的接口,来对配置文件进行解析,转换为“BeanDefinition”对象。所以如果要扩展解析配置文件,可以通过实现"BeanDefinitionReader"接口来进行解析转换。
有了bean的定义信息之后,我们要对bean进行相关的实例化工作,通过反射进行实例化以及初始化操作,完全对象创建。
“BeanFactory”这个接口是Bean容器的一个根接口,这是为了提高可扩展性,常见的实现类是"DefaultListableBeanFactory",里面的接口包括了创建对象(反射),所以“BeanDefinition”是通过“BeanFactory”来完成创建对象的。在这个过程,可以对它做一些扩展操作,就是“PostProcessor”,有人叫它为增强器,也有人叫它后置处理器,它的本质就是进行扩展实现。所以在读取“BeanDefinition”的时候,会经过一系列的“beanFactoryPostProcessor”后置处理器,然后再由“BeanFactory”完成一系列的实例化操作。
比如我们在配置"dataSource"的bean 的时候,是这样的:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/sampledb" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}"" />
</bean>
我们需要把${}信息替换成我们具体的值,这个修改的操作就是在"PlaceholderConfigurerSupport"中进行转换的。
我们也可以自己去实现“beanFactoryPostProcessor”的扩展类来对“BeanDefinition”的定义信息进行修改。
3.bean的生命周期细节
其实通过上面,我们已经可以知道bean的生命周期了,具体是这样的:
首先实例化对象,然后填充对象属性,接着执行aware接口需要实现的方法,aware接口是为了方便通过Spring中的bean对象来获取对应容器中的相关属性值,比如我们可以通过实现BeanNameAware来获取beanName:
下一步就是执行BeanPostProcessor的before和after方法,在中间会执行“init-method”完成对象初始化,然后在after中来实现动态代理。可以通过jdk或者cglib来完成动态代理,是在“BeanPostProcessor”的实现类“AbstractAutoProxyCreator”中完成的,这里我们可以查看源码来证实给大家看。
首先这是BeanPostProcessor的两个方法,分别是前置和后置处理方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
再去看AbstractAutoProxyCreator的“postProcessAfterInitialization()”方法
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
继续往“wrapIfNecessary”这个方法看:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
这里我们看到了“this.createProxy”这个方法,里面可以找到是通过ProxyFactory获取jdk或cglib代理来实现对象代理的。
最后就是销毁动作了,这个就是我们IOC的整个生命周期的细节。