SpringBoot IoC(6)总结

504 阅读2分钟

说明:

SpringIoC的源代码很深,其最精华的部分位于AbstractApplicationContext->refresh()方法中,当然即使是这样,这里也只分析了其精华中的精华

第一步 createApplicationContext():初始化IoC容器

AnnotationConfigServletWebServerApplicationContext.png 在DefaultResourceLoader中会初始化以下三个属性:

// 类加载器Launcher$AppClassLoader
private ClassLoader classLoader;
// 协议解析器容器
private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);
// 配置文件缓存器
private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);

在AbstractApplicationContext类中主要初始化:

// 确定日志类型,比如log4j,logback
protected final Log logger = LogFactory.getLog(getClass());
// 创建beanFactory后置处理器
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
// 创建事件监听器容器
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
/*resourceLoader:AnnotationConfigApplicationContext
* pathMatcher: AntPathMatcher ant风格的解析器 
*/
private ResourcePatternResolver resourcePatternResolver;

在GenericApplicationContext中创建Spring IoC最重要的对象beanFactory。

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

最后才会调用AnnotationConfigServletWebServerApplicationContext()的构造函数完成Spring容器的创建和初始化工作。

public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

在执行reader变量初始化的时候,会添加5个beanDefinitionMap,如下:

// 配置类处理器,也是第一次找bean所用到的后置处理器
1.org.springframework.context.annotation.internalConfigurationAnnotationProcessor
// 自动注入类处理器
2.org.springframework.context.annotation.internalAutowiredAnnotationProcessor
// 通用注解类处理器
3.org.springframework.context.annotation.internalCommonAnnotationProcessor
4.org.springframework.context.event.internalEventListenerProcessor
5.org.springframework.context.event.internalEventListenerFactory

第二步 load(context, sources.toArray(new Object[0])):注册启动类bd

解析启动类,并将主源添加至beanDefinitionMap,如果有多个则按照顺序添加

第三步 刷新容器

第一步 prepareRefresh():初始化容器

第二步 obtainFreshBeanFactory():获得IOC容器

第三步 容器准备

prepareBeanFactory(beanFactory):准备化工作,添加两个beanPostProcessors,注册默认的环境bean。

postProcessBeanFactory(beanFactory):作用域新增requestsession

第四步 invokeBeanFactoryPostProcessors(beanFactory)

  1. 找到当前IoC容器中实现BeanDefinitionRegistryPostProcessor的后置处理器并实例化,调用各后置处理器的postProcessBeanDefinitionRegistry(registry)方法,找bean,添加到bdMap和bdNames中参考1 参考2
  2. 再一次查找当前IoC容器中实现BeanDefinitionRegistryPostProcessor的后置处理器并实例化,未调用过的调用各后置处理器的postProcessBeanDefinitionRegistry(registry)方法,找bean,添加到bdMap和bdNames中
  3. 调用各后置处理器的postProcessBeanFactory(beanFactory)方法,其中ConfigurationClassPostProcessor对@Configuration做Cglib增强
  4. 找到当前IoC容器中实现BeanFactoryPostProcessor的后置处理器并实例化,未调用过的调用各后置处理器的postProcessBeanFactory(beanFactory)方法

第五步 registerBeanPostProcessors(beanFactory):注册后置处理器

查找当前IoC容器中实现BeanPostProcessor的后置处理器,确保都添加到beanPostProcessors集合中,并且都实例化,确保beanPostProcessors有BeanPostProcessorChecker和ApplicationListenerDetector这两个后置处理器。后面实例化用到的后置处理器就是这些了。

不同的后置处理器有不同的作用,举最常见的几个后置处理器说明:

ApplicationListenerDetector(有用到,已见过)

  与监听器有关,通过postProcessAfterInitialization方法,当前bean如果实现了ApplicationListener接口,放入应用上下文的的applicationListeners和applicationEventMulticaster中,如定时任务后置处理器ScheduledAnnotationBeanPostProcessor。

AutowiredAnnotationBeanPostProcessor(有用到,已见过)

  是Spring实现依赖注入和依赖查找的核心技术。它在bean实例化过程中,通过findAutowiredAnnotation方法寻找beanClass中是否有@Autowird, @Value注解。上述注解的依赖注入就是通过这个后置处理器实现的。

CommonAnnotationBeanPostProcessor(有用到,已见过)

  Spring的通用注解后置处理器,专门用来处理@PostConstruct,@PreDestroy, @Resource。上述注解的依赖注入和方法的执行就是通过这个后置处理器实现的。

AnnotationAwareAspectJAutoProxyCreator(有用到,已见过)

  与AoP的实现有关。

ConfigurationPropertiesBindingPostProcessor(有用到,已见过)

  用于解析@ConfigurationProperties注解,并将配置文件中的内容绑定到对应的bean的对象上。

大致过程为

  1. 取Bean的所有字段,遍历,这时会将字段名由驼峰改为中划线,如testAge变成test-age
  2. 遍历属性源,找到名称为test-age的属性值
  3. 如果没有的话,遍历属性源中的所有key,依次与test-age比较,相似则取其属性值(无视大小写与特殊字符,如testAge、TEST_AGE都认为相似)
  4. 找到的话利用反射赋值,否则跳过

@ConfigurationProperties与@Value最大的区别是前者没有对应属性跳过,后者没有对应属性直接报错

PostProcessorRegistrationDelegate$BeanPostProcessorChecker

  BeanPostProcessorChecker是PostProcessorRegistrationDelegate的内部类。BeanPostProcessorChecker的官方注释如下:当bean在BeanPostProcessor实例化期间创建时,即当bean不符合所有BeanPostProcessor处理的条件时,记录信息消息的BeanPostProcessor。值得说明的是,它只针对于Spring不对外公开的“基础设施”类提供检查。(bd. role=ROLE_INFRASTRUCTURE)。

ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

  用于BeanFactoryAware接口的bean的增强处理。

ApplicationContextAwareProcessor(有用到,已见过)

  ApplicationContextAwareProcessor负责EnvironmentAware、ResourceLoaderAware、ApplicationContextAware等的注入,当beanClass实现ApplicationContextAware接口的时候,会执行setApplicationContext方法;当beanClass实现EnvironmentAware接口的时候,会执行setEnvironment方法。

  很典型的一个是当beanName为dispatcherServlet时,会将应用上下文的环境赋给它的environment成员变量,将应用上下文赋给它的webApplicationContext变量。

  通过实现aware接口的形式得到应用上下文,然后得到指定的bean就是利用这个后置处理器实现的。

第六步 实例化前准备

initMessageSource():初始化上下文中的消息源

initApplicationEventMulticaster():初始化上下文中的监听器管理对象。如果IoC容器有名称为applicationEventMulticaster的bean,直接用它;否则实例化SimpleApplicationEventMulticaster对象,取上述名称,并注入到IoC容器中

onRefresh():创建web服务器、启动、Servlet类、过滤器,详细见Tomcat的实例化与启动

registerListeners():将上下文中的监听器转给它的成员变量applicationEventMulticaster的成员变量defaultRetriever的applicationListeners中

第七步 finishBeanFactoryInitialization(beanFactory)

实例化bean,这里实际实例化的是非后置处理器,且为单例、非懒加载的bean

具体实例化的的流程见此

第八步 finishRefresh()

生命周期处理器、发布相应的的事件、web服务开启监听

详情可见Tomcat的监听与销毁中的相关部分

至此,IoC阶段完成