最近项目用到了observer观察者模式:
event,listener是observer模式一种体现,这里我们介绍ApplicationEvent的使用。
一.PropertyAddedEvent继承ApplicationEvent
二.监听类PropertyEventHandler
BookingEventsListener 需要实现ApplicationListener 并重写onApplicationEvent方法***。ApplicationListener带泛型,如果泛型参数为BookingCreatedEvent,则表示只监听BookingCreatedEvent类型的事件,如果泛型参数为ApplicationEvent ,则表示监听所有类型的事件。***另外可以用@Component来注册组件,这样就不需要在spring的配置文件中指定了。
触发要实现ApplicationContextAware,用于引入ApplicationContext,由于bookingService也 是spring组件,所以在系统启动的时候,ApplicationContext已经注入。也可以用如下方式直接注入 ApplicationContext。
三.触发event
原理:
首先说说spring的IOC容器初始化过程,首先Spring会定位BeanDefinition资源文件,然后会一个一个的去加载所有BeanDefinition,这里的BeanDefinition就是指的Bean的资源文件,即:在XML中配置的Bean和通过注解装配的Bean,在加载完所有BeanDefinition之后,会将这些BeanDefinition注册到一个HashMap中。到此spring的IOC初始化完成,那么依赖注入发生在哪里呢?在用户第一次向IOC容器索要Bean时才开始依赖注入过程(也可以通过配置lazy-init属性让容器初始化的时候就对Bean预实例化)
可以看到在Bean所有的属性都被注入之后会去调用这个afterPropertiesSet()方法,其实在依赖注入完成的时候,spring会去检查这个类是否实现了InitializingBean接口,如果实现了InitializingBean接口,就会去调用这个类的afterPropertiesSet()方法。所以afterPropertiesSet()方法的执行时间点就很清楚了,发生在所有的properties被注入后。
package com.purcotton.omni.download.config;
import com.purcotton.omni.download.core.OrderType;
import com.purcotton.omni.download.core.PageSynchronizer;
import com.purcotton.omni.download.core.StreamSynchronizer;
import com.purcotton.omni.sync.SyncProperty;
import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;
import static org.springframework.util.ObjectUtils.isEmpty;
@Component
public class PropertyEventHandler implements ApplicationContextAware, ApplicationListener<PropertyAddedEvent> {
private GenericApplicationContext applicationContext;
@Override
public void onApplicationEvent(PropertyAddedEvent event) {
SyncProperty property = (SyncProperty) event.getSource();
String beanName = property.getId() + "Synchronizer";
BeanDefinitionBuilder builder;
if (property.getVersion() >= 2.0) {
builder = BeanDefinitionBuilder
.genericBeanDefinition(property.getPullStrategy().equalsIgnoreCase("page") ?
PageSynchronizer.class : StreamSynchronizer.class)
.addConstructorArgValue(property)
.addPropertyReference("formatter", "formatter")
.addPropertyReference("scheduleMapper", "syncScheduleMapper")
.addPropertyReference("errorMapper", "syncErrorMapper")
.addPropertyReference("restTemplate", property.isLoadBalanced()
? "loadBalancedRestTemplate" : "sslRestTemplate")
.addPropertyReference("dataStorage",
isEmpty(property.getStorageService()) ? "mapDataStorage" : "codeDataStorage");
} else {
builder = BeanDefinitionBuilder
.genericBeanDefinition(getBeanClass(property));
if (!isEmpty(property.getType())) {
builder.addConstructorArgValue(OrderType.valueOf(property.getType()));
}
if (!isEmpty(property.getShopCode())) {
builder.addConstructorArgValue(property.getShopCode());
}
}
synchronized (this) {
if (!applicationContext.isBeanNameInUse(beanName)) {
applicationContext.registerBeanDefinition(beanName, builder.getBeanDefinition());
}
}
}
@SneakyThrows
private Class<?> getBeanClass(SyncProperty property) {
String packageName = "com.purcotton.omni.download.core.page";
String channel = property.getChannel().toLowerCase();
String className = channel.substring(0, 1).toUpperCase()
+ channel.substring(1) + "Synchronizer";
return Class.forName(packageName + "." + className);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = (GenericApplicationContext) applicationContext;
}
}
来源:CSDN
作者:runoob12
链接:https://blog.csdn.net/runoob12/article/details/104406780