springboot源码解析

springboot源码解析

md文档
mybatis源码
spring-IOC源码
spring-aop源码
spring-mvc源码(外加一点springboot 一次请求的原理分析)
spring-mybatis整合
springboot源码
springBoot2.7.8版本

一、启动源码

@SpringBootApplication
public class SampleWebUiApplication {
	public static void main(String[] args) {
		SpringApplication.run(SampleWebUiApplication.class, args);
	}
}

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    //1、创建SpringApplication对象
    //2、调用run方法
    return run(new Class<?>[] { primarySource }, args);
}

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
}

- 1、创建SpringApplication

public SpringApplication(Class<?>... primarySources) {
    //primarySources - > main方法所在的类
    this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    //null
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    //main方法所在的入口类放入到一个set集合中
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //判断应用类型:java web ..
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //bootstrappers:初始启动引导器
    this.bootstrapRegistryInitializers = new ArrayList<>(
        			getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
     //设置spring容器的ApplicationContextInitializer初始化器
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //设置spring容器的监听器ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //推断出main方法的类,赋值给成员变量
    this.mainApplicationClass = deduceMainApplicationClass();
}

* 判断应用类型

//ClassUtils.isPresent() 方法是用来判断一个类的存在性的
static WebApplicationType deduceFromClasspath() {
    if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
        && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
        //响应式编程
        return WebApplicationType.REACTIVE;
    }
    for (String className : SERVLET_INDICATOR_CLASSES) {
        if (!ClassUtils.isPresent(className, null)) {
            //不应作为 web 应
            return WebApplicationType.NONE;
        }
    }
    //web应用
    return WebApplicationType.SERVLET;
}

* getSpringFactoriesInstances

()从spring.factories文件中获取

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = getClassLoader();
    //SpringFactoriesLoader.loadFactoryNames 从spring.factories文件中获取类型为type的类
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //实例化对象
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

* SpringFactoriesLoader.loadFactoryNames 从spring.factories文件中获取类型为type的类

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    //类加载器
    ClassLoader classLoaderToUse = classLoader;
    if (classLoaderToUse == null) {
        classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
    }
    //获取类名称
    String factoryTypeName = factoryType.getName();
    //获取spring.factories中的配置类
    return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
    //从缓存中获取
    Map<String, List<String>> result = cache.get(classLoader);
    if (result != null) {
        return result;
    }

    result = new HashMap<>();
    try {
        // 获取所有spring.factories的URL FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"
        Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
        // 遍历URL
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            UrlResource resource = new UrlResource(url);
            // 将每个spring.factories 文件中内容包装成 properties 对象
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            // 遍历每个配置
            for (Map.Entry<?, ?> entry : properties.entrySet()) {
                 //提取 properties 对象中的 key 值
                String factoryTypeName = ((String) entry.getKey()).trim();
                String[] factoryImplementationNames =
                    StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
                 //遍历配置类数组,并将数组转换为 list 集合
                for (String factoryImplementationName : factoryImplementationNames) {
                    // 逐个添加到接口对应的集合当中
                    result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
                        .add(factoryImplementationName.trim());
                }
            }
        }
        // Replace all lists with unmodifiable lists containing unique elements
        //将 propertise 对象的 key 与由配置类组成的 List 集合一一对应存入名为 result 的 Map 中
        result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
                          .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
        cache.put(classLoader, result);
    }
   
    return result;
}

* bootstrappers:初始启动引导器

在这里插入图片描述

* ApplicationContextInitializer初始化器

在这里插入图片描述

* 监听器ApplicationListener

在这里插入图片描述

* 推断出main方法的类,赋值给成员变量

private Class<?> deduceMainApplicationClass() {
    try {
        //获取堆栈信息
        StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            if ("main".equals(stackTraceElement.getMethodName())) {
                return Class.forName(stackTraceElement.getClassName());
            }
        }
    }
    catch (ClassNotFoundException ex) {
        // Swallow and continue
    }
    return null;
}

- 2、run方法

public ConfigurableApplicationContext run(String... args) {
    //启动时间
    long startTime = System.nanoTime();
    //创建引导上下文    获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    //设置系统属性
    configureHeadlessProperty();
    //获取所有的运行监听器
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {// 保存命令行参数;对args再次封装 ApplicationArguments
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //环境信息
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        //配置忽略Bean信息
        configureIgnoreBeanInfo(environment);
        //打印Banner
        Banner printedBanner = printBanner(environment);
        //根据项目类型创建IOC容器
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        //准备IOC上下文环境信息
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        //刷新IOC容器
        refreshContext(context);
        //容器刷新完成后
        afterRefresh(context, applicationArguments);
        //启动完成后的时间
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
        }
        //执行ApplicationRunListeners中的started()方法
        listeners.started(context, timeTakenToStartup);
        //执行Runner(ApplicationRunner和CommandLineRunner)
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

-1- 创建引导上下文(Context环境)

private DefaultBootstrapContext createBootstrapContext() {
    DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
    //创建SpringApplication放入
    this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
    return bootstrapContext;
}

-2- 进入headless模式

private void configureHeadlessProperty() {
    System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
                       System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

-3- 获取所有的运行监听器 调用 starting 方法

通知所有感兴趣系统正在启动过程中的人,项目正在启动Listeners

	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
                //从spring.factories中获取                      
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
				this.applicationStartup);
	}
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners,
                              ApplicationStartup applicationStartup) {
    this.log = log;
    this.listeners = new ArrayList<>(listeners);
    this.applicationStartup = applicationStartup;
}

void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
    doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
                    (step) -> {
                        if (mainApplicationClass != null) {
                            step.tag("mainApplicationClass", mainApplicationClass.getName());
                        }
                    });
}

-4- 保存命令行参数;对args再次封装

public DefaultApplicationArguments(String... args) {
    Assert.notNull(args, "Args must not be null");
    this.source = new Source(args);
    this.args = args;
}

-5- 准备环境信息

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
         DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // Create and configure the environment
    //返回或者创建一个基础环境信息
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    //配置环境信息(读取所有的配置源配置属性值)
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    //绑定
    ConfigurationPropertySources.attach(environment);
    //通知所有监听器当前环江已经准备完成
    listeners.environmentPrepared(bootstrapContext, environment);
    DefaultPropertiesPropertySource.moveToEnd(environment);
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
                 "Environment prefix cannot be set via properties.");
    
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
        environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

-6- 创建spring ioc上下文,根据项目类型创建上下文

private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
ApplicationContextFactory DEFAULT = new DefaultApplicationContextFactory();
protected ConfigurableApplicationContext createApplicationContext() {
    //webApplicationType = 当前是什么项目(创建springApplication时判断)
    return this.applicationContextFactory.create(this.webApplicationType);
}
/**
 * AnnotationConfigApplicationContext::new ==  () -> new AnnotationConfigApplicationContext()
 * new BiFunction<ApplicationContextFactory, WebApplicationType, ConfigurableApplicationContext>() {
 *						@Override
 *						public ConfigurableApplicationContext apply(ApplicationContextFactory applicationContextFactory, 	
 *													WebApplicationType webApplicationType) {
 *							return  applicationContextFactory.create(webApplicationType);
 *						}
 *					},
 *  (applicationContextFactory,Type) -> applicationContextFactory.create(Type),
 */
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
    try {
        return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
                                      AnnotationConfigApplicationContext::new);
    }
    catch (Exception ex) {
        throw new IllegalStateException("Unable create a default ApplicationContext instance, "
                                        + "you may need a custom ApplicationContextFactory", ex);
    }
}
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
              BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
    //获取所有的类加载器 进行遍历 
    //action.apply 会调用ApplicationContextFactory的create方法根据
    //webApplicationType进行判断当前需要创建的IOC容器类型
    for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
                                                                                   getClass().getClassLoader())) {
        T result = action.apply(candidate, webApplicationType);
        if (result != null) {
            return result;
        }
    }
    return (defaultResult != null) ? defaultResult.get() : null;
}
//web : servlet类型:
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
    return (webApplicationType != WebApplicationType.SERVLET) ? null
        //与spring IOC创建一样 会创建BeanFactory 与 五个bean定义
        : new AnnotationConfigServletWebServerApplicationContext();
}

-7- 插口:准备IOC容器基本信息

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
                            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
                            ApplicationArguments applicationArguments, Banner printedBanner) {
    //给IOC容器设置环境
    context.setEnvironment(environment);
    // IOC容器的后置处理流程。(给IOC入一些组件类型转化器在这里放入ConversionService)
    postProcessApplicationContext(context);
    //应用初始化器
    applyInitializers(context);
    //遍历所有的 listener 调用 contextPrepared。
    listeners.contextPrepared(context);
    bootstrapContext.close(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
        ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
    }
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    //通知所有的监听器 contextLoaded
    listeners.contextLoaded(context);
}
//TODO 插口 : 可以使用此方法给IOC放入一些postProcessor等。。 应用初始化器
protected void applyInitializers(ConfigurableApplicationContext context) {
    //new SpringApplication时候放入的初始化器,
    for (ApplicationContextInitializer initializer : getInitializers()) {
        Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
                                                                        ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        //调用所有的初始化器的initialize方法
        initializer.initialize(context);
    }
}

-8- 刷新容器(spring 12步骤 ,会调用自动装配)

-9- 插口: 执行CommandLineRunner/ApplicationRunner Runner

可以用来做定时任务,在项目启动时调用

(ApplicationRunnerCommandLineRunner

  • 获取容器中的 ApplicationRunner
  • 获取容器中的 CommandLineRunner
  • 合并所有runner并且按照@Order进行排序
  • 遍历所有的runner。调用 run 方法
private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<>();
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    for (Object runner : new LinkedHashSet<>(runners)) {
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        if (runner instanceof CommandLineRunner) {
            callRunner((CommandLineRunner) runner, args);
        }
    }
}

private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    try {
        (runner).run(args);
    }
    catch (Exception ex) {
        throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
    }
}

private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
    try {
        (runner).run(args.getSourceArgs());
    }
    catch (Exception ex) {
        throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
    }
}

-3 、定时任务程序启动调用一次

@Component
@EnableScheduling
@RestController
@Slf4j
@Order
public class Scheduling implements SchedulingConfigurer, CommandLineRunner {

    private final AnalysisService analysisService;
    private final ScoreService scoreService;
    private final AlarmLevelService alarmLevelService;
    @Value("${tasksBool}")
    private boolean tasksBool;

    public Scheduling(AnalysisService analysisService, ScoreService scoreService, AlarmLevelService alarmLevelService) {
        this.analysisService = analysisService;
        this.scoreService = scoreService;
        this.alarmLevelService = alarmLevelService;
    }

    @Override
    public void run(String... args) throws Exception {
        alarmLevelService.initAlarmLevel();
        ScoreConstants.initScoreConstants(scoreService.select(new ScoreDetails()));

    }

    @Override
    public void configureTasks(@Nonnull ScheduledTaskRegistrar taskRegistrar) {
        if (!tasksBool) {
            taskRegistrar.addTriggerTask(analysisService::analysisEntrance, new PeriodicTrigger(30, TimeUnit.MINUTES));
        }

        taskRegistrar.addTriggerTask(scoreService::initScoreByArea, new PeriodicTrigger(30, TimeUnit.SECONDS));
        taskRegistrar.addTriggerTask(scoreService::pushScore, new PeriodicTrigger(30, TimeUnit.SECONDS));
        taskRegistrar.addTriggerTask(analysisService::totalGasAndProduction, new CronTrigger("0 0,20,40 1 * * ? "));
    }

    @RequestMapping("tsdb/test")
    public String test() {
        analysisService.analysisEntrance();
        return "11111";
    }
}


二、自动配置

@SpringBootApplication 注解

//@Configuration
@SpringBootConfiguration 
//自动装配核心注解
@EnableAutoConfiguration
//包扫描
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
//自动装配核心注解 @EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	/**
	 * Environment property that can be used to override when auto-configuration is
	 * enabled.
	 */
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

-1、@AutoConfigurationPackage

  • 导入一个组件@Import(AutoConfigurationPackages.Registrar.class)

    • 自动注册主配置类所在的包
    • 会在springIOC容器刷新第5部注册bean定义时候调用(将bean定义放入到容器中时候) loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    • ImportBeanDefinitionRegistrar 实现了这个类
  • packageNames传的就是启动类所在的包名,然后这个方法就是判断容器是否注入了BasePackagesBeanDefinition。如果注入了就从容器获取,并将包名赋值给他的basePackages属性,然后执行这块的时候其实是并没有注册的,所以直接执行else。else就是直接创建一个BasePackagesBeanDefinition对象,然后将包名赋值给他的basePackages属性。

  • 其实这个就是springboot默认的扫描包。也就是这个包下的只要使用注入容器相关的注解,就会被放入到IOC容器当中。

//metadata:注解的元信息 就是这个注解的原始位置在什么类上,main方法所在的类
//registry:beanFactory

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
    }

    @Override
    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImports(metadata));
    }

}

	public static void register(BeanDefinitionRegistry registry, String... packageNames) {
        //判断容器中是否包含BeanDefinition(AutoConfigurationPackages)
		if (registry.containsBeanDefinition(BEAN)) {
			BasePackagesBeanDefinition beanDefinition = (BasePackagesBeanDefinition) registry.getBeanDefinition(BEAN);
			beanDefinition.addBasePackages(packageNames);
		}
		else {
            //将main方法所在的类封装为的BasePackagesBeanDefinition 放入ioc容器中
			registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
		}
	}

-2- @Import(AutoConfigurationImportSelector.class)

  • AutoConfigurationImportSelector 实现 DeferredImportSelector 其内部类实现接口的内部接口 Group

  • springIOC调用 实现DeferredImportSelector接口后中的Group接口 的 process 方法进行组件注入

  • 在IOC容器刷新第5步骤 对配置类进行处理时候 调用

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-828k39OB-1688298080303)(./图片/自动配置.png)]

public void processGroupImports() {
    for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
        Predicate<String> exclusionFilter = grouping.getCandidateFilter();
        // 调用DeferredImportSelectorGrouping的getImports() 方法得到一个Iterable<Entry>集合
        // 遍历集合中的元素
        grouping.getImports().forEach(entry -> {
            ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
            try {
                // 调用processImports解析是否是有Import,进行递归调用放入到beanFactory
                processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
                               Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
                               exclusionFilter, false);
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configurationClass.getMetadata().getClassName() + "]", ex);
            }
        });
    }
}

spring-ioc:https://blog.csdn.net/qq_52219290/article/details/129487618

public Iterable<Group.Entry> getImports() {
    for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
        // 调用process
        this.group.process(deferredImport.getConfigurationClass().getMetadata(),
                           deferredImport.getImportSelector());
    }
    //调用selectImports
    return this.group.selectImports();
}

process()

public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
   //获取自动配置类
    AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
        .getAutoConfigurationEntry(annotationMetadata);
    this.autoConfigurationEntries.add(autoConfigurationEntry);
    for (String importClassName : autoConfigurationEntry.getConfigurations()) {
        this.entries.putIfAbsent(importClassName, annotationMetadata);
    }
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    //检查自动配置功能是否开启,默认开启
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
	//@SpringBootApplication注解的属性  annotationMetadata == main类元数据注释信息
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    //获取配置类
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    //删除重复的(list变为set在变为list)
    configurations = removeDuplicates(configurations);
    //获得@SpringBootApplication注解中被exclude和excludeName排除的类的集合
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    //检查被排除类是否可实例化、是否被自动注册配置所使用,不符合条件则抛出异常
    checkExcludedClasses(configurations, exclusions);
    //从候选配置类中去除掉被排除的类
    configurations.removeAll(exclusions);
    //获取配置类过滤器过滤掉不符合要求的类
    configurations = getConfigurationClassFilter().filter(configurations);
    //将配置类和排除类通过事件传入到监听器中
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}
//getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    //从spring.factories文件中获取配置类
    //getSpringFactoriesLoaderFactoryClass() == EnableAutoConfiguration.class
    List<String> configurations = new ArrayList<>(
        SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
    ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
    return configurations;
}

selectImports()

public Iterable<Entry> selectImports() {
    if (this.autoConfigurationEntries.isEmpty()) {
        return Collections.emptyList();
    }
    // 提取所有的排除项(exclusions),并将它们收集到一个Set集合中,表示所有被排除的配置类。
    Set<String> allExclusions = this.autoConfigurationEntries.stream()
        .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
    // 提取所有的配置项(configurations),并将它们收集到一个LinkedHashSet集合中,表示所有的配置类(可能包括被排除的配置类)。
    Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
        .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
        .collect(Collectors.toCollection(LinkedHashSet::new));
    // 从所有配置项中移除被排除的配置项,得到一个只包含有效配置类的集合
    processedConfigurations.removeAll(allExclusions);

    // 进行排序,该方法根据配置类之间的依赖关系进行排序,确保配置类的正确顺序。
	// 将排序后的配置类转换为一个包含Entry对象的列表,每个Entry对象表示一个导入项,包含配置类信息和配置类的全限定类名。
    return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
        .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
        .collect(Collectors.toList());
}

三、spi

spi:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Springboot源码解析PDF是一本深入解析Springboot框架的技术书籍,涵盖了Springboot的背景、原理、设计思路、运行机制、开发实践等方面。全书主要分为三部分:第一部分介绍Springboot的基础知识,包括Spring框架的常用注解、Springboot的配置、自动配置原理等;第二部分深入探讨Springboot的主要功能,如数据访问、Web开发、缓存、消息、安全等;第三部分着重介绍开发Springboot应用的最佳实践,包括Springboot与其他框架的结合使用、集成测试、监控与诊断等。 阅读Springboot源码解析PDF可以让开发者更深入理解Springboot的设计理念、技术实现以及应用场景,在实际项目开发中更加灵活、高效地使用Springboot。该书对于有一定JavaSpring框架基础的开发者来说是一本非常优秀的参考资料,也是Java开发者必不可少的技术读物。同时,该书也是借助源码解析的方式,让读者更加系统化地学习Springboot技术,具有很高的实用性和参考价值。总之,阅读Springboot源码解析PDF有助于开发者更好地掌握Springboot技术,提高应用开发效率和代码质量。 ### 回答2: Spring Boot源码解析pdf是一本介绍Spring Boot框架的开源书籍,该书的目的是帮助开发者深入了解Spring Boot的内部工作原理和实现细节。 该书首先从Spring Boot框架的源码结构和核心模块入手,详细介绍了Spring Boot的MVC、ORM、缓存、安全等核心功能的实现原理。同时,该书还介绍了Spring Boot对微服务的支持和整合Spring Cloud的方式,让开发者更深入了解Spring Boot在分布式架构中的应用。 在讲解源码实现原理的同时,该书还指出了一些常见的开发问题和易错点,并提供了相应的解决方案。此外,该书还通过一系列的案例,全面展示了Spring Boot的实际开发应用场景,帮助开发者更好地应用Spring Boot框架。 总的来说,Spring Boot源码解析pdf是一本非常实用的书籍,能够帮助开发者快速掌握Spring Boot框架的内部实现原理,提高开发效率和代码质量。同时,该书还可以作为学习Spring Boot的参考资料,对于想要深入学习和研究Spring Boot的开发者来说是非常有用的。 ### 回答3: Spring Boot 是一个很受欢迎的 Java 框架,它简化了开发者的工作,允许他们更快速地构建和部署应用程序。Spring Boot 的优点包括简洁的配置、内嵌的 Web 容器和现成的插件,让开发者可以更专注于业务逻辑。Spring Boot源码解析是学习它的关键。 Spring Boot源码解析Java初学者来说可能会比较复杂,但是它对于学习框架和原理是非常有益的。一个好的 Spring Boot 项目需要基于很好的基础,这就要求开发者了解其源码源码解析可以帮助开发者了解各种设计模式和组件的原理,有助于解决实际问题。 在 Spring Boot源码解析中,我们将会找到很多有用的信息。例如,我们可以看到 Spring Boot 如何通过注解处理器创建并配置 bean,这可以帮助我们更好地理解依赖注入和 IoC 容器。此外,我们还可以了解 Spring Boot 如何处理 HTTP 请求、创建模板、处理安全性等。这些知识可以帮助我们更好地理解 Spring Boot 内部的工作机制。 总之,Spring Boot源码解析是必不可少的一部分,它可以帮助开发者更好地了解和使用该框架,掌握在实践中所需的知识和技能。如果您是一名 Spring 开发者,那么深入了解 Spring Boot源码将会是一个很好的学习过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值