参考:
Spring ApplicationListener:https://blog.csdn.net/liyantianmin/article/details/81017960
Spring Boot 启动事件顺序:https://blog.csdn.net/qq_42948241/article/details/114587189
springboot事件监听器:https://www.jianshu.com/p/3478c9ea16c0
BeanPostProcessor:https://www.jianshu.com/p/369a54201943
使用观察者模式可以实现事件监听。【发布(添加事件监听,触发事件)-订阅(添加事件)】
spring ApplicationListener事件可以自定义、监听也可以自定义,根据业务处理。Spring 内置事件:
| 事件 | 描述 |
|---|---|
| ContextRefreshedEvent | ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用 |
| ContextStartedEvent | 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。 |
| ContextStoppedEvent | 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。 |
| ContextClosedEvent | 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。 |
| RequestHandledEvent | 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。 |
@Component public class TestApplicationListener implements ApplicationListener自定义事件{ @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { System.out.println(contextRefreshedEvent); System.out.println("TestApplicationListener..."); } }
- 1.定义事件:继承ApplicationEvent
public class NotifyEvent extends ApplicationEvent {
private String address;
private String text;
public NotifyEvent(Object source, String address, String text) {
super(source);
this.address = address;
this.text = text;
}
public NotifyEvent(Object source) {
super(source);
}
//setter、getter
}
- 2.定义事件监听器并注册:实现ApplicationListener
@Component public class NotifyEventListener implements ApplicationListener{ @Override public void onApplicationEvent(NotifyEvent event) { if (event instanceof NotifyEvent) { System.out.println("邮件地址:" + event.getAddress()); System.out.println("邮件内容:" + event.getText()); } else { System.out.println("容器本身事件:" + event); } } }
- 3.触发事件,监听器实时监听事件触发,完成业务。
// xml配置
public class SpringTest {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//创建一个ApplicationEvent对象
NotifyEvent event = new NotifyEvent("hello","abc@163.com","This is a test");
//主动触发该事件
context.publishEvent(event);
}
}
// 自动注入
@RunWith(SpringRunner.class)
@SpringBootTest
public class ListenerTest {
@Autowired
private WebApplicationContext context;
@Test
public void testListener() {
NotifyEvent event = new NotifyEvent("object", "abc@qq.com", "This is the content");
context.publishEvent(event);
}
}
springboot
事件与事件监听器
内置事件:不需手动触发事件,springboot启动后会自动触发事件,实现事件监听中业务。
自定义事件:需手动触发事件,实现事件监听器中业务。
内置事件与执行顺序| 顺序 | 事件 | 描述 |
|---|---|---|
| 1 | ApplicationStartingEvent | 这个事件在 Spring Boot 应用运行开始时,且进行任何处理之前发送(除了监听器和初始化器注册之外)。 |
| 2 | ApplicationEnvironmentPreparedEvent | 这个事件在当已知要在上下文中使用 Spring 环境(Environment)时,在 Spring 上下文(context)创建之前发送。 |
| 3 | ApplicationContextInitializedEvent | 这个事件在当 Spring 应用上下文(ApplicationContext)准备好了,并且应用初始化器(ApplicationContextInitializers)已经被调用,在 bean 的定义(bean definitions)被加载之前发送。 |
| 4 | ApplicationPreparedEvent | 这个事件是在 Spring 上下文(context)刷新之前,且在 bean 的定义(bean definitions)被加载之后发送。 |
| 5 | ApplicationStartedEvent | 这个事件是在 Spring 上下文(context)刷新之后,且在 application/ command-line runners 被调用之前发送。 |
| 6 | AvailabilityChangeEvent | 这个事件紧随上个事件之后发送,状态:ReadinessState.CORRECT,表示应用已处于活动状态。 |
| 7 | ApplicationReadyEvent | 这个事件在任何 application/ command-line runners 调用之后发送。 |
| 8 | AvailabilityChangeEvent | 这个事件紧随上个事件之后发送,状态:ReadinessState.ACCEPTING_TRAFFIC,表示应用可以开始准备接收请求了。 |
| 9 | ApplicationFailedEvent | 这个事件在应用启动异常时进行发送。 |
定义内置事件可以通过@Order()指定监听器顺序
- 自定义内置事件监听器
public class EnvironmentPreparedListener implements ApplicationListener{ public EnvironmentPreparedListener() {} @Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { System.out.println("EnvironmentPreparedListener..."); } }
- 注册事件监听器
@SpringBootApplication
public class MySpringbootApplication {
public static void main(String[] args) {
// SpringApplication.run(MySpringbootApplication.class, args);
SpringApplication sa = new SpringApplication(MySpringbootApplication.class);
// 添加事件监听
sa.addListeners(new EnvironmentPreparedListener());
ConfigurableApplicationContext caContext = sa.run(args);
}
}
自定义事件
定义事件
public class NotifyEvent extends ApplicationEvent {
private String address;
private String text;
public NotifyEvent(Object source, String address, String text) {
super(source);
this.address = address;
this.text = text;
}
public NotifyEvent(Object source) {
super(source);
}
//setter、getter
}
定义监听器
public class NotifyEventListener implements ApplicationListener{ @Override public void onApplicationEvent(NotifyEvent event) { if (event instanceof NotifyEvent) { System.out.println("邮件地址:" + event.getAddress()); System.out.println("邮件内容:" + event.getText()); } else { System.out.println("容器本身事件:" + event); } } }
注册监听器并手动触发事件
@SpringBootApplication
public class MySpringbootApplication {
public static void main(String[] args) {
// SpringApplication.run(MySpringbootApplication.class, args);
SpringApplication sa = new SpringApplication(MySpringbootApplication.class);
// 手动注册事件器
sa.addListeners(new NotifyEventListener());
ApplicationContext context = sa.run(args);
// 发布事件
NotifyEvent notifyEvent = new NotifyEvent("nortifyEvent", "localhost", "hello xiaoai");
context.publishEvent(notifyEvent);
}
}
事件监听器注册方式
- 1、@Component + 实现ApplicationListener<>接口
@Component public class NotifyEventListener implements ApplicationListener{ @Override public void onApplicationEvent(NotifyEvent event) { if (event instanceof NotifyEvent) { System.out.println("邮件地址:" + event.getAddress()); System.out.println("邮件内容:" + event.getText()); } else { System.out.println("容器本身事件:" + event); } } }
- 2、@Component + @EventListener
@Component
public class EventListner {
@EventListener
public void evendListener(NotifyEvent event){
if (event instanceof NotifyEvent) {
System.out.println("邮件地址:" + event.getAddress());
System.out.println("邮件内容:" + event.getText());
} else {
System.out.println("容器本身事件:" + event);
}
}
}
- 3、配置文件注册
context:
listener:
classes: com.xiaoai.my_springboot.event.NotifyEventListener
- 4、启动类手动注册
public static void main(String[] args) {
// SpringApplication.run(MySpringbootApplication.class, args);
SpringApplication sa = new SpringApplication(MySpringbootApplication.class);
// 注册事件监听器器
sa.addListeners(new NotifyEventListener());
ApplicationContext context = sa.run(args);
// 发布事件
NotifyEvent notifyEvent = new NotifyEvent("nortifyEvent", "localhost", "hello xiaoai");
notifyEvent.getAddress();
context.publishEvent(notifyEvent);
}
- 5、spring.factories机制注入
# resources目录下新建一个meta-INF 的目录,目录下新建一个spring.factories的文件,里面的内容为: org.springframework.context.ApplicationListener=com.xiaoai.my_springboot.event.NotifyEventListener
- 6、多事件监听:@Component + 实现 SmartApplicationListener接口
@Order(1)
@Component
public class SmartListenerTest implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class extends ApplicationEvent> eventType){
//这里是类型判断,判断监听器感兴趣的事件
//可以对多个事件感兴趣,这里就配置了两个事件
return ApplicationStartedEvent.class.isAssignableFrom(eventType)
|| NotifyEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent appEvent) {
if (appEvent instanceof ApplicationStartedEvent){
System.out.println("applicationStartedEvent...");
}
if (appEvent instanceof NotifyEvent) {
NotifyEvent event = (NotifyEvent) appEvent;
System.out.println("邮件地址:" + event.getAddress());
System.out.println("邮件内容:" + event.getText());
} else {
System.out.println("容器本身事件:" + appEvent);
}
}
}
自动执行任务
ApplicationRunner
@Component
public class StartTask2 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("-----ApplicationRunner:springboot start......");
}
}
CommandLineRunner
@Component
public class StartTask implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("-----CommandLineRunner:springboot start......");
}
}
修饰方法相关注解
-
@PostConstruct
-
@PreDestroy
@Component
public class TestClass {
// 当bean创建完成加载时执行
@PostConstruct
public String init(){
System.out.println("-----@PostConstruct:TestClass method 【init】 is run.....");
return "hello";
}
// 关闭前执行
@PreDestroy
public void destroyPro(){
System.out.println("-----@PreDestroy:TestClass method 【destroyPro】 is run.....");
}
}
BeanPostProcessor
运行顺序:
- Spring IOC容器实例化Bean
- 调用BeanPostProcessor的postProcessBeforeInitialization方法
- 调用bean实例的初始化方法
- 调用BeanPostProcessor的postProcessAfterInitialization方法
@Component
public class StartTask3 implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 可以根据不同的bean执行不同的操作
if (beanName.equalsIgnoreCase("eventListner")){
System.out.println("postProcessBeforeInitialization()..." + beanName + "=>" + bean);
System.out.println("eventListner is loading...");
}
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equalsIgnoreCase("eventListner")){
System.out.println("postProcessAfterInitialization()..." + beanName + "=>" + bean);
System.out.println("eventListner is loaded...");
}
return null;
}
}
BeanFactoryPostProcessor
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
int count = beanFactory.getBeanDefinitionCount();
String[] names = beanFactory.getBeanDefinitionNames();
System.out.println("当前BeanFactory中有【" + count + "】个Bean");
// System.out.println(Arrays.asList(names));
}
}



