基于Springboot的观察者模式实现
业务上很多地方可以用到观察者模式,于是写了个通用的模板,实现如下:
抽象层
/**
* @Author
* @Description 观察者
* @CreateTime 2021年10月21日 09:22:00
*/
public interface Observer {
@Async
void notify(Field field, Object oldVal, Object newVal);
}
/**
* @Author
* @Description 被观察者
* @CreateTime 2021年10月21日 09:21:00
*/
public abstract class Subject {
/**
* 观察者列表
*/
private volatile List<Observer> observers;
public void notifyAllObserver(Field field, Object oldVal, Object newVal) {
initObservers();
if (CollectionUtils.isNotEmpty(observers)) {
observers.forEach(observer -> {
observer.notify(field, oldVal, newVal);
});
}
}
private void initObservers() {
if (Objects.nonNull(observers)) {
return;
}
Map<String, Observer> observerMap = SpringContextUtil.getBeans(Observer.class);
if (MapUtils.isNotEmpty(observerMap)) {
observers = new LinkedList<>(observerMap.values());
}
}
public void addObservers(Observer observer) {
if (Objects.isNull(observers)) {
observers = new LinkedList<>();
}
observers.add(observer);
}
}
实现
/**
* @Author
* @Description 被观察对象
* @CreateTime 2021年10月21日 09:43:00
*/
public class DemoEO extends Subject {
private String name;
private int status;
public DemoEO() {
}
public DemoEO(String name, int status) {
this.name = name;
this.status = status;
}
public String getName() {
return name;
}
public void setName(String name) throws NoSuchFieldException {
notifyAllObserver(this.getClass().getDeclaredField("name"), this.name, name);
this.name = name;
}
public int getStatus() {
return status;
}
public void setStatus(int status) throws NoSuchFieldException {
notifyAllObserver(this.getClass().getDeclaredField("status"), this.status, status);
this.status = status;
}
}
/**
* @Author
* @Description 姓名监听
* @CreateTime 2021年10月21日 10:12:00
*/
@Slf4j
@Component
public class NameObserver implements Observer {
@Override
public void notify(Field field, Object oldVal, Object newVal) {
if ("name".equals(field.getName())) {
log.info("姓名 从 {} 被修改为 {}", oldVal, newVal);
} else {
log.info("和我无关!");
}
}
}
/**
* @Author
* @Description 状态监听
* @CreateTime 2021年10月21日 10:04:00
*/
@Slf4j
@Component
public class StatusObserver implements Observer {
@Override
public void notify(Field field, Object oldVal, Object newVal) {
if ("status".equals(field.getName())) {
log.info("状态 从 {} 被修改为 {}", oldVal, newVal);
} else {
log.info("和我无关!");
}
}
}
测试
/**
* @Author
* @Description 被观察者业务类
* @CreateTime 2021年10月21日 10:14:00
*/
@Service
public class DemoService {
public boolean updateDemoEo(int status, String name) throws NoSuchFieldException {
DemoEO demoEO = new DemoEO("二哈", 0);
demoEO.setStatus(status);
demoEO.setName(name);
return true;
}
}
结果
这样Observer的实现类和被观察者DemoEO之间完全解耦,没有依赖。
工具类补充
Spring的ApplicationContext 抽出来作为工具类,会非常方便:
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name){
return (T) applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> classzz) {
return applicationContext.getBean(classzz);
}
public static <T> Map<String, T> getBeans(Class<T> classzz) {
return applicationContext.getBeansOfType(classzz);
}
}