(四)Spring关键接口之Springboot相关接口

本文深入解析Spring框架中的关键接口,包括ImportSelector、ImportBeanDefinitionRegistrar和EnvironmentPostProcessor,阐述了它们在Spring和Spring Boot中的作用及调用流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、注解相关接口

1.ImportSelector接口

2.ImportBeanDefinitionRegistrar接口

二、Springboot特殊接口

1.EnvironmentPostProcessor接口


本系列一共四篇,其它三篇传送门:

一、注解相关接口

1.ImportSelector接口

接口源码如下:

public interface ImportSelector {
   String[] selectImports(AnnotationMetadata importingClassMetadata);
}

接口说明:可以看到这个接口就一个方法selectImports(),并且返回的是String数组,根据其注解入口@Import都可以猜测出来,这个方法会在实现类中写需要被引入的类名称,接着这个方法便会返回引入的类,并且注册到Spring工厂中,实际上也确实如此。

调用方法链如下:

final class PostProcessorRegistrationDelegate {
    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> 
                    postProcessors, BeanDefinitionRegistry registry) {
       for (BeanDefinitionRegistryPostProcessor postProcessor : 
               postProcessors) {
          postProcessor.postProcessBeanDefinitionRegistry(registry);
       }
    }
}
public class ConfigurationClassPostProcessor 
        implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, 
        EnvironmentAware {
    @Override
    public void postProcessBeanDefinitionRegistry(
            BeanDefinitionRegistry registry) {
        ...
        processConfigBeanDefinitions(registry);
    }
    public void processConfigBeanDefinitions(
            BeanDefinitionRegistry registry) {
        ...
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, 
                this.environment, this.resourceLoader, 
                this.componentScanBeanNameGenerator, registry);
        parser.parse(candidates);
        ...
    }
}
class ConfigurationClassParser {
    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        ...
        if (bd instanceof AnnotatedBeanDefinition) {
           parse(((AnnotatedBeanDefinition) bd).getMetadata(), 
                   holder.getBeanName());
        }
        ...
    }
    protected final void parse(AnnotationMetadata metadata, 
            String beanName) throws IOException {
       processConfigurationClass(
               new ConfigurationClass(metadata, beanName));
    }
    protected void processConfigurationClass(
            ConfigurationClass configClass)  throws IOException {
        ...
        do {
           sourceClass = doProcessConfigurationClass(configClass, 
                   sourceClass);
        }
        while (sourceClass != null);
        ...
    }
    protected final SourceClass doProcessConfigurationClass(
            ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {
        ...
        processImports(configClass, sourceClass, getImports(sourceClass), 
                true);
        ...
    }
    private void processImports(ConfigurationClass configClass, 
            SourceClass currentSourceClass, 
            Collection<SourceClass> importCandidates, 
            boolean checkForCircularImports) {
        ...
        for (SourceClass candidate : importCandidates) {
            if (candidate.isAssignable(ImportSelector.class)) {
                if (selector instanceof DeferredImportSelector) {
                   this.deferredImportSelectorHandler
                           .handle(configClass, 
                                   (DeferredImportSelector) selector);
                }
                else {
                   // 调用ImportSelector接口的selectImports方法
                   // 获得该方法引入的类,并且会在该方法的其它地方被实例化
                   String[] importClassNames = selector
                           .selectImports(currentSourceClass.getMetadata());
                   Collection<SourceClass> importSourceClasses = 
                           asSourceClasses(importClassNames);
                   processImports(configClass, currentSourceClass, 
                           importSourceClasses, false);
                }
            } else if (candidate
                    .isAssignable(ImportBeanDefinitionRegistrar.class)) {
               Class<?> candidateClass = candidate.loadClass();
               // 在这里实例化
               ImportBeanDefinitionRegistrar registrar =
                       BeanUtils.instantiateClass(candidateClass, 
                       ImportBeanDefinitionRegistrar.class);
               // 调用BeanClassLoaderAware、BeanFactoryAware和
               // ResourceLoaderAware这些Aware接口
               ParserStrategyUtils.invokeAwareMethods(registrar, 
                       this.environment, this.resourceLoader, 
                       this.registry);
               // 在这里添加进集合importBeanDefinitionRegistrars中
               configClass.addImportBeanDefinitionRegistrar(registrar, 
                       currentSourceClass.getMetadata());
            }
        }
        ...
    }
}

2.ImportBeanDefinitionRegistrar接口

接口源码如下:

public interface ImportBeanDefinitionRegistrar {
   void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, 
           BeanDefinitionRegistry registry);
}

接口说明:该接口的主要作用便是将注解元数据AnnotationMetadata注册到Spring的注册中心registry里面,该接口在@Configuration和@Import注解运行Spring获得被引入和声明的bean之后将被调用,主要的作用便是搭配@Import和@Configuration进行额外的处理逻辑。

调用方法链如下:

public class ConfigurationClassPostProcessor 
        implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, 
        ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    @Nullable
    private ConfigurationClassBeanDefinitionReader reader;
    @Override
    public void postProcessBeanDefinitionRegistry(
            BeanDefinitionRegistry registry) {
        ...
        processConfigBeanDefinitions(registry);
    }
    @Override
    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) {
        ...
        if (!this.registriesPostProcessed.contains(factoryId)) {
           processConfigBeanDefinitions(
                   (BeanDefinitionRegistry) beanFactory);
        }
        ...
    }
    public void processConfigBeanDefinitions(
            BeanDefinitionRegistry registry) {
        ...
        if (this.reader == null) {
           this.reader = new ConfigurationClassBeanDefinitionReader(
                 registry, this.sourceExtractor, this.resourceLoader, 
                 this.environment, this.importBeanNameGenerator, 
                 parser.getImportRegistry());
        }
        this.reader.loadBeanDefinitions(configClasses);
        ...
    }
}
class ConfigurationClassBeanDefinitionReader {
    public void loadBeanDefinitions(
            Set<ConfigurationClass> configurationModel) {
       ...
       for (ConfigurationClass configClass : configurationModel) {
          loadBeanDefinitionsForConfigurationClass(configClass, 
                  trackedConditionEvaluator);
       }
    }
    private void loadBeanDefinitionsForConfigurationClass(
            ConfigurationClass configClass, 
            TrackedConditionEvaluator trackedConditionEvaluator) {
        ...
        loadBeanDefinitionsFromRegistrars(configClass
                .getImportBeanDefinitionRegistrars());
    }
    private void loadBeanDefinitionsFromRegistrars(
            Map<ImportBeanDefinitionRegistrar, 
            AnnotationMetadata> registrars) {
       registrars.forEach((registrar, metadata) ->
               registrar.registerBeanDefinitions(metadata, this.registry));
    }
}

二、Springboot特殊接口

1.EnvironmentPostProcessor接口

接口源码如下:

@FunctionalInterface
public interface EnvironmentPostProcessor {
   void postProcessEnvironment(ConfigurableEnvironment environment, 
           SpringApplication application);
}

接口说明:这个接口在Springboot里面仅在ConfigFileApplicationListener类执行监听事件ApplicationEnvironmentPreparedEvent时才会被触发调用,其主要作用便是对Spring程序上下文中的Environment在刷新前进行一系列的自定义操作,如Springboot官方便是使用这个接口读取properties文件和yml文件,随后将这些文件添加进environment对象中。

调用方法链如下:

public class SpringApplication {
    public SpringApplication(ResourceLoader resourceLoader, 
            Class<?>... primarySources) {
       this.resourceLoader = resourceLoader;
       Assert.notNull(primarySources, "PrimarySources must not be null");
       this.primarySources = new LinkedHashSet<>(
               Arrays.asList(primarySources));
       this.webApplicationType = WebApplicationType.deduceFromClasspath();
       setInitializers((Collection) getSpringFactoriesInstances(
               ApplicationContextInitializer.class));
       setListeners((Collection) getSpringFactoriesInstances(
               ApplicationListener.class));
       this.mainApplicationClass = deduceMainApplicationClass();
    }
    public SpringApplication(Class<?>... primarySources) {
       this(null, primarySources);
    }
    public static ConfigurableApplicationContext run(
            Class<?> primarySource, String... args) {
       return run(new Class<?>[] { primarySource }, args);
    }
    public static ConfigurableApplicationContext run(
            Class<?>[] primarySources, String[] args) {
       return new SpringApplication(primarySources).run(args);
    }
    public ConfigurableApplicationContext run(String... args) {
        ...
        ConfigurableEnvironment environment = 
                prepareEnvironment(listeners, applicationArguments);
        ...
    }
    private ConfigurableEnvironment prepareEnvironment(
            SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
        ...
        listeners.environmentPrepared(environment);
        ...
    }
}
class SpringApplicationRunListeners {
    public void environmentPrepared(ConfigurableEnvironment environment) {
       for (SpringApplicationRunListener listener : this.listeners) {
          listener.environmentPrepared(environment);
       }
    }
}
public class EventPublishingRunListener 
        implements SpringApplicationRunListener, Ordered {
    private final SimpleApplicationEventMulticaster initialMulticaster;
    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
       this.initialMulticaster
               .multicastEvent(
                       new ApplicationEnvironmentPreparedEvent(
                               this.application, this.args, environment));
    }
}
public class SimpleApplicationEventMulticaster 
        extends AbstractApplicationEventMulticaster {
    @Override
    public void multicastEvent(ApplicationEvent event) {
       multicastEvent(event, resolveDefaultEventType(event));
    }
    @Override
    public void multicastEvent(final ApplicationEvent event, 
            @Nullable ResolvableType eventType) {
       ...
       for (ApplicationListener<?> listener : 
               getApplicationListeners(event, type)) {
          if (executor != null) {
             executor.execute(() -> invokeListener(listener, event));
          }
          else {
             invokeListener(listener, event);
          }
       }
    }
    protected void invokeListener(ApplicationListener<?> listener, 
            ApplicationEvent event) {
        ...
        doInvokeListener(listener, event);
        ...
    }
    private void doInvokeListener(ApplicationListener listener, 
            ApplicationEvent event) {
        ...
        listener.onApplicationEvent(event);
        ...
    }
}
public class ConfigFileApplicationListener 
        implements EnvironmentPostProcessor, SmartApplicationListener, 
                Ordered {
    private static final String DEFAULT_SEARCH_LOCATIONS = 
            "classpath:/,classpath:/config/,file:./,file:./config/";
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            onApplicationEnvironmentPreparedEvent(
                    (ApplicationEnvironmentPreparedEvent) event);
        }
        ...
    }
    private void onApplicationEnvironmentPreparedEvent(
            ApplicationEnvironmentPreparedEvent event) {
       List<EnvironmentPostProcessor> postProcessors = 
               loadPostProcessors();
       postProcessors.add(this);
       AnnotationAwareOrderComparator.sort(postProcessors);
       for (EnvironmentPostProcessor postProcessor : postProcessors) {
          postProcessor.postProcessEnvironment(event.getEnvironment(), 
                  event.getSpringApplication());
       }
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值