假设我有一个类RecordSender
,其构造函数采用目标名称。为了对这个类进行CDI化,我可能会写一个像这样的生产者,该生产者检查注入点以找到一个名为Topic
的注释(不是限定符,因为不能用所有可能的主题名称值来注释生产方法。它可能会产生):
@Produces
public RecordSender getRecordSender(InjectionPoint injectionPoint) {
return new RecordSender(injectionPoint.getAnnotated().getAnnotation(Topic.class).value());
}
但是,假设这个RecordSender
类非常繁重但具有线程安全性,因此应尽可能多地共享。这意味着我希望任何看起来像@Inject @Topic("FooBar") RecordSender fooBarSender
的注入站点共享以FooBar为名称构造的RecordSender
实例。
我们不能将生产者方法标记为ApplicationScoped,因为RecordSenders只能在具有相同名称的注入点之间共享。我们不能将@Topic设置为限定符,因为此限定符不会注释生产者方法。解决此问题的CDI方法是什么?
我的愿景是添加一个范围注释(可能是ScopedTo),它的参数是一个非限定符注释类,它将强制分离它们所注释的bean的范围。因此,例如,生产者方法上的@ApplicationScoped @ScopedTo(Topic.class)
就是我的问题的答案(每个应用程序每个唯一的Topic注释一个RecordSender)
答案 0 :(得分:0)
另一种方法是编写一个可移植的扩展程序,该扩展程序对相关的注入点进行扫描和分类,然后在观察器AfterBeanDiscovery
的观察器方法中,ApplicationScoped
范围内的programmatically adds beans相关的注射点类别。这样一来,您就不必在生产者方法中进行动态InjectionPoint
选择了。
答案 1 :(得分:0)
最好的方法可能是走扩展路线。
但是,另一种更简单的方法可能是将生产者放在应用程序范围的Bean中。该bean可能包含某种缓存(值较小的映射可能会完成此任务)。这样,如果给定类型已经存在,则可以返回缓存的版本,否则在从生产者返回之前创建新的对象和缓存。该键可以从您的主题注释中提取。如果这是一个限定词,则可以将topic属性标记为非绑定。