当前位置: 首页 > news >正文

Spring IOC - Bean的初始化

        在bean的初始化阶段,bean已经被实例化及属性填充了,此时的bean已相对成熟,接下来的初始化阶段还会做一些额外的工作对bean做进一步处理,主要包括以下四个方面:

  1. 调用aware接口方法

  2. 初始化前:调用初始化前的后置处理器方法

  3. 初始化:调用InitializingBean接口的afterPropertiesSet方法

  4. 初始化后:调用初始化后的后置处理器方法

1. Bean初始化主流程

        AbstractAutowireCapableBeanFactory#initializeBean

        运用aware回调接口、afterPropertiesSet方法、后置处理器完成bean实例的初始化

// 运用aware回调接口、afterPropertiesSet方法、后置处理器完成bean实例的初始化
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 {// 1.调用aware接口的方法invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {// 2.调用初始化前后置处理器wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {// 3.调用初始化方法,其实就是afterPropertiesSet方法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;
}

2. Aware接口调用

        如果Bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,则会调用相应接口的方法。

  • BeanNameAware:在Bean实例化后进行扩展操作,可以获取Bean的名称
  • BeanClassLoaderAware:在Bean实例化后进行扩展操作,可以获取Bean的类加载器
  • BeanFactoryAware:在Bean实例化后进行扩展操作,可以获取Bean所属的BeanFactory
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);}}
}

3. 初始化前:调用初始化前的后置处理器方法

        这里涉及到了Bean后置处理器:BeanPostProcessor,其作用如下:

  1. spring会自动从它的所有的bean定义中检测BeanPostProcessor类型的bean定义,然后实例化它们,再将它们应用于随后创建的每一个bean实例

  2. 在bean实例的初始化方法回调之前调用BeanPostProcessor的postProcessBeforeInitialization的方法

  3. 在bean实例的初始化方法回调之后调用BeanPostProcessor的postProcessAfterInitialization的方法

  4. 通常,通过标记接口等方式填充bean的后置处理器会实现postProcessBeforeInitialization方法,而将bean包装为代理的后置处理器会实现postProcessAfterInitialization方法

public interface BeanPostProcessor {@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}
@Override
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;
}

        例如ApplicationContextAwareProcessor后置处理器,其重写了postProcessBeforeInitialization方法,如果bean实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware接口,则会调用响应接口的方法

  • EnvironmentAware:在Bean实例化后进行扩展操作,可以获取Environment实例
  • EmbeddedValueResolverAware:在Bean实例化后进行扩展操作,可以获取StringValueResolver实例,可用于解析占位符
  • ResourceLoaderAware:在Bean实例化后进行扩展操作,可以获取ResourceLoader实例
  • ApplicationEventPublisherAware:在Bean实例化后进行扩展操作,可以获取ApplicationEventPublisher实例
  • MessageSourceAware:在Bean实例化后进行扩展操作,可以获取MessageSource实例
  • ApplicationContextAware:在Bean实例化后进行扩展操作,可以获取ApplicationContext实例

4. 初始化:调用InitializingBean接口的afterPropertiesSet方法或自定义的init方法

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {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>) () -> {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {// 调用afterPropertiesSet方法((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)) {// 调用自定义的init方法invokeCustomInitMethod(beanName, bean, mbd);}}
}

5. 初始化后:调用初始化后的后置处理器方法

@Override
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;
}
http://www.lryc.cn/news/68947.html

相关文章:

  • Golang 安装
  • ( 位运算 ) 338. 比特位计数 ——【Leetcode每日一题】
  • Unity之新版输入系统InputSystem入门
  • python 之 logging的使用
  • gunicorn常用参数命令
  • TimerResolution.exe
  • Qt魔法书:打造自定义鼠标键盘脚本
  • 〖Python网络爬虫实战㉖〗- Selenium库和ChromeDriver驱动的安装
  • U8产成品入库API接口 --参照生产订单/产品检验/不良品
  • gdb打印的堆栈有些函数是??()是什么
  • 【Jmeter第三章】Jmeter给请求添加请求头
  • WebApi必须知道的RestFul,Swagger,OAuth2.0
  • 【网络编程】demo版UDP网络服务器实现
  • C++的stack和queue
  • C++ RAII机制
  • AI模型部署概述
  • 【Rust 日报】2023-05-17 pgx -- 用于在 Rust 中开发 PostgreSQL 扩展的框架
  • 二十、Zipkin持久化链路跟踪
  • 大学毕业设计这样做可以吗
  • NSUserDefaults
  • Windows下通过cwRsync备份到服务器服务器之间使用rsync备份传输
  • IS420UCSBH4A 用于高速应用中的Mark VIe系列
  • 将JSON写入文件
  • effective c++ 35 考虑virtual函数以外的其他选择
  • Akura Medica:新型静脉血栓切除系统,完成首次人体试验
  • 大型央企集团财务经营分析框架系列(三)
  • C++并发编程:std::future、std::async、std::packaged_task与std::promise的深度探索
  • 测牛学堂:2023软件测试学习教程之sql的单表查询排序和模糊查询
  • CSS第一天总结
  • js中各种console使用方法大全