Поверхностный анализ процесса запуска 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) })
复制代码
Для процесса автоматической настройки вы можете прочитать этот пост в блоге
2.основной метод
public static void main(String[] args) {
SpringApplication.run(AppTest.class, args);
}
复制代码
следовать за
Сначала взгляните на статический метод объявления метода, который возвращает объект класса реализации интерфейса ConfigurableApplicationContext.
Вы можете видеть, что существует множество классов реализации и подинтерфейсов, так как же выбрать объект класса реализации? Продолжайте следить за исходным кодом с этим вопросом.
primarySources //主启动类的class对象
args //main方法的启动参数
复制代码
Здесь создается новый экземпляр SpringApplication и вызывается метод запуска
новое приложение Spring ()
Используйте новый метод SpringApplication(primarySources)
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
复制代码
Создайте новый экземпляр SpringApplication. Контекст приложения будет загружать bean-компоненты из указанного основного источника.
Продолжайте следить за методом построения
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;
复制代码
Судя по текущему типу проекта, здесь возвращается WebApplicationType.SERVLET, то есть тип текущего SpringApplication — это веб-приложение, встроенный сервлет веб-сервера.
Затем настройте прослушиватель
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
复制代码
Затем установите запись программы
this.mainApplicationClass = deduceMainApplicationClass()
复制代码
SpringApplication.run()
Далее посмотрим, что делает метод run
StopWatch stopWatch = new StopWatch(); //计时器
stopWatch.start(); //开始计时
复制代码
Установлено системное свойство java.awt.headless.
configureHeadlessProperty()
复制代码
Получите прослушиватель для класса начальной загрузки контекста приложения Spring,
SpringApplicationRunListeners listeners = getRunListeners(args)
复制代码
Следите, чтобы узнать и опубликовать событие ApplicationStartingEvent.
listeners.starting();
复制代码
Инкапсулируйте параметры, необходимые для загрузочного класса SpringApplication.
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
复制代码
Подготовьте среду
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
复制代码
Игнорировать нежелательные bean-компоненты на основе текущей среды
configureIgnoreBeanInfo(environment);
复制代码
распечатать баннер
Banner printedBanner = printBanner(environment)
复制代码
Перед созданием контекста ApplicationContext убедитесь, что тип webApplicationType — SERVLET.
context = createApplicationContext()
复制代码
Возвратите объект байт-кода 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 способов обновить контейнеры Ознакомьтесь с этой записью в блоге
Наконец, остановите таймер и распечатайте журнал
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
复制代码