目录
2.ImportBeanDefinitionRegistrar接口
本系列一共四篇,其它三篇传送门:
一、注解相关接口
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());
}
}
}