Поверхностный анализ процесса запуска SpringBoot

Поверхностный анализ процесса запуска SpringBoot

1. Стартовый класс

1. Аннотация @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) })
复制代码

изображение-20220327122913567

Для процесса автоматической настройки вы можете прочитать этот пост в блоге

[Spring Boot] Схема автоматической настройки Spring Boot полна текстов — Блог Autumn Sunset — Блог CSDN

2.основной метод

   public static void main(String[] args) {
        SpringApplication.run(AppTest.class, args);
    }
复制代码

следовать за

изображение-20220327123111967

Сначала взгляните на статический метод объявления метода, который возвращает объект класса реализации интерфейса ConfigurableApplicationContext.

изображение-20220327123422047

изображение-20220327123612064

Вы можете видеть, что существует множество классов реализации и подинтерфейсов, так как же выбрать объект класса реализации? Продолжайте следить за исходным кодом с этим вопросом.

изображение-20220327123733436

primarySources   //主启动类的class对象  
args   //main方法的启动参数
复制代码

Здесь создается новый экземпляр SpringApplication и вызывается метод запуска

новое приложение Spring ()

Используйте новый метод SpringApplication(primarySources)

public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}
复制代码

Создайте новый экземпляр SpringApplication. Контекст приложения будет загружать bean-компоненты из указанного основного источника.

Продолжайте следить за методом построения

изображение-20220327124335545

resourceLoader  //资源加载器   此时为null 

this.resourceLoader = resourceLoader;
复制代码
primarySources  //容器中bean的来源   此时为主启动类的字节码对象
复制代码

Это утверждает, что primarySources не может быть нулевым, иначе будет выдано исключение.

Assert.notNull(primarySources, "PrimarySources must not be null");
复制代码

PrimarySources в параметре метода является переменным параметром, а затем primarySources превращается в LinkedHashSet.

this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
复制代码

Элементы коллекции наборов LinkedHashSet не повторяются, базовый слой представляет собой связанный список для обеспечения упорядоченного хранения.

Затем выполните эту строку кода

this.webApplicationType = WebApplicationType.deduceFromClasspath();
复制代码

Что это за webApplicationType? Нажмите, и вы увидите, что это перечисление с тремя элементами перечисления

	/**
	 * The application should not run as a web application and should not start an
	 * embedded web server.
	 该应用程序不应作为 Web 应用程序运行,也不应启动嵌入式 Web 服务器。
	 */
	NONE,

	/**
	 * The application should run as a servlet-based web application and should start an
	 * embedded servlet web server.
	 应用程序应作为基于 servlet 的 Web 应用程序运行,并应启动嵌入式 servlet Web 服务器
	 */
	SERVLET,

	/**
	 * The application should run as a reactive web application and should start an
	 * embedded reactive web server.
	 该应用程序应作为响应式 Web 应用程序运行,并应启动嵌入式响应式 Web 服务器
	 */
	REACTIVE;
复制代码

изображение-20220327125229813

Судя по текущему типу проекта, здесь возвращается WebApplicationType.SERVLET, то есть тип текущего SpringApplication — это веб-приложение, встроенный сервлет веб-сервера.

Затем настройте прослушиватель

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
复制代码

Затем установите запись программы

this.mainApplicationClass = deduceMainApplicationClass()
复制代码

Контейнер Spring запускает создание экземпляра объекта класса

SpringApplication.run()

Далее посмотрим, что делает метод run

изображение-20220327125749885

StopWatch stopWatch = new StopWatch();   //计时器
stopWatch.start();  //开始计时
复制代码

Установлено системное свойство java.awt.headless.

configureHeadlessProperty()
复制代码

Получите прослушиватель для класса начальной загрузки контекста приложения Spring,

SpringApplicationRunListeners listeners = getRunListeners(args)
复制代码

Следите, чтобы узнать и опубликовать событие ApplicationStartingEvent.

listeners.starting();
复制代码

изображение-20220327131941245

Инкапсулируйте параметры, необходимые для загрузочного класса SpringApplication.

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
复制代码

Подготовьте среду

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
复制代码

Игнорировать нежелательные bean-компоненты на основе текущей среды

configureIgnoreBeanInfo(environment);
复制代码

изображение-20220327132203736

распечатать баннер

Banner printedBanner = printBanner(environment)
复制代码

Перед созданием контекста ApplicationContext убедитесь, что тип webApplicationType — SERVLET.

context = createApplicationContext()
复制代码

image-20220327133346608

image-20220327133705760Возвратите объект байт-кода AnnotationConfigServletWebServerApplicationContext, а затем вызовите BeanUtils.instantiateClass для создания экземпляра.

class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry 
复制代码

Унаследовано от ServletWebServerApplicationContext

Обновление контекста, наконец, повторно использует метод контейнера обновления Spring.

refreshContext(context);
复制代码

Вызовите метод ConfigurableApplicationContext.refresh().

再调用org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh

Наконец, вызовите org.springframework.context.support.AbstractApplicationContext#refresh

12 способов обновить контейнеры Ознакомьтесь с этой записью в блоге

[Весна] Анализ исходного кода процесса запуска контейнера SpringIOC и проблемы циклической зависимости — Блог Autumn Sunset — Блог CSDN

image-20220327132839716

image-20220327132925712

Наконец, остановите таймер и распечатайте журнал

        stopWatch.stop();

        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }


复制代码

рекомендация

отjuejin.im/post/7079651741762846733