[Java]从spring(spring boot)的启动分析注解定义方式的bean的加载

7 篇文章 0 订阅
4 篇文章 0 订阅

spring boot启动的时候会创建一个注解配置嵌入式web应用上下文AnnotationConfigEmbeddedWebApplicationContext,在实例化这个ApplicationContext时,首先会先实例化它的父类GenericApplicationContext(在父类的构造方法中初始化一个BeanFactory),然后回到子类的构造方法中初始化注解bean定义阅读器AnnotatedBeanDefinitionReader和类路径bean定义扫描器ClassPathBeanDefinitionScanner.

在生成阅读器对象Reader的时候会把所有与注解配置相关的后处理器Processor注册到IOC容器当中 [重点1],在这之前还会初始化AnnotationAwareOrderComparator(处理@Order@Priority注解,还有Ordered接口)和ContextAnnotationAutowireCandidateResolver(处理懒加载注解@Lazy).

类路径bean定义扫描器通过includeFilters判断需要扫描的情况和通过excludeFilter判断不扫描的情况(两者都是链表LinkedList).而在构造函数中(刚创建)只会会注册对@Component@ManagedBean注解的扫描.最后会设置资源加载器ResourceLoader

接着在BeanDefinitionLoader(会新建它自己的多个阅读器和扫描器,外观模式)的load()方法中会开始一次对bean定义的加载().它定义的扫描器不扫描用户定义的spring boot启动类,但它却只注册用户定义的spring boot启动类.

值得注意的是扫描到的Bean的注解解析,是在注册bean的时候发生的.还有spring中的元数据`Metadata`一般指的是注解`Annotation

上面的结束后,接下来就进入熟悉的spring初始化方法refresh()中了

因为spring boot使用的是通用应用上下文GenericApplicationContext不像AbstractRefreshableApplicationContext,所以它的bean工厂的创建和bean定义的加载不在refreshBeanFactory()方法完成,而是在通用应用上下文的构造方法里创建.

prepareBeanFactory()方法仍然是配置应用上下文感知后处理器ApplicationContextAwareProcessor(重要)和其他一些东西.

这里也有一个要注意的,那就是bean工厂后处理器`BeanFactoryPostProcessor`和bean处理器`BeanPostProcessor`的区别:


前者是`AbstractApplicationContext`附加的,它本质也是个bean.后者是`AbstractBeanFactory`所持有的(在实例化bean是会回调所有的Bean后处理器)

invokeBeanFactoryPostProcessors()中会执行之前注册的后处理器.首先他会调用所有处理器的postProcessBeanDefinitionRegistry()方法先把所有bean注册好,接着再调用其他处理方法.下面主要说一下几个重要的处理器.

ConfigurationClassPostProcessor

配置类处理器用于处理@Configuration注解,而在它的postProcessBeanDefinitionRegistry()方法首先处理的是用户定义的spring boot启动类(上面说过它的加载,@SpringBootApplication继承了@Configuration),在这里首先会用配置类解析器ConfigurationClassParser解析目前唯一一个配置类(通常是webApplication).

在解析的过程中,因为@SpringBootApplication同时继承@ComponentScan注解,所以会触发ComponentScanParser以用户定义的spring boot启动类所在包为basePackage进行扫描并注册 注解配置方式的bean (如spring MVC那些注解配置的类).然后判断加载的bean是否是配置类@Configuration,是则递归调用parse方法解析 [重点2].

当然parse()方法还会解析很多其他注解,如@Import,@ImportResource,@Bean,@PropertySource等.注意@Bean注解修饰的方法配置的bean定义不是在这里生成的,也不会在这里注册到IOC容器,这里只是做一些配置上的初始化(解析parse()方法结束后通过ConfigurationClassBeanDefinitionReader加载).

最后parse()就是调用processDeferredImportSelectors()对spring boot的自动配置进行加载了,和上面一样,最终调用processConfigurationClass()解析配置类.但import导入的自动配置的bean注册会在另外的地方进行(解析parse()方法结束后通过ConfigurationClassBeanDefinitionReader加载).

用户定义的第三方BeanDefinitionRegistryPostProcessor

运行完spring内置的bean定义注册后处理器后,spring还会循环运行第三方的实现BeanDefinitionRegistryPostProcessor接口的处理器(如mybatis的MapperScannerConfigurer),直到没有新的bean定义注册后处理器出现才会停止.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值