Spring Boot 3.1.5 源码分析-[学习笔记]

Spring Boot源码分析

启动类注解

@SpringBootApplication

集成注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
@Inherited

@Inherited修饰的注解,如果作用在某个类上,其子类是可以继承该注解;

@SpringBootConfiguration

@SpringBootConfiguration 标明了配置类是Spring Boot的配置类

@EnableAutoConfiguration

开启自动装配,实例化start目录以外的bean

@AutoConfigurationPackage

指定自动装配的包

/**
*AutoConfigurationPackages.Registrar.class 
将被@SpringBootAPplication标记的包,包装成BasePackage,注册到spring容器中
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}
public abstract class AutoConfigurationPackages {

    private static final String BEAN = AutoConfigurationPackages.class.getName();

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

        /**
         * 根据 ImportBeanDefinitionRegistrar 的处理,spring将调用 registerBeanDefinitions() 注册内容
         */
        @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata, 
                    BeanDefinitionRegistry registry) {
            //new PackageImports(metadata).getPackageNames()`就是当前启动类所在的包。
            register(registry, new PackageImport(metadata).getPackageName());
        }

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

    }

    /**
     * 处理具体的注册操作
     * 1. 如果 beanFacotry 中包含 BEAN,则将传入的包名添加到 BEAN 对应的 BeanDefinition 的构造方法参数值上;
     * 2. 如果 beanFacotry 中不包含 BEAN,则创建 beanDefinition,设置参数值,然后将其注册到 beanFacotry。
     * 注册到beanFacotry中的bean为BasePackages
     */
    public static void register(BeanDefinitionRegistry registry, String... packageNames) {
        if (registry.containsBeanDefinition(BEAN)) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
            // bean 是 BasePackages,构造方法是 BasePackages(String... names),这里获取原本的构造参数的值
            ConstructorArgumentValues constructorArguments 
                    = beanDefinition.getConstructorArgumentValues();
            // 将原本的构造参数值,以及传入的 packageNames 统一添加到构造方法的第0个参数值上
            constructorArguments.addIndexedArgumentValue(0, 
                    addBasePackages(constructorArguments, packageNames));
        }
        else {
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            // 设置BeanClass为BasePackages.class
            beanDefinition.setBeanClass(BasePackages.class);
            // 设置构造方法的参数值
            beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(BEAN, beanDefinition);
        }
    }

    /**
     * packageName 的包装类
     * packageName 是传入类所在的包名,在PackageImport的构造方法中获取
     */
    private static final class PackageImport {

        private final String packageName;

        PackageImport(AnnotationMetadata metadata) {
            // 获取传入类所在包名
            this.packageName = ClassUtils.getPackageName(metadata.getClassName());
        }

        String getPackageName() {
            return this.packageName;
        }

        // 省略 equals/toString/hashCode 方法
        ...

    }

    /**
     * 注解到 beanFactory 中的类
     * 该类中有一个List结构,用来保存包扫描路径
     */
    static final class BasePackages {
        // 包扫描路径在这里保存
        private final List<String> packages;

        private boolean loggedBasePackageInfo;

        BasePackages(String... names) {
            List<String> packages = new ArrayList<>();
            for (String name : names) {
                if (StringUtils.hasText(name)) {
                    packages.add(name);
                }
            }
            this.packages = packages;
        
    }

}

@Import({AutoConfigurationImportSelector.class})

根据配置文件spring.factories,将bean注入到容器中
AutoConfigurationImportSelector 开启自动配置类的导包的选择器(导入哪些组件的选择器),DeferedImportSelector处理自动配置。如果需要@EnableAutoConfiguration的自定义变量,也可以对该类进行子类化。

public interface DeferredImportSelector extends ImportSelector {
    ...

    interface Group {

        /**
         * 处理导入操作
         */
        void process(AnnotationMetadata metadata, DeferredImportSelector selector);

        /**
         * 返回导入类
         */
        Iterable<Entry> selectImports()
    }
}

@ComponentScan()
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

@ComponentScan()指定包扫描路径
TypeExcludeFilter: 这个类表示在进行包扫描时,可以排除一些类。

AutoConfigurationExcludeFilter:用来排除自动配置类,也就是说,spring 在进行包扫描时,不会扫描自动配置类.

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.boot.autoconfigure;

import java.io.IOException;
import java.util.List;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
    private ClassLoader beanClassLoader;
    private volatile List<String> autoConfigurations;

    public AutoConfigurationExcludeFilter() {
    }

    public void setBeanClassLoader(ClassLoader beanClassLoader) {
        this.beanClassLoader = beanClassLoader;
    }

    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        return this.isConfiguration(metadataReader) && this.isAutoConfiguration(metadataReader);
    }

    private boolean isConfiguration(MetadataReader metadataReader) {
        return metadataReader.getAnnotationMetadata().isAnnotated(Configuration.class.getName());
    }

    private boolean isAutoConfiguration(MetadataReader metadataReader) {
        boolean annotatedWithAutoConfiguration = metadataReader.getAnnotationMetadata().isAnnotated(AutoConfiguration.class.getName());
        return annotatedWithAutoConfiguration || this.getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
    }

    protected List<String> getAutoConfigurations() {
        if (this.autoConfigurations == null) {
            this.autoConfigurations = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader).getCandidates();
        }

        return this.autoConfigurations;
    }
}

启动流程

启动器入口

@SpringBootApplication
public class UserApplication {

	public static void main(String[] args) {
	//run 方法启动入口
		SpringApplication.run(UserApplication.class, args);
	}

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

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    //primarySources 就是 class com.user.UserApplication
    //args就是参数
        return (new SpringApplication(primarySources)).run(args);
    }

重要方法

SpringApplicaion(primarySources) 构造方法
run(agrs)

SpringApplicaion(primarySources) 构造方法
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		//resourceLoader 设置成员变量,这里的值为null
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//设置primarySourse成员变量 UserApplication.class
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//当前的web应用类型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		//设置初始化器,从META-INF/spring.factories中获取配置
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//设值监听器,从META-INF/spring.factories中获取配置
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//返回包含main()方法的class
		this.mainApplicationClass = deduceMainApplicationClass();
	}
WebApplicationType

spring-boot-starter-web 所以是web应用


package org.springframework.boot;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.util.ClassUtils;

/**
 * An enumeration of possible types of web application.
 *
 * @author Andy Wilkinson
 * @author Brian Clozel
 * @since 2.0.0
 */
public enum WebApplicationType {

	/**
	 * 不是web应用
	 * embedded web server.
	 */
	NONE,

	/**
	 * servlet 类型的 web应用
	 * embedded servlet web server.
	 */
	SERVLET,

	/**
	 * reactive 类型的web应用
	 * embedded reactive web server.
	 */
	REACTIVE;

	private static final String[] SERVLET_INDICATOR_CLASSES = { "jakarta.servlet.Servlet",
			"org.springframework.web.context.ConfigurableWebApplicationContext" };

	private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

	private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

	private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

	static WebApplicationType deduceFromClasspath() {
	// classpath中仅存在 WEBFLUX 相关类
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
		// classpath 不存在 servlet相关类
		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		//默认 web 类型为servlet 相关类
		//同时存在WEBFLUX 与 SERVLET相关类 最终返回的是SERVLET
		return WebApplicationType.SERVLET;
	}

	static class WebApplicationTypeRuntimeHints implements RuntimeHintsRegistrar {

		@Override
		public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
			for (String servletIndicatorClass : SERVLET_INDICATOR_CLASSES) {
				registerTypeIfPresent(servletIndicatorClass, classLoader, hints);
			}
			registerTypeIfPresent(JERSEY_INDICATOR_CLASS, classLoader, hints);
			registerTypeIfPresent(WEBFLUX_INDICATOR_CLASS, classLoader, hints);
			registerTypeIfPresent(WEBMVC_INDICATOR_CLASS, classLoader, hints);
		}

		private void registerTypeIfPresent(String typeName, ClassLoader classLoader, RuntimeHints hints) {
			if (ClassUtils.isPresent(typeName, classLoader)) {
				hints.reflection().registerType(TypeReference.of(typeName));
			}
		}

	}

}
设置初始化器 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

从META-INF/spring.factories 进行实例化

	private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
		return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
	}
public class SpringFactoriesLoader{


	public static SpringFactoriesLoader forDefaultResourceLocation(@Nullable ClassLoader classLoader) {
		return forResourceLocation(FACTORIES_RESOURCE_LOCATION, classLoader);
	}
	public static SpringFactoriesLoader forResourceLocation(String resourceLocation, @Nullable ClassLoader classLoader) {
		Assert.hasText(resourceLocation, "'resourceLocation' must not be empty");
		ClassLoader resourceClassLoader = (classLoader != null ? classLoader :
				SpringFactoriesLoader.class.getClassLoader());
		Map<String, SpringFactoriesLoader> loaders = cache.computeIfAbsent(
				resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());
		return loaders.computeIfAbsent(resourceLocation, key ->
				new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation)));
	}


protected static Map<String, List<String>> loadFactoriesResource(ClassLoader classLoader, String resourceLocation) {
		Map<String, List<String>> result = new LinkedHashMap<>();
		try {
			Enumeration<URL> urls = classLoader.getResources(resourceLocation);
			while (urls.hasMoreElements()) {
				UrlResource resource = new UrlResource(urls.nextElement());
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				properties.forEach((name, value) -> {
					String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) value);
					List<String> implementations = result.computeIfAbsent(((String) name).trim(),
							key -> new ArrayList<>(factoryImplementationNames.length));
					Arrays.stream(factoryImplementationNames).map(String::trim).forEach(implementations::add);
				});
			}
			result.replaceAll(SpringFactoriesLoader::toDistinctUnmodifiableList);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" + resourceLocation + "]", ex);
		}
		return Collections.unmodifiableMap(result);
	}
}

setInitalizers()

会把项目中所有的spring.factories中的key都存到内存里,后面可以快速找到对应key

	/**
	 * Sets the {@link ApplicationContextInitializer} that will be applied to the Spring
	 * {@link ApplicationContext}.
	 * @param initializers the initializers to set
	 */
	public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
		this.initializers = new ArrayList<>(initializers);
	}
设置监听器

流程和实例化器一致

获取main()方法

获取调用栈,遍历得到包含main方法的类

		this.mainApplicationClass = deduceMainApplicationClass();

	private Class<?> deduceMainApplicationClass() {
		return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
			.walk(this::findMainClass)
			.orElse(null);
	}
	private Optional<Class<?>> findMainClass(Stream<StackFrame> stack) {
		return stack.filter((frame) -> Objects.equals(frame.getMethodName(), "main"))
			.findFirst()
			.map(StackWalker.StackFrame::getDeclaringClass);
	}
run()
public ConfigurableApplicationContext run(String... args) {
//开启钩子,用作在进程结束后做善后工作
		if (this.registerShutdownHook) {
			SpringApplication.shutdownHook.enableShutdowHookAddition();
		}
		//测量方法执行时间
		long startTime = System.nanoTime();
		//启动期间传递上下文信息和执行逻辑
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		//准备空的ApplicationContext,以及一组异常报告器
		ConfigurableApplicationContext context = null;
		//配置 headless 属性,java.awt.headless,java.awt.headless模式是系统的一种配置模式,在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式
		configureHeadlessProperty();
		// 获取监听器,也是从 META-INF/spring.factories 中获取
		SpringApplicationRunListeners listeners = getRunListeners(args);
		 // starting():首次启动run方法时立即调用。可用于非常早期的初始化(准备运行时环境之前)。
   		// 发布事件
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
		 	// 封装传入的参数,args是启动Spring应用的命令行参数,该参数可以在Spring应用中被访问。如:--server.port=9000
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// 处理环境参数
      		// 创建并配置当前SpringBoot应用将要使用的Environment
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			//准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体
			Banner printedBanner = printBanner(environment);
			//创建applicationContext 核心容器
			context = createApplicationContext();
			//让核心容器跑起来	
			context.setApplicationStartup(this.applicationStartup);
			//准备上下文,设置了一系列的属性值
      		//这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			//刷新容器 调用 AbstractApplicationContext.refresh,启动spring容器
			refreshContext(context);
			//最后刷新
			//刷新后的处理
      		//扩展接口,设计模式中的模板方法,默认为空实现。
      		// 如果有自定义需求,可以重写该方法。比如打印一些启动结束log,或者一些其它后置处理
			afterRefresh(context, applicationArguments);
			//停止统计时间
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}
			//发布事件
			listeners.started(context, timeTakenToStartup);
			调用 runner,实现了 ApplicationRunnerCommandLineRunner 的接口
      		//用于调用项目中自定义的执行器XxxRunner类,使得在项目启动完成后立即执行一些特定程序
      		//Runner 运行器用于在服务启动时进行一些业务初始化操作,这些操作只在服务启动后执行一次。
      		//Spring Boot提供了ApplicationRunner和CommandLineRunner两种服务接口
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			if (ex instanceof AbandonedRunException) {
				throw ex;
			}
			 // 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
		//发布应用上下文就绪事件
		   	   //表示在前面一切初始化启动都没有问题的情况下,使用运行监听器SpringApplicationRunListener持续运行配置好的应用上下文ApplicationContext,
		       // 这样整个Spring Boot项目就正式启动完成了
			if (context.isRunning()) {
				Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
				listeners.ready(context, timeTakenToReady);
			}
		}
		catch (Throwable ex) {
			if (ex instanceof AbandonedRunException) {
				throw ex;
			}
			// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
DefaultBootstrapContext
private DefaultBootstrapContext createBootstrapContext() {
    DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();//创建 DefaultBootstrapContext实例 ->
    this.bootstrapRegistryInitializers.forEach((initializer) -> { //遍历列表 列表内容:bootstraptInitializer 注册表初始器
        initializer.initialize(bootstrapContext); //每个注册表初始器初始化引导程序上下文
    });
    return bootstrapContext;
}
configureHeadlessProperty()

定义了一系列的方法来监听 springboot 的启动过程,方法的说明已经在文档中有详细定义,如果我们需要在 springboot 的启动中的某个过程做一些事情,就可以实现 SpringApplicationRunListener 然后重写对应的方法

listeners.starting()就是遍历所有的监听器,逐一调用其 starting() 罢了,this.listeners 就是上面获取到的所有的运行监听器

java.awt.headless 的值设置到了系统变量,设置成 true,缺少显示设备
监听器
public interface SpringApplicationRunListener {

    /**
     * 首次启动run方法时立即调用。可用于非常早期的初始化。
     */
    default void starting() {
    }

    /**
     * 准备好环境(Environment构建完成),但在创建ApplicationContext之前调用。
     */
    default void environmentPrepared(ConfigurableEnvironment environment) {
    }

    /**
     * 在创建和构建ApplicationContext之后,但在加载之前调用。
     */
    default void contextPrepared(ConfigurableApplicationContext context) {
    }

    /**
     * ApplicationContext已加载但在刷新之前调用。
     */
    default void contextLoaded(ConfigurableApplicationContext context) {
    }

    /**
     * ApplicationContext已刷新,应用程序已启动,
     * 但尚未调用CommandLineRunners和ApplicationRunners。
     */
    default void started(ConfigurableApplicationContext context) {
    }

    /**
     * 在运行方法彻底完成之前立即调用,
     * 刷新ApplicationContext并调用所有CommandLineRunners和ApplicationRunner。
     */
    default void running(ConfigurableApplicationContext context) {
    }

    /**
     * 在运行应用程序时失败时调用。
     */
    default void failed(ConfigurableApplicationContext context, Throwable exception) {
    }
}

准备运行环境ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments)
	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		// 配置运行时环境
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		    //  SpringApplicationRunListener 的 environmentPrepared 方法
    // (Environment构建完成,但在创建ApplicationContext之前)
    //  配置文件加载监听器(ConfigFileApplicationListener)
		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;
	}
获取或创建环境
	private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
		ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType);
		if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
			environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType);
		}
		return (environment != null) ? environment : new ApplicationEnvironment();
	}
配置获取或创建环境
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
        // 添加转换器,处理参数类型转换,如 String转Number,Integer转Enum等
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService) conversionService);
    }
    // 将启动参数添加到 environment 中 形如 java -jar xxx.jar --a1=aaa --b1=bbb
    configurePropertySources(environment, args);
    // 处理 ActiveProfiles 值
    configureProfiles(environment, args);
}

createApplicationContext()创建核心容器 IOC
	private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
			BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
		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;
	}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    private final DefaultListableBeanFactory beanFactory;
    @Nullable
    private ResourceLoader resourceLoader;
    private boolean customClassLoader;
    private final AtomicBoolean refreshed;

    public GenericApplicationContext() {
        this.customClassLoader = false;
        this.refreshed = new AtomicBoolean();
        this.beanFactory = new DefaultListableBeanFactory();
    }

    public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
        this.customClassLoader = false;
        this.refreshed = new AtomicBoolean();
        Assert.notNull(beanFactory, "BeanFactory must not be null");
        this.beanFactory = beanFactory;
    }
}
容器准备 prepareContext()
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
			// 将创建好的应用环境设置到IOC容器中
		context.setEnvironment(environment);
		// 设置容器的一些参数
		postProcessApplicationContext(context);
		addAotGeneratedInitializerIfNecessary(this.initializers);
		applyInitializers(context);
		 //  监听器:SpringApplicationRunListeners的contextPrepared方法
        // (在创建和准备ApplicationContext之后,但在加载之前)
		listeners.contextPrepared(context);
		bootstrapContext.close(context);
		// 打印个日志
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// 获取beanFactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		// 将运行参数作为bean注册到beanFactory中
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		// 将 banner 作为bean注册到beanFactory中
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
		 // 是否允许bean的信息被覆盖
		if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
			autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
			if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
				listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
			}
		}
		// 处理懒加载
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
		if (!AotDetector.useGeneratedArtifacts()) {
			// 获取所有资源
			Set<Object> sources = getAllSources();
			Assert.notEmpty(sources, "Sources must not be empty");
			 // 加载 class
			load(context, sources.toArray(new Object[0]));
		}
		// 发布事件
		listeners.contextLoaded(context);
	}

	private void addAotGeneratedInitializerIfNecessary(List<ApplicationContextInitializer<?>> initializers) {
		if (AotDetector.useGeneratedArtifacts()) {
			List<ApplicationContextInitializer<?>> aotInitializers = new ArrayList<>(
					initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList());
			if (aotInitializers.isEmpty()) {
				String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
				aotInitializers.add(AotApplicationContextInitializer.forInitializerClasses(initializerClassName));
			}
			initializers.removeAll(aotInitializers);
			initializers.addAll(0, aotInitializers);
		}
	}
刷新容器 refresh()
private void refreshContext(ConfigurableApplicationContext context) {
    // 启动spring容器
    refresh(context);
    if (this.registerShutdownHook) {
        try {
            // 注册 ShutdownHook
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}
  public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            //准备此上下文以进行刷新。将 servletContext 与 servletConfig 设置到了 Environment 中。
            this.prepareRefresh();
            //告诉子类刷新内部 Bean 工厂
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 准备 Bean 工厂以在此上下文中使用。
            this.prepareBeanFactory(beanFactory);

            try {
            // 允许在上下文子类中对 Bean 工厂进行后处理。这个 BeanPostProcessor 是用来处理 ServletContextAware 与 ServletConfigAware 两个 Aware 接口的
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
      // 执行 BeanFactoryPostProcessors。在这个方法中,有个重的 BeanFactoryPostProcessor 会被执行:ConfigurationClassPostProcessor,springboot 的自动装配的启用注解 @EnableAutoConfiguration 会在这里处理,自动装配类的加载、条件注解也是在 ConfigurationClassPostProcessor 中
         this.invokeBeanFactoryPostProcessors(beanFactory);
         // 注册 BeanPostProcessor
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                // 初始化此上下文的消息源,用于国际化操作。
                this.initMessageSource();
                // 为此上下文初始化事件多播程序。
                this.initApplicationEventMulticaster();
                // 在特定上下文子类中初始化其他特殊 bean。web 服务器是在这个方法中创建的,如tomcat/jetty等
                this.onRefresh();
                // 注册事件监听器
                this.registerListeners();
                // 初始化单例 
                beanthis.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }
				// 销毁已创建的单例以避免悬而未决的资源。
                this.destroyBeans();
                // 重置“活动”标志。
                this.cancelRefresh(var10);
                // 将异常传播给调用方。
                throw var10;
            } finally {
            // 重置 Spring 核心中的常见内省缓存,因为我们可能不再需要单例 Bean 的元数据了
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }
刷新后处理afterRefresh()

一个空方法,springboot 提供的扩展

callRunners()

springboot 为我们提供了两个接口:ApplicationRunner 与
CommandLineRunner,我们可以实现它来完成一些操作

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<>();
    // 获取所有的 ApplicationRunner 与 CommandLineRunner
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    // 排序
    AnnotationAwareOrderComparator.sort(runners);
    // 遍历调用
    for (Object runner : new LinkedHashSet<>(runners)) {
        // 调用 ApplicationRunner#run 方法
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        // 调用 CommandLineRunner#run 方法
        if (runner instanceof CommandLineRunner) {
            callRunner((CommandLineRunner) runner, args);
        }
    }
}

/**
 * 调用 ApplicationRunner#run 方法
 */
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    try {
        (runner).run(args);
    }
    catch (Exception ex) {
        throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
    }
}

/**
 * 调用 CommandLineRunner#run 方法
 */
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
    try {
        (runner).run(args.getSourceArgs());
    }
    catch (Exception ex) {
        throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
    }
}

总结

目前Spring Boot 3.×源码分析作者也只是浅浅的理解了一部分,欢迎大家一起讨论,后续会一直更新该博客,将自己最新的理解补充进来。

参考链接https://blog.youkuaiyun.com/Ares___/article/details/128087439,内容很棒,同学们想更深入的了解可跳转此链接,为该博主打call!!!

<think>好的,我现在需要回答用户关于在Spring Boot 3.1.5中集成Spring Cloud进行微服务架构开发的问题。首先,我需要结合用户提供的引用内容,特别是引用[1]、[2]、[4]中的信息,来构建一个清晰的步骤指南。 用户提到的引用[1]解释了Spring Cloud和Spring Boot的关系,强调Spring Boot用于开发单个微服务,而Spring Cloud负责协调和管理这些微服务。因此,在集成时,需要明确两者的版本兼容性。引用[4]提到Spring Boot 3.1.5对应的Spring Cloud版本是2022.0.4,这需要作为依赖管理的基础。 接下来,用户可能需要知道如何设置父项目,管理依赖版本。根据引用[4],应该在pom.xml中使用dependencyManagement引入Spring Cloud的BOM,确保所有子模块使用统一的版本。同时,引用[2]提到Spring Boot升级到3.1.5需要注意迁移指南,因此要确认所有依赖库是否兼容,特别是Spring Cloud组件。 然后,用户需要添加具体的Spring Cloud组件,比如服务发现(Eureka)、配置中心(Config)、API网关等。引用[4]中的例子是Eureka注册中心,所以应该详细说明如何配置Eureka Server和Client,包括依赖添加和配置文件设置。 另外,用户可能需要了解如何启用Spring Cloud的功能,比如使用@EnableEurekaServer注解,这属于代码层面的配置。引用[3]提到了@SpringBootConfiguration和@EnableAutoConfiguration,但用户的问题更关注Spring Cloud的集成,所以重点放在相关的注解和配置上。 最后,用户可能关心实际应用中的例子,比如创建一个简单的微服务并进行服务注册与发现。需要提供代码示例,例如启动类、配置文件以及服务调用的方法。同时,测试步骤也是重要的,比如如何启动Eureka服务器和客户端,并验证它们是否正常注册。 还需要注意,用户提供的引用中有关于Dubbo和Spring Cloud的对比,但用户的问题主要集中在Spring Cloud,因此可能不需要深入比较,但可以作为扩展内容提及。 总结步骤应该是:版本匹配、依赖管理、添加组件依赖、配置注册中心、创建微服务模块、测试验证。同时,要确保所有步骤符合Spring Boot 3.1.5Spring Cloud 2022.0.4的兼容性要求,并引用正确的文档和迁移指南。</think>### Spring Boot 3.1.5集成Spring Cloud微服务架构开发指南 #### 1. **版本兼容性匹配** - **Spring Boot 3.1.5** 需搭配 **Spring Cloud 2022.0.4**(对应Spring Cloud版本命名规则为"Kilburn")[^4]。 - 在父项目的`pom.xml`中通过`dependencyManagement`统一管理依赖版本: ```xml <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2022.0.4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ``` #### 2. **添加Spring Cloud核心组件** - **服务注册与发现(Eureka)**: 1. **Eureka Server**:添加依赖并配置服务端: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> ``` 启动类添加注解: ```java @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { ... } ``` 配置文件`application.yml`: ```yaml server: port: 8761 eureka: client: register-with-eureka: false # 不向自身注册 fetch-registry: false ``` 2. **Eureka Client**:在微服务模块中添加客户端依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> ``` 配置文件中指定注册中心地址: ```yaml eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ ``` - **配置中心(Spring Cloud Config)**: 1. 添加依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> ``` 2. 启动类启用配置服务: ```java @EnableConfigServer @SpringBootApplication public class ConfigServerApplication { ... } ``` #### 3. **微服务模块开发** - 每个微服务模块需独立配置,例如`user-service`和`order-service`: ```java @SpringBootApplication @EnableDiscoveryClient // 启用服务发现 public class UserServiceApplication { ... } ``` - 使用`RestTemplate`或`OpenFeign`实现服务间调用: ```java @Bean @LoadBalanced // 启用负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); } ``` #### 4. **测试与验证** 1. 启动Eu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制诗人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值