gpt4 book ai didi

java - CDI - 应用程序范围但已配置

转载 作者:行者123 更新时间:2023-12-01 21:45:21 24 4
gpt4 key购买 nike

问题

使用 CDI 我想生成 @ApplicationScoped bean 。

此外,我想为注入(inject)点提供配置注释,例如:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Configuration {

String value();

}

我不想为value的每种不同可能性编写一个单独的生产者。 。

<小时/>

方法

通常的方法是创建一个生产者并处理注入(inject)点注释:

@Produces
public Object create(InjectionPoint injectionPoint) {
Configuration annotation = injectionPoint.getAnnotated().getAnnotation(Configuration .class);
...
}

因此,bean 不能再处于应用程序范围内,因为每个注入(inject)点可能不同(生产者的参数注入(inject)点不适用于 @AplicationScoped 带注释的生产者)。

所以这个解决方案不起作用。

<小时/>

问题

我需要具有相同值的注入(inject)点获得相同 bean 实例的可能性。

有内置的CDI方式吗?或者我是否需要以某种方式“记住”列表中的 bean ,例如在包含生产者的类中?

我需要的基本上是一个 ApplicationScoped每个不同的实例 value .

最佳答案

您想要实现的并不是 CDI 中的开箱即用功能,但借助其 SPI 和可移植扩展,您可以实现您所需要的功能。

此扩展将分析给定类型的所有注入(inject)点,获取每个注入(inject)点的 @Configuration 注释,并在 applicationScoped 中为成员 value( ) 在注释中。

由于您将注册多个具有相同类型的 bean,因此您首先必须将注释转换为限定符

@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
@Documented
public @interface Configuration {
String value();
}

在用于创建 bean 实例的类下方:

@Vetoed
public class ConfiguredService {

private String value;

protected ConfiguredService() {
}

public ConfiguredService(String value) {
this.value = value;
}

public String getValue() {
return value;
}
}

请注意 @Vetoed 注释,以确保 CDI 不会像我们自己那样选择此类来创建 bean。该类必须有一个不带参数的默认构造函数,才能用作钝化 bean 的类(在应用程序范围内)

然后您需要声明自定义 bean 的类。将其视为 bean 的工厂和元数据持有者(范围、限定符等)。

public class ConfiguredServiceBean implements Bean<ConfiguredService>, PassivationCapable {


static Set<Type> types;
private final Configuration configuration;
private final Set<Annotation> qualifiers = new HashSet<>();

public ConfiguredServiceBean(Configuration configuration) {
this.configuration = configuration;
qualifiers.add(configuration);
qualifiers.add(new AnnotationLiteral<Any>() {
});
}

@Override
public Class<?> getBeanClass() {
return ConfiguredService.class;
}

@Override
public Set<InjectionPoint> getInjectionPoints() {
return Collections.EMPTY_SET;
}

@Override
public boolean isNullable() {
return false;
}

@Override
public Set<Type> getTypes() {
return types;
}

@Override
public Set<Annotation> getQualifiers() {
return qualifiers;
}

@Override
public Class<? extends Annotation> getScope() {
return ApplicationScoped.class;
}

@Override
public String getName() {
return null;
}

@Override
public Set<Class<? extends Annotation>> getStereotypes() {
return Collections.EMPTY_SET;
}

@Override
public boolean isAlternative() {
return false;
}

@Override
public ConfiguredService create(CreationalContext<ConfiguredService> creationalContext) {
return new ConfiguredService(configuration.value());
}

@Override
public void destroy(ConfiguredService instance, CreationalContext<ConfiguredService> creationalContext) {
}

@Override
public String getId() {
return getClass().toString() + configuration.value();
}
}

请注意,限定符是唯一的参数,允许我们将限定符的内容链接到 create() 方法中的实例。

最后,您将创建一个扩展,该扩展将从注入(inject)点集合中注册您的 Bean。

public class ConfigurationExtension implements Extension {


private Set<Configuration> configurations = new HashSet<>();

public void retrieveTypes(@Observes ProcessInjectionPoint<?, ConfiguredService> pip, BeanManager bm) {
InjectionPoint ip = pip.getInjectionPoint();

if (ip.getAnnotated().isAnnotationPresent(Configuration.class))
configurations.add(ip.getAnnotated().getAnnotation(Configuration.class));
else
pip.addDefinitionError(new IllegalStateException("Service should be configured"));
}


public void createBeans(@Observes AfterBeanDiscovery abd, BeanManager bm) {

ConfiguredServiceBean.types = bm.createAnnotatedType(ConfiguredService.class).getTypeClosure();

for (Configuration configuration : configurations) {
abd.addBean(new ConfiguredServiceBean(configuration));
}
}
}

通过将其完全限定类名添加到 META-INF/services/javax.enterprise.inject.spi.Extension 文本文件来激活此扩展。

还有其他方法可以通过扩展创建功能,但我尝试为您提供一个在 CDI 1.0 上运行的代码(@Vetoed 注释除外)。

你可以在我的CDI Sandbox on Github中找到这个扩展的源代码.

代码非常简单,但如果您有疑问,请不要犹豫。

关于java - CDI - 应用程序范围但已配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36065091/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com