Spring源码:Bean初始化过程
程序员文章站
2022-05-21 23:05:28
...
主代码
bean完成属性注入之后,接着要以bean进行初始化,初始化过程在AbstractAutowireCapableBeanFactory抽象类中,核心代码如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// **Aware方法
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 若mbd为null或者mbd不是合成的,执行BeanPostProcessor扩展点的PostProcessBeforeInitialization进行修改实例化Bean
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
/* 调用Bean的初始化方法,这个初始化方法是在BeanDefinition中通过定义init-method属性指定的。
** 同时,如果Bean实现了InitializingBean接口,那么这个Bean的afterPropertiesSet实现也会
** 被调用
*/
invokeInitMethods(beanName, wrappedBean, mbd);
if (mbd == null || !mbd.isSynthetic()) {
// 执行BeanPostProcessor扩展点的PostProcessAfterInitialization进行修改实例化Bean
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
1. **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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
BeanNameAware:让Bean获取自己在BeanFactory配置中的名字(根据情况是id或者name)
Spring自动调用。并且会在Spring自身完成Bean配置之后,且在调用任何Bean生命周期回调(初始化或者销毁)方法之前就调用这个方法。换言之,在程序中使用BeanFactory.getBean(String beanName)之前,Bean的名字就已经设定好了。
BeanClassLoaderAware: 获取Bean的类装载器
-
BeanFactoryAware:让Bean获取配置他们的BeanFactory的引用
>
setBeanFactory方法是在根据某个配置文件创建了一个新工厂之后,Spring才调用这个方法,并把BeanFactory注入到Bean中。 让bean获取配置自己的工厂之后,可以在Bean中使用这个工厂的getBean()方法,但是,实际上非常不推荐这样做,因为结果是进一步加大Bean与Spring的耦合,而且,能通过DI注入进来的尽量通过DI来注入。
2. 后处理方法(初始化之前调用)
3. **自定义的init方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
// 实现了InitializingBean接口 && (mbd为null || mbd中的afterPropertiesSet方法不是外部方法)
((InitializingBean) bean).afterPropertiesSet();
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用自定义的初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
自定义初始化方法(在配置文件指定init-method)
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 获取初始化方法名称
String initMethodName = mbd.getInitMethodName();
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
// 若指示配置的init方法是是默认方法,且不存在,抛出异常找不到该方法
throw new BeanDefinitionValidationException(".....");
} else {
// 没有找到默认的名字叫initMethodName初始化的初始化方法
return;
}
}
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
}
4. 后处理方法(初始化之后调用)
推荐阅读
-
Spring基于xml文件配置Bean过程详解
-
spring源码分析系列5:ApplicationContext的初始化与Bean生命周期
-
spring源码分析6: ApplicationContext的初始化与BeanDefinition的搜集入库
-
Spring源码剖析2:Spring IOC容器的加载过程
-
spring5 源码深度解析-----ApplicationContext容器refresh过程
-
Spring MVC源码(一) ----- 启动过程与组件初始化
-
Spring源码分析之IoC容器初始化
-
SpringBoot 源码解析 (三)----- Spring Boot 精髓:启动时初始化数据
-
spring源码之bean解析
-
spring源码深度解析— IOC 之 开启 bean 的加载