Spring Boot 中 @EnableX 注解的驱动逻辑

作者 | 温安适
来源 |
工作中经常用到 , 如下注解:

  • @EnableEurekaClient
  • @EnableFeignClients
  • @EnableCircuitBreaker
  • @EnableHystrix
他们都是@Enable开头 , 各自实现不同的功能 , 解析这种@Enable的逻辑是什么呢?
@Enable驱动逻辑找入口@Enable的模块驱动 , 依赖于@Import实现 。
@Import作用是装载导入类 , 主要包括@Configuration class,ImportSelector实现类,ImportBeanDefinitionRegistrar实现类 。
XML时代 , 经常是@Import,,一起使用 。
(注解配置)中大概率有我们需要找的逻辑 。
根据 Spring Framework 2.0引入的可扩展的XML编程机制 , XML Schema命名空间需要与Handler建立映射关系 。
该关系配置在相对于classpath下的/META-INF/spring.handlers中 。
查看ContextNamespaceHandler 源码
public class ContextNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {//省略其他代码registerBeanDefinitionParser("annotation-config",new AnnotationConfigBeanDefinitionParser());}}复制代码** 对应AnnotationConfigBeanDefinitionParser这个就是要找的入口**
找核心类从AnnotationConfigBeanDefinitionParser的parse方法开始一路向下 , 找到
AnnotationConfigUtils.registerAnnotationConfigProcessors中注册了ConfigurationClassPostProcessor 。
Spring Boot 中 @EnableX 注解的驱动逻辑文章插图
img
ConfigurationClassPostProcessor类注释说明
\1. 用于的引导处理@Configuration类
\2. context:annotation-config/或 context:component-scan/时会注册
否则需要手工编程
\3. ConfigurationClassPostProcessor第一优先级 , 保证
@Configuration}类中声明@Bean , 在其他 BeanFactoryPostProcessor执行之前被注册
扩展
AnnotationConfigApplicationContext中new AnnotationBeanDefinitionreader也调用了 AnnotationConfigUtils .
registerAnnotationConfigProcessors
从类注释中 , 可以看出ConfigurationClassPostProcessor就是要找的核心类
找核心方法
查看 ConfigurationClassPostProcessor 的层级关系为
Spring Boot 中 @EnableX 注解的驱动逻辑文章插图
img
Aware系列注入相应资源 , Ordered设置优先级 , 值得关注的就是
postProcessBeanDefinitionRegistry了 。
postProcessBeanDefinitionRegistry其内部有2个方法
  1. postProcessBeanDefinitionRegistry在BeanDefinition注册之后 , BeanFactoryPostProcessor执行之前 , 修改或重写BeanDefinition
  2. 继承自BeanFactoryPostProcessor的postProcessBeanFactory , BeanDefinition加载之后 , Bean实例化之前 , 重写或添加BeanDefinition , 修改BeanFactory
浏览2个方法 , 都有processConfigBeanDefinitions , 从名称可以看出是处理配置类Bean定义
Spring Boot 中 @EnableX 注解的驱动逻辑文章插图
img
ConfigurationClassPostProcessor#processConfigBeanDefinitions就是要找的核心方法
梳理流程public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List configCandidates = new ArrayList<>();String[] candidateNames = registry.getBeanDefinitionNames();for (String beanName : candidateNames) {BeanDefinition beanDef = registry.getBeanDefinition(beanName);if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}// 没有找到 @Configuration classes 立即返回if (configCandidates.isEmpty()) {return;}//根据@Order 值进行排序configCandidates.sort((bd1, bd2) -> {int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());return Integer.compare(i1, i2);});//通过封闭的应用程序上下文 ,检测任何自定义bean名称生成策略supplied through the enclosing application contextSingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;if (!this.localBeanNameGeneratorSet) {BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {this.componentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}}if (this.environment == null) {this.environment = new StandardEnvironment();}// 解析@Configuration classConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);Set candidates = new LinkedHashSet