我正在尝试实现解析器模式(策略模式)。
所以我有一个自定义注释@PaymentTypeValue
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface PaymentTypeValue {
PaymentType[] value();
}
和PaymentType
作为枚举类
public enum PaymentType{
CASH, CARD, NET_BANKING, UPI, WALLET;
}
现在我有接口PaymentService
public interface PaymentService {
void process();
}
有5个实现,其中一个是
@Service
@PaymentTypeValue({PaymentTypeValue.CASH})
public class CashPaymentService implements PaymentService {
@Override
void process(){
//some logic
}
}
我有解析器是这样的
@Component
public class PaymentServiceResolver {
private static final Logger log = getLogger(PaymentServiceResolver.class);
@Autowired
private List<PaymentService> paymentServices;
private final Map<PaymentType, PaymentService> paymentServiceMap = new EnumMap<>(PaymentType.class);
@PostConstruct
public void init() {
paymentServices.forEach(paymentService -> {
PaymentTypeValue annotation = paymentService.getClass().getAnnotation(PaymentTypeValue.class);
if (annotation != null && annotation.value() != null) {
PaymentType[] paymentTypes = annotation.value();
Arrays.stream(paymentTypes).forEach(paymentType -> {
paymentServiceMap.put(paymentType, paymentService);
});
} else {
log.error("paymentService {} is missing a necessary annotation",
paymentService.getClass().getName());
log.error("This paymentService cannot be initialized");
// throw new IllegalStateException("paymentService is missing a necessary annotation for " + paymentService.getClass().getName());
}
}
);
}
public PaymentService resolvePaymentService(PaymentType paymentType) {
PaymentService paymentService = paymentServiceMap.get(paymentType);
if (paymentService != null) {
return paymentService;
} else {
String message = "Could not find paymentService for " + paymentType;
log.error(message);
throw new RuntimeException(message);
}
}
}
现在问题出在init()方法中,PaymentService
的所有服务实现都出现在列表中,但当我试图查找注释时,它的值为null。我检查了paymentService的值。getClass()
方法,其中annotationData有0个注释。如果我自动连接PaymentService的任何特定实现,那么我就能够获得注释值。请帮我理解我错过了什么?
注释方法使事情变得复杂,我会尽量避免。一个没有注释的更简单的解决方案,假设PaymentType
和服务实现之间有1:1的映射:
boolean canHandle(PaymentType)
。接口:
public interface PaymentService {
boolean canHandle(PaymentType paymentType);
void process();
}
服务实施:
@Service
public class CashPaymentService implements PaymentService {
@Override
public boolean canHandle(PaymentType paymentType) {
return PaymentType.CASH.equals(paymentType);
}
@Override
public void process() {
// processing...
}
}
服务定位器:
@Component
public class PaymentServiceResolver {
private final List<PaymentService> paymentServices;
private final Map<PaymentType,PaymentService> serviceMapping = new ConcurrentHashMap<>(5);
@Autowired
public PaymentServiceResolver(List<PaymentService> paymentServices) {
this.paymentServices = paymentServices;
}
public PaymentService resolve(PaymentType paymentType) {
return serviceMapping.computeIfAbsent(paymentType, resolveInternal());
}
private Function<PaymentType, PaymentService> resolveInternal() {
return paymentType ->
paymentServices.stream()
.filter(service -> service.canHandle(paymentType))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Unsupported payment type: " + paymentType));
}
}
您可以向解析器添加更多验证逻辑,以在Spring的初始化阶段检查每个PaymentType
是否有可用的实现。
问题内容: 在阅读有关标记接口的信息时,我偶然发现了以下站点:项目37:使用标记接口定义类型 在这里,根据Joshua Bloch的说法,标记接口比标记注释有两个优点。 1. 标记接口定义了一种由标记的类的实例实现的类型。标记注释没有。这种类型的存在使您可以在编译时捕获错误,而如果使用标记注释,则这些错误在运行时才捕获。 2. 标记接口相对于标记注释的另一个优点是可以更精确地定位它们。如果使用ta
在阅读有关标记接口的内容时,我偶然发现了以下网站:第37项:使用标记接口定义类型 根据Joshua Bloch的说法,标记接口比标记注释有两个优点。 > 标记接口定义由标记类的实例实现的类型;标记注释没有。这种类型的存在允许您在编译时捕获错误,如果您使用标记注释,则直到运行时才能捕获这些错误。 与标记注释相比,标记接口的另一个优点是可以更精确地定位它们。如果使用target,它可以应用于任何类或接
我有一个简单的类叫BeaconDao 然而,当我用@service或@component标记beaconDao时,一切都运行得非常好。有人能看出问题所在吗?
我正在尝试构建一个aar,以便在jcenter上发布。 assembleRelease任务工作正常,javadoc任务也工作正常,但javadocJar任务输出以下错误: /Users/martinmoreno/Projects/android-dev-utils/dev-utils/src/main/java/com/tinchoapps/devutils/BitmapUtils.java:11
问题内容: 运行我的Android应用程序时出现此错误: 在类[[Lmodel.Vak;中,没有字段具有DatabaseField注释。 我的班级Vak有注解,所以我真的不明白为什么它仍然给我这个错误。 我有一个名为Databasehelper.java的文件,在其中扩展了OrmLiteSqLiteOpenHelper,该文件如下所示: 我还有一个扩展OrmLiteBaseActivity的文件控
我从micronaut下载。lanch是一个简单的grpc项目,在添加Kotlin grpc插件之前,我可以构建它。 除了build.gradle.kts的变化,没有什么比原来的脚手架项目。 我在build.gradle.kts.编辑 首先,为了匹配IntelliJ Kotlin版本 其次,为kotlin grpc proto自动生成的文件添加了文件夹 而最后 从INtelliJ或straigh命