关于bean的创建篇章,本节是终结篇,也是我们对#doCreateBean(...)方法的最后一个过程的详细分析,即初始化bean,这里的bean是我们最终想要的bean,直接看代码:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
//1.激活Aware,对特殊的bean进行处理,比如:Aware BeanClassLoaderAware BeanFactoryAware
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//同上
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//2.应用前置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//3.激活用户自定义的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//4.应用后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
上述就是初始化bean的过程,简单的来小结一下流程:
- 激活Aware方法
- 2.前置处理器的应用
- 3.激活用户自定义的方法
- 后置处理器的应用
我们分别来看上述的这四个流程
激活Aware方法
我们先来了解下什么是Aware,Aware是感知的意思,在spring中提供了一些Aware相关的接口,如:BeanFactoryAware ApplicationContextAware ResourceLoaderAware ServletContextAware BeanClassLoaderAware及ResourceLoaderAware BootstrapContextAware BeanNameAware,简单的来看几个:
- BeanFactoryAware:声明BeanFactory
- BeanClassLoaderAware:是spring类的bean加载器
- BeanNameAware: 是spring用来申明bean的名字
直接来看激活Aware的方法
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);
}
}
}
代码简单,就不多说啥了,接着我们来看前置处理器的应用
前置处理器的应用
BeanPostProcessor相信大家不陌生,这是spring框架中的一个亮点,其主要的作用是:如果我们想要在 Spring 容器完成 Bean 的实例化,配置和其他的初始化后添加一些自己的逻辑处理,那么请使用该接口,该接口给了用户充足的权限去更改或者扩展 Spring是,我们对 Spring 进行扩展和增强处理一个必不可少的接口,直接看代码:
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;
}
上述是前置处理代码,我们再来看后置处理代码:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
关于前置和后置处理,该方法都是实现接口BeanPostProcessor接口,我们也可以实现该接口来实现对bean的逻辑处理,方法简单就不多说了,最后我们来看激活自定义的init方法
激活用户自定义的方法
何为自定义的init方法这样说可能很蒙蔽,我们可能最熟悉的是在配置文件中有时候会使用init-method,其实这里说的就是该方法,直接看代码;
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//首先是检查是否是InitializingBean,如果是需要调用afterPropertiesSet
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
//在系统安全管理器的环境下
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
//1.属性初始化后的处理
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//同上
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//2.激活自定义方法的入口
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
上述代码是激活用户自定义init方法的过程,简单的小结一下:
- 首先是对bean的判断是否是InitializingBean,是的话需要调用#afterPropertiesSet()来处理,这里考虑到了另外的一种方式是通过实现InitializingBean接口的方法,并非来自我们的init-method配置
- 判断完之后,接着是对属性的初始化过程,具体实现我们后面来说
- 最后调用#invokeCustomInitMethod(...)完成真正的激活过程,具体详解后面说.
到这里我们一个完整的bean从创建到属性填充在到循环依赖的处理最后是完成初始化就说完了,后续的文章中我们来一起学习下spring容器的扩展部分
网友评论