为什么启动类被【@SpringBootApplication】注解后,就会⾃动
扫描其包内所。。。
1、因为【@SpringBootApplication】⼜被【@ComponentScan】注解。
2、注解【@ComponentScan】有⼀个属性【useDefaultFilters】,并且默认值为【true】。
3、Spring初始化时会将启动类加⼊上下⽂的【BeanFactory】中,然后进⾏后置处理器的处理。
4、后置处理器中有⼀个默认的配置类后置处理器。
5、在配置类后置处理器中,有⼀个能否加⼊候选配置类集合的判断,判断依据为该类是否被【@Configuration】注解。
6、在判定为配置类并加⼊候选集合后,会挨个执⾏⽅法【parse】和【doProcessConfigurationClass】进⾏处理。此时会通过配置类的元数据中获取所有的【ComponentScan】注解,然后针对每个【ComponentScan】注解,通过扫描解析器【componentScanParser】进⾏扫描并获取所有符合条件的【BeanDefinitionHolder】。
7、在对每个【ComponentScan】注解执⾏扫描解析时,会先建⽴⼀个Bean定义扫描器【ClassPathBeanDefinitionScanner】。此时就会询问该【ComponentScan】注解的【useDefaultFilters】属性值了。
8、当【useDefaultFilters】的属性值为真时,该会对该扫描器注册默认的过滤器。
9、该注册过程的第⼀步就是对其【包含过滤器集合】---【includeFilters】增加对【@Component】注解的过滤。
10、在后续对每个【ClassPath】下到的类⽂件进⾏过滤时,所有被【@Component】注解过的类就会成为候选项。所以虽然是⾃动完成的,但最终还是通过Spring的扫描过滤器实现的。
11、所有被扫描出的类定义中,如果还有被【@Configuration】注解过的配置类,则对其递归调⽤【parse】⽅法,继续重复这个过程。
配置类中被【@Bean】注解的【method】是通过后续的【retrieveBeanMethodMetadata】⽅法获取,并放⼊其【beanMethods】属性中。
12、通过遍历包路径下的类⽂件得到的配置类定义是如何加⼊到【BeanFactory】的呢?
我们在对被【@Configuration】注解的启动类作为候选项进⾏解析的时候,会先创建⼀个解析器,该解析器会包含对Spring上下⽂的信息,同时也包括实现了接⼝【BeanDefinitionRegistry】的【BeanFactory】的引⽤。
这样在扫描完成后,通过接⼝【BeanDefinitionRegistry】的⽅法【registerBeanDefinition】将获取到的候选【@Componet】Bean注册到Spring上下⽂的【BeanFactory】中。
13、配置类中被【@Bean】注解的⽅法是如何加⼊到【BeanFactory】中Bean定义集合的呢?
前⾯提到过在解析候选配置类时,除了将到的被【@Component】注解的类定义加⼊【BeanFactory】中外,还通过⽅法【retrieveBeanMethodMetadata】,将配置类中被【@Bean】注解的⽅法收集到配置类【ConfigurationClass】的属性【beanMethods】中。
在解析完配置类⾃⾝后,⼜建⽴了⼀个Bean定义读取器【ConfigurationClassBeanDefinitionReader】来对解析后⽣成的配置类进⾏处理,从⽽获取其通过⽅法定义的Bean定义。
该Bean定义读取器和类⽂件解析器【ConfigurationClassParser】⼀样,建⽴时同样拥有对Spring上下⽂及实现了实现了【BeanDefinitionRegistry】接⼝的【BeanFactory】的引⽤。
在处理过程中通过配置类对象的【getBeanMethods】⽅法,获取被【@Bean】注解的⽅法,然后调springboot其实就是spring
⽤⽅法【loadBeanDefinitionsForBeanMethod】进⾏解析、构建和注册。
在将⽅法转换为Bean定义【BeanDefinition】后,然后执⾏接⼝【BeanDefinitionRegistry】的⽅法【registerBeanDefinition】,将其注⼊到【BeanFactory】的Bean定义集合中。
14、总体过程就是,Spring启动后先根据配置⽂件构建上下⽂运⾏环境,然后以启动类为起点扫描其包下的所有配置类,再扫描其它配置类,并形成【BeanDefinition】注册到【BeanFactory】中。然后遍历所有注册的配置类定义,将其在扫描过程中收集到的【@Bean】⽅法,转换为【BeanDefinition】并注册到【BeanFactory】。
后续应该就是对所有的【BeanDefinition】,根据其顺序、依赖关系、优先级等属性,进⾏实例化并注册到【BeanFactory】中,这部分的实现过程并没有再深⼊跟踪。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论