Мы щелкали слой за слоем и, наконец, обнаружили, что этот метод был выполнен.
Итак, когда мы запускаем проект, мы также можем запустить его вот так new SpringApplication(SpringbootExtensionPointApplication.class).run(args);
Старый просто оборачивает статический метод. Фактический нижний уровень предназначен для создания экземпляра объекта SpringApplication и последующего вызова его метода запуска.
Давайте перейдем к методу построения и посмотрим. Один из них, отмеченный красным прямоугольником, предназначен для установки инициализатора, а другой — для установки прослушивателя.
Щелкните и посмотрите. Два базовых метода одинаковы: передать тип и найти класс реализации этого типа через Spring SPI.
Создайте точку останова и запустите ее. На данный момент имеется 7 инициализаторов контекста, которые поставляются с системой и настраиваются в разных файлах Spring.factories.
Теперь я хочу создать новый собственный инициализатор
Что мне теперь делать, чтобы позволить Spring Boot сканировать созданный мной инициализатор при его запуске? Просто добавьте его в файл Spring.factories и зарегистрируйте, чтобы его можно было сканировать. Это SPI. SPI означает интерфейс поставщика услуг, который представляет собой механизм обнаружения служб.
Тогда давайте начнем весну снова в это время Boot,Нашел то, что создалApplicationContextInitializer
Уже зарегистрирован,Стало 8.
Освободите точку останова,Это предложение также выводится в консоли,Тогда это первая точка расширенияApplicationContextInitializer
Эти 8 инициализаторов определены, значит должно быть где-то их настроить, иначе как их можно было распечатать Так где же именно они настраиваются? Разбиваем точку на собственном инициализаторе и видим, что она зашла., а потом смотрим? в информации о стеке ниже, именно здесь выполняется вызов.
Оказывается, это называлосьrun()
метод中изprepareContext()
метод中изapplyInitializers()
метод,существовать这个метод中for循环из调用各个初始化器изinitialize()
метод,Таким образом, мы можем увидетьJackизApplicationContextInitializer
Это предложение было распечатано。
Тогда этот метод поиска заключается в обратном поиске вызывающего абонента с ориентацией на результат, потому что, если вы ищете, его трудно найти и запомнить, я надеюсь, что каждый сможет изучить этот метод.
Итак, наконец, давайте посмотрим на расположение нашей первой точки расширения.
Инициализатор может выполнять некоторые действия, например устанавливать некоторые конфигурации переменных для объекта Environment.
В приведенном выше конструкторе мы обнаружили, что помимо setInitializers есть еще setListeners, поэтому этот прослушиватель на самом деле является точкой расширения.
Так что же такое слушатель?,Вот и все,На самом деле это режим наблюдателя,ApplicationEventMulticaster
выпускатьсобытие,Каждый слушатель отслеживает событие.
Как и инициализатор, теперь мы настраиваем два прослушивателя, один — Starting, а другой — Started. Тот, что в скобках, — общий. Если не написано, независимо от типа события, он будет слушать.
Этот универсальный вариант представляет собой событие, верхний предел которого — тип ApplicationEvent. Существует множество конкретных классов реализации, и Starting и Started — лишь два из них.
Теперь мы еще добавляем эти два слушателя в конфигурацию через SPI.
Хорошо, давайте запустим. Мы видим, что эти два предложения были напечатаны.
То же, что слушатель,Поскольку его можно распечатать,Должно быть, кто-то звонит,так что мыJackStartingApplicationListener
Сделать точку останова,Затем посмотрите информацию о стеке
мы можем увидеть вSpringApplication run()
методизlisteners.starting()
Начать отправкуApplicationStartingEvent
транслироватьсобытие,Наконец опубликуйте это,Получено нашим прослушивателем событий.
ТакApplicationStartedEvent
событие也是一样из道理,Найдите вызывающего абонента через точки останова,Наконец, давайте сейчас посмотрим на диаграмму точек расширения.
мы видим вlisteners.started()
Есть один позадиcallRunners
Давайте нажмем и посмотрим,На самом деле он получает два типа Runner из контейнера.,Один из нихApplicationRunner
,Еще одинCommandLineRunner
,Затем вызовите их в цикле for,Так что на самом деле это тоже точка расширения
Давайте напишем наш собственный Runner
Запустите его и посмотрите, что напечатает.
Тогда общий сценарий применения этого Runner — это освобождение и очистка ресурсов или центр регистрации, поскольку проект запускается при выполнении Runner, и в это время его можно зарегистрировать в центре регистрации. На этом этапе давайте еще раз посмотрим на диаграмму точек расширения.
Давайте посмотримrunметод里изrefreshContext()
метод
这个метод底层会调spring里面изrefresh()
метод,这个метод里面就会做对контейнериз初始化。红框里изinvokeBeanFactoryPostProcessors()
метод,Здесь также есть точка расширения,то естьBeanFactoryPostProcessor
,ВыполнятьBeanFactoryиз后置处理。Spring Bootанализировать КонфигурациястановитьсяBeanDefinition
из操作也是существовать此метод中。
现существовать我们来创建一个自己изBeanFactoryPostProcessor
,В этом методе вы можете изменить свойства beanFactory.,beanfactoryЕстьBeanDefinition
,Может быть измененBeanDefinition
里面из值。BeanDefinition
этоbeanиз元数据из信息,Сколько ихbean就Сколько ихBeanDefinition
。
Запустите его, и он также будет распечатан.
На этом этапе мы снова смотрим на диаграмму точек расширения, которая становится все более совершенной.
最后介绍из是BeanPostProcessor
,Он выполняется после создания экземпляра компонента через отражающий конструктор.,Так红框里面标出来изregisterBeanPostProcessors()
методто есть向BeanFactory
Зарегистрируйтесь вbeanpostprocessor
,Операции перехвата, используемые для последующего создания компонента.
现существовать我们来创建一个自己изBeanPostProcessor
,Всего есть два метода,postProcessBeforeInitialization
иpostProcessAfterInitialization
,Но мы обычно используемpostProcessAfterInitialization
,существоватьbeanВыполняется после вызова отражающего конструктора и создания его экземпляра.。著名из应用场景AOP底层то есть通过BeanPostProcessor
来实现из。
现существовать我существоватьpostProcessAfterInitialization
上Сделать точку останова,Посмотрите, где вызывается информация стека.
是существоватьfinishBeanFactoryInitialization()
метод处调用из
Наконец, я дополню диаграмму точек расширения, как показано ниже. Она очень ясна и понятна. Что называется когда? Когда мы сами ее разрабатываем, мы объединяем сценарии приложения и знаем, какой тип точки расширения создавать, когда нам нужно. сделать что-нибудь.
Первые три этой статьи рассказывают о точках расширения в Spring Boot. Последние две — это точки расширения в Spring, потому что нижний уровень Spring Boot — это исходный код Spring, поэтому они являются точками расширения в Spring. таким образом, в Spring все еще есть точки расширения. Многие точки расширения, такие как InitializeBean, Aware и т. д., здесь не упоминаются, ожидая, пока все обнаружат ~.