最近设计一个对外接口调用失败重试补推功能,由于对于不少接口的调用我准备采起策略模式去实现。思考了下,若是使用普通的策略模式,一个接口对应对个实现类,若是多一个类型的接口,那么就会多一个实现类,决定使用枚举策略模式。java
调用接口失败,将失败的调用的url,param,method等信息做为一条记录存入数据库中spring
public class HttpFailEntity {
.
.
.
private Integer apiType;
private String url;
private String param;
.
.
.
}
复制代码
经过定时器从库中获取调用外部接口失败的数据数据库
List<HttpFailEntity> httpFailEntities;
//补推
httpFailEntities.forEach(httpFailEntity -> {
PushHttpFailEnum.valueOf(httpFailEntity.getApiType()).push(httpFailEntity);
});
复制代码
使用枚举策略处理,避免多一个接口处理,新增一个实现类api
public enum PushHttpFailEnum {
/** * id -> 业务接口 */
ONE(1, "A接口") {
private XXXXService xxxxService = SpringContextHolder.getBean(XXXXService.class);
@Override
public Map<String, Object> push(HttpFailEntity httpFailEntity) {
// 补推操做
xxxxService.XXXX();
}
},
TWO(2, "B接口") {
@Override
public Map<String, Object> push(HttpFailEntity httpFailEntity) {
// 补推操做
}
},
.
.
.
OTHER(9999, "") {
@Override
public Map<String, Object> push(HttpFailEntity httpFailEntity) {
return null;
}
};
/** * 补推 * * @param httpFailEntity http推送失败类 */
public abstract Map<String, Object> push(HttpFailEntity httpFailEntity);
/** * 状态值 */
@Getter
private int value;
/** * 状态表述 */
@Getter
private String desc;
PushHttpFailEnum(int value, String desc) {
this.value = value;
this.desc = desc;
}
public static PushHttpFailEnum valueOf(int value) {
return Arrays.stream(PushHttpFailEnum.values())
.filter(a -> a.getValue() == value)
.findFirst().orElse(PushHttpFailEnum.ERROR);
}
}
复制代码
在A接口的实现抽象方法中使用到 spring 容器中的Service类,一开始使用注解形式,运行得时候都是nullapp
@Resource
private XXXXService xxxxService;
复制代码
后来发现枚举类里面实现的抽象方法,本质就是匿名内部类,spring容器根本没法扫描到,因此也就没法把对象注入。最后使用SpringContextHolder的静态方法从spring容器中拿到对应的对象。ide
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextHolder.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
assertApplicationContext();
return applicationContext;
}
public static <T> T getBean(String beanName) {
assertApplicationContext();
return (T) applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> requiredType) {
assertApplicationContext();
return applicationContext.getBean(requiredType);
}
private static void assertApplicationContext() {
if (SpringContextHolder.applicationContext == null) {
throw new RuntimeException("ApplicationContext属性为null,请检查是否注入了SpringContextHolder!");
}
}
}
复制代码