如果bean的依赖注入完成比作进化出猴子,那么最后的bean初始化过程就是给猴子穿上了衣服,变成了人。
目录
2. 依次回调bean后置处理器的postProcessBeforeInitialization方法
2.1 ApplicationContextAwareProcessor
2.2 ImportAwareBeanPostProcessor
2.3 CommonAnnotationBeanPostProcessor
4. 依次回调bean后置处理器的postProcessAfterInitialization方法
*本篇文章的项目沿用《【七】Spring IoC 最全源码详解之bean的依赖注入》的。
在doCreateBean中,依赖注入populateBean执行完成后,紧接着就是创建bean的最后一步:初始化bean。本节就来看看Spring是如何初始化bean的。
Object exposedObject = bean;
try {
// 依赖注入填充属性
populateBean(beanName, mbd, instanceWrapper);
// bean属性填充完成后,就可以进行bean的初始化工作了。依赖注入初始化工作后续文章再详细介绍。
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
throw new xxx;
}
初始化bean的入口函数是initializeBean。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 如果实现了Aware接口,就对该bean进行一些设置。
// 比如实现了BeanNameAware接口,那么对其bean的属性beanName上set上对应的beanName。
// 如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂。
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// 如果这个bd不是属于内部类的bd,就调用后置处理器的postProcessBeforeInitialization对bean进行操作。
//
// common 执行LifeCircle操作
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//如果bean实现了InitializingBean或者用户自定义的init方法方法,那么调用这些初始化方法对bean的属性进行一些个性化设置。
invokeInitMethods(beanName, wrappedBean, mbd);
// 执行后置处理器的postProcessAfterInitialization方法。AOP的原理和实现就在其中(下一篇文章再单独介绍)。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
初始化步骤大体上可以分为四步:
1. 对实现Aware接口对bean的设置。
2. 依次回调bean后置处理器的postProcessBeforeInitialization方法。
3. 执行实现了InitializingBean或者用户自定义的init方法方法。
4. 依次回调bean后置处理器的postProcessAfterInitialization方法。
1. 实现Aware接口对bean的设置
进入initializeBean方法后,不管是走带有安全检查的if分支还是走不需要检查的else分支,第一步的核心方法都是执行invokeAwareMethods(beanName, bean)方法。实现interface Aware接口用于让bean能拥有某些额外的感知能力。比如实现了BeanNameAware接口,那么对其bean的属性beanName上set上对应的beanName,那么该bean就可以知道自己的beanName是什么。 如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂,那么该bean就可以感知到创建自己的bean工厂是哪一个。具体代码如下:
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2. 依次回调bean后置处理器的postProcessBeforeInitialization方法
如果这个bd不是属于内部类的bd,就调用后置处理器的postProcessBeforeInitialization对bean进行操作。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
在不引入AOP的情况下,重要的postProcessBeforeInitialization有以下3个:
2.1 ApplicationContextAwareProcessor
ApplicationContextAwareProcessor依靠它内部invokeAwareInterfaces方法实现了以下Aware接口bean的初始化工作。
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
2.2 ImportAwareBeanPostProcessor
如果实现了ImportAware接口,在postProcessBeforeInitialization中首先解析出importingClass,使得bean能感知到importingClass。
2.3 CommonAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor会实际调用InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法执行。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 获得声明周期的元数据对象,里面存放有bean中@PostConstruct 和 @PreDestroy注解的方法
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
// 执行@PostConstruct对应的方法集,比如Human.class中对应的是 void com.Hodey.learn.bean.Human.init()这个1个方法
metadata.invokeInitMethods(bean, beanName);
return bean;
}
首先通过findLifecycleMetadata(bean.getClass());寻找到本类中属于声明周期回调的注解元数据对象。也就是寻找本类中是否有@PostConstruct 和 @PreDestroy注解的方法。然后对其中的@PostConstruct注解方法进行回调操作。
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
// 只要存在@PostConstruct注解方法,就执行回调
if (!initMethodsToIterate.isEmpty()) {
for (LifecycleElement element : initMethodsToIterate) {
element.invoke(target);
}
}
}
它先获取@PostConstruct对应的方法集checkedInitMethods,然后再for循环中依次通过element.invoke(target),在内部通过反射执行。对于本项目以Adam.class举例,会调用private void init(){ name = "Adam"; }中的name = "Adam";方法对name赋值。
在执行完成所有bean后置处理器postProcessBeforeInitialization方法回调后,就会执行下一个大步骤。
3. 用户自定义的init方法方法
如果bean实现了InitializingBean或者用户自定义的init方法方法,那么调用这些初始化方法对bean的属性进行一些个性化设置。
4. 依次回调bean后置处理器的postProcessAfterInitialization方法
最后,再回调所有bean后置处理器的postProcessAfterInitialization方法。Spring AOP的代理实现场所就在这里,由于本篇文章主要介绍IOC中bean的初始化流程,AOP的知识下个专题再介绍。执行完成postProcessAfterInitialization后,会返回最终经过这些后置处理器加工后的bean返回到doCreateBean方法中。接下来还要执行另外一种声明周期方法的注册。
5. @PreDestory方法的注册
registerDisposableBeanIfNecessary是doCreateBean返回前的最后一步。这一步是完成针对@PreDestory方法的注册。我们分析bd是单例的情况下的注册方式,原型方法大同小异。接下来方法会进入mbd.isSingleton()分支,首先创建一个adapter,然后再注册。
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// 单例bean 的销毁回调注册。 实现了DestructionAwareBeanPostProcessors,DisposableBean或者用户自定义销毁方法的都在这里注册。
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// 非单例bean的销毁回调注册
Scope scope = this.scopes.get(mbd.getScope());
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean =
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
// 这里会进行一些destroy方法的推断,推断的依据是看看方法名字是不是“close”,“shutdown”。
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
this.destroyMethod = determineDestroyMethod(destroyMethodName);
if (this.destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
else {
Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
}
// 不管怎么样都会执行本行
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
该方法看起来很复杂其实不然,inferDestroyMethodIfNecessary(bean, beanDefinition)方法仅仅是象征性的根据方法名推断destroy方法,推断的依据是看看方法名是否是“close”或“shutdown”。不管怎样都会调用filterPostProcessors方法。
private List<DestructionAwareBeanPostProcessor> filterPostProcessors(List<BeanPostProcessor> processors, Object bean) {
List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
if (!CollectionUtils.isEmpty(processors)) {
filteredPostProcessors = new ArrayList<>(processors.size());
for (BeanPostProcessor processor : processors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
if (dabpp.requiresDestruction(bean)) {
filteredPostProcessors.add(dabpp);
}
}
}
}
return filteredPostProcessors;
}
在本方法中,它还是会遍历所有的bean后置处理器, 找出实现了DestructionAwareBeanPostProcessor接口的处理器调用其dabpp.requiresDestruction(bean)方法判断是否需要加入之后需要返回的结果集filteredPostProcessors中。显然执行该任务的后置处理器就是2.3方法中的InitDestroyAnnotationBeanPostProcessor,不同的是这次调用的是requiresDestruction方法进行处理,它实际也是检查this.checkedDestroyMethods中的对象是否有值。该对象放置的解析结果就是@PreDestroy的注解方法。假如有@PreDestroy方法,那么就会添加到中返回,在registerDisposableBean中this.disposableBeans.put(beanName, bean);放入到disposableBeans这个map中完成注册。它的回调是在bean工厂的destroySingletons()或destroySingleton()被调用时进行回调方法的执行。
执行完以上步骤后,initializeBean就算执行完成了。接下来的事情,在《【七】Spring IoC 最全源码详解之bean的依赖注入》中已经讲的很明白了,再次就不再赘述了。当所有的bean都初始化完成,标志着refresh()方法中finishBeanFactoryInitialization(beanFactory)这个大步骤的完成。接下来执行完成finishRefresh()后,容器的启动流程就告一段落了。finishRefresh方法非常简单,就留给读者自行分析吧。
初始化完成,标志着容器的启动过程基本技术。时间也就从上一节的06:00来到07:00。太阳已经比你先起床了!
下一篇文章,我们将一起来探究Spring AOP的内幕,敬请期待~