предисловие
Когда мы используем springboot для сборки проекта, мы иногда сталкиваемся с необходимостью инициализировать некоторые операции при запуске проекта.Для этого требования springboot (spring) предоставляет нам следующие параметры:
-
ApplicationRunner
иCommandLineRunner
интерфейс - InitializingBean, метод init и PostConstruct для инициализации Spring Bean
- Механизм событий Spring
ApplicationRunner и CommandLineRunner
Если нужно вSpringApplication
Чтобы выполнить какой-то специальный код при запуске, вы можете реализоватьApplicationRunner
илиCommandLineRunner
интерфейс,Эти два интерфейса работают одинаково, они предоставляют только один метод запуска, и этот метод вызывается только до завершения SpringApplication.run(...), точнее, когда run() вызывается после создания экземпляра SpringApplication. завершено. Подробный анализ см. ниже., так что здесь они разделены на одну категорию.
ApplicationRunner
Создайте класс для реализации интерфейса ApplicationRunner.
@Component
public class ApplicationRunnerTest implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner");
}
}
Результаты запуска проекта представлены на рисунке:
CommandLineRunner
Для этих двух интерфейсов мы можем указать порядок вызова через аннотацию Order или с помощью интерфейса Ordered,@Order()
Чем меньше значение в , тем выше приоритет
@Component
@Order(1)
public class CommandLineRunnerTest implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...");
}
}
Конечно, мы также можем использоватьApplicationRunner
иCommandLineRunner
, первый по умолчанию выполняется перед вторым, но это не обязательно, просто используйте один
Связь и различие между ними
Как упоминалось ранее, оба интерфейса имеют метод run(), но их параметры различаются. Параметр CommandLineRunner — самый примитивный параметр без какой-либо обработки. Параметр ApplicationRunner — это ApplicationArguments, который является дальнейшим шагом к исходному параметру.
отслеживание источника
Затем мы кратко проследим исходный код, чтобы увидетьApplicationRunner(CommandLineRunner)
Как это называется.
Когда Springboot запустится, он создастSpringApplication
Пример, что касается того, как устроен этот пример, я не буду его здесь рассматривать, если вам интересно, вы можете перейти к исходному коду. В основном здесьApplicationRunner
как называется, и его вызов находится вSpringApplication
Этот экземпляр вызывает метод run.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Введите метод запуска
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}
Выполнить метод запуска SpringApplication
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
Нажмите run() до упора, чтобы прийти сюда
Выяснил, что вызов ApplicationRunner на самом деле находится в методе callRunners Для CommandLineRunner или ApplicationRunner следует отметить два момента.:- Время выполнения всех команд CommandLineRunner/ApplicationRunner начинается после того, как ApplicationContext приложения SpringBoot полностью инициализируется и начинает работать.
callRunners()
Видно, что это последний метод, вызываемый внутри метода run (его можно рассматривать как последний шаг перед выполнением основного метода) - Пока любой CommandLineRunner/ApplicationRunner существует в ApplicationContext текущего приложения SpringBoot, он будет загружен и выполнен (независимо от того, регистрируетесь ли вы вручную или автоматически сканируете в контейнер Ioc)
InitializingBean, метод init и PostConstruct для инициализации Spring Bean
Интерфейс InitializingBean
InitializingBean
интерфейсbean
Предоставляет способ инициализации метода, он включает толькоafterPropertiesSet()
метод.
Когда Spring инициализирует bean-компонент, если bean-компонент реализуетInitializingBean
интерфейс, метод afterPropertiesSet() не будет вызываться до тех пор, пока не будут инициализированы все свойства объекта
@Component
public class InitialingzingBeanTest implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean..");
}
}
Конечно, мы можем видеть, что bean-компонент инициализации spring обязательно будет в Перед вызовом интерфейсов ApplicationRunner и CommandLineRunner.
Конечно, мы должны обратить внимание на то, что хотя использованиеinitialingBean
Интерфейс может реализовать действие инициализации, но официал не рекомендует нам его использоватьInitializingBean
интерфейс, поскольку он связывает ваш код с кодом Spring, официальная рекомендация — указать его в файле конфигурации bean-компонента.init-method
метод или в@Bean
установить вinit-method
Атрибуты
init-метод и @PostConstruct
Как упоминалось ранее, не рекомендуется использовать официальную документацию.InitializingBean
интерфейс, но мы можем<bean>
Атрибут метода init-метода элемента указывает метод работы после инициализации компонентов, либо на указанном методе @postconstruct добавлять аннотации к разработке метода, называемого после инициализации
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@PostConstruct
public void init() {
System.out.println("init...");
}
}
Для получения дополнительной информации о жизненном цикле Spring Bean обратитесь к книгам или блогам, связанным с Spring.Жизненный цикл Spring Bean
Механизм событий Spring
Механизм событий Spring на самом деле является типичным применением шаблона наблюдателя в шаблоне проектирования.Шаблон проектирования Head FirstШаблон наблюдателя определяется следующим образом:
Шаблон Observer определяет зависимость «один ко многим», которая позволяет одному или нескольким объектам-наблюдателям прослушивать объект-субъект. Таким образом, когда состояние наблюдателя изменяется, соответствующие наблюдатели должны быть уведомлены, чтобы эти наблюдатели могли обновляться автоматически.
Базовые концепты
Модель Spring, управляемая событиями, состоит из трех частей.
- событие:
ApplicationEvent
, унаследовано от JDKEventObject
, все события должны наследовать его, т. е. наблюдаемое - Издатель мероприятия:
ApplicationEventPublisher
иApplicationEventMulticaster
Интерфейс, используя этот интерфейс, вы можете публиковать события - Прослушиватель событий:
ApplicationListener
, унаследовано от JDKEventListener
, его наследуют все слушатели, которых мы называем наблюдателями, конечно, мы также можем использовать аннотации@EventListener
, эффект тот же
событие
В среде Spring для событий ApplicationEvent по умолчанию предоставляется следующая поддержка:
- ContextStartedEvent: событие, инициированное после запуска ApplicationContext.
- ContextStoppedEvent: событие запускается после остановки ApplicationContext.
- Событие ContextRefreshedEvent:Событие запускается после завершения инициализации или обновления ApplicationContext; (Вызывается после инициализации контейнера, поэтому мы можем использовать это событие для выполнения некоторых операций инициализации)
- ContextClosedEvent: событие, инициированное после закрытия ApplicationContext (например, когда веб-контейнер закрывается, закрытие контейнера Spring будет автоматически запущено. Если это обычное приложение Java, вам нужно вызвать ctx.registerShutdownHook() ; регистрируем хук при закрытии виртуальной машины)
Создайте класс для наследования ApplicationEvent
public class TestEvent extends ApplicationEvent {
private static final long serialVersionUID = -376299954511699499L;
private String message;
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public TestEvent(Object source) {
super(source);
}
public void getMessage() {
System.out.println(message);
}
public void setMessage(String message) {
this.message = message;
}
}
Создать прослушиватель событий
Существует два способа создания слушателей: один — напрямую реализовать интерфейс ApplicationListener, а другой — использовать аннотации.@EventListener
,Аннотации добавляются в метод слушателя, следующий пример является прямой реализацией интерфейса
@Component
public class ApplicationListenerTest implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent testEvent)
{
testEvent.getMessage();
}
}
выпуск события
Для публикации событий делегатом являетсяApplicationEventPublisher
иApplicationEventMulticaster
, реализация, обеспечиваемая системой, выглядит следующим образом
Ниже приведен тестовый пример издателя событий:
@RunWith(SpringRunner.class)
@SpringBootTest
public class EventTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void publishTest() {
TestEvent testEvent = new TestEvent("");
testEvent.setMessage("hello world");
applicationContext.publishEvent(testEvent);
}
}
//output:
hello world
Используйте событие ContextRefreshedEvent для инициализации
Так много предзнаменований было сделано ранее, давайте перейдем к сегодняшней теме, используем механизм событий Spring для инициализации некоторых операций, на самом деле, как упоминалось ранее, используя механизм событий SpringContextRefreshedEvent
событие инициализировано, событиеApplicationContext
Инициализировать событие, называемое после завершения, мы можем использовать это событие для реализации слушателя, вonApplicationEvent()
Инициализировать операцию в методе
@Component
public class ApplicationListenerTest implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("我被调用了..");
}
}
Уведомление: В традиционном проекте Spring на основе XML конфигурации будет проблема двух вызовов, то есть метод вызывается дважды.Причина в том, что в традиционном проекте Spring MVC в системе два контейнера, корневой контейнер и проект-сервлет Подконтейнер, соответствующий .xml, вызовет этот метод один раз при инициализации двух контейнеров, поэтому возникает проблема вторичного вызова, но эта проблема не существует для проектов на основе Springboot.
резюме
Выше кратко суммированы несколько схем инициализации операций при запуске Springboot, Эти методы могут удовлетворить наши потребности и использовать соответствующие схемы для конкретных сценариев. Однако CommandLineRunner или ApplicationRunner не являются исходными вещами среды Spring.Они относятся к интерфейсам расширений обратного вызова для конкретных приложений SpringBoot, поэтому их легко расширять, и они широко используются в некоторых микросервисных приложениях.