一.目录
观察者模式,大体执行路径:
二.spring原生配置
PropertyEventHandler
package com.purcotton.omni.download.config;
import com.google.common.base.CaseFormat;
import com.purcotton.omni.download.core.OrderType;
import com.purcotton.omni.download.core.page.TbSynchronizer;
import com.purcotton.omni.sync.SyncProperty;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
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 org.springframework.util.ObjectUtils;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*1.从ApplicationContextAware获取ApplicationContext上下文的情况,
*仅仅适用于当前运行的代码和已启动的Spring代码处于同一个Spring上下文,否则获取到的ApplicationContext是空的。
*
* 2.PropertyEventHandler 需要实现ApplicationListener 并重写onApplicationEvent方法。
* ApplicationListener带泛型 PropertyAddedEvent,则表示只监听PropertyAddedEvent类型的事件,
* 如果泛型参数为ApplicationEvent ,则表示监听所有类型的事件。
* 另外可以用@Component来注册组件,这样就不需要在spring的配置文件中指定了。
*
* 3.触发要实现ApplicationContextAware,用于引入ApplicationContext。
*
*/
@Component
public class PropertyEventHandler implements ApplicationContextAware, ApplicationListener<PropertyAddedEvent> {
private GenericApplicationContext applicationContext;
/*
从SynchronizerConfiguration.afterPropertiesSet拿到淘宝的配置以后,生成对应的bean
*/
@Override
public void onApplicationEvent(PropertyAddedEvent event) {
SyncProperty property = (SyncProperty) event.getSource();
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(TbSynchronizer.class)
.addConstructorArgValue(OrderType.valueOf(property.getType()))
.addConstructorArgValue(property.getShopCode());
BeanDefinition beanDefinition = builder.getBeanDefinition();
String beanName = getBeanName(property.getChannel(), property.getType(), property.getShopCode());
synchronized (this) {
if (!applicationContext.isBeanNameInUse(beanName)) {
applicationContext.registerBeanDefinition(beanName, beanDefinition);
}
}
}
/*
生成bean的名字
*/
private String getBeanName(String orderChannel, String orderType, String shopCode) {
// CaseFormat是一种实用工具类,以提供不同的ASCII字符格式之间的转换。
// UPPER_CAMEL,即我们常说的"驼峰式"编写方式;其次,我们常用的是:UPPER_UNDERSCORE,即我们常用的常量命名法
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,
Stream.of(orderChannel, orderType, shopCode) //返回含有多个T元素的Stream
.filter(value -> !ObjectUtils.isEmpty(value)) //过滤为空的数据
.collect(Collectors.joining("_"))) //转为一个string 用_连接
+ "Synchronizer";
}
/*
获取容器的上下文 applicationContext
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = (GenericApplicationContext) applicationContext;
}
}
SynchronizerConfiguration
package com.purcotton.omni.download.config;
import com.purcotton.omni.download.core.OrderChannel;
import com.purcotton.omni.download.core.OrderType;
import com.purcotton.omni.download.core.page.MpcSynchronizer;
import com.purcotton.omni.order.entity.OrderPureh2bTrade;
import com.purcotton.omni.salesreturn.entity.OrderPureh2bReturnTrade;
import com.purcotton.omni.sync.SyncProperty;
import com.purcotton.omni.sync.mapper.SyncPropertyMapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import java.util.List;
/*
InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,
凡是继承该接口的类,在初始化bean的时候都会执行该方法。
*/
@Configuration
public class SynchronizerConfiguration implements ApplicationContextAware, InitializingBean {
private final SyncPropertyMapper propertyMapper;
private GenericApplicationContext applicationContext;
public SynchronizerConfiguration(SyncPropertyMapper propertyMapper) {
this.propertyMapper = propertyMapper;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = (GenericApplicationContext) applicationContext;
}
/*
* 它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。
*/
@Override
public void afterPropertiesSet() {
// 初始化bean的时候加载淘宝
List<SyncProperty> properties = propertyMapper.findProperties(OrderChannel.TB.name());
for (SyncProperty property : properties) {
/*
applicationContext.publishEvent 发布一个(加载淘宝配置)事件,然后被上面的
PropertyEventHandler 类捕获传入 onApplicationEvent 方法
*/
applicationContext.publishEvent(new PropertyAddedEvent(property));
}
}
@Bean
public MpcSynchronizer<OrderPureh2bTrade> mpcTradeSynchronizer() {
return new MpcSynchronizer<>(OrderType.TRADE);
}
@Bean
public MpcSynchronizer<OrderPureh2bReturnTrade> mpcRefundSynchronizer() {
return new MpcSynchronizer<>(OrderType.REFUND);
}
}