Java CDI-已处理但已配置的应用程序
问题 使用CDI,我希望生成Java CDI-已处理但已配置的应用程序,java,configuration,scope,cdi,code-injection,Java,Configuration,Scope,Cdi,Code Injection,问题 使用CDI,我希望生成@ApplicationScopedbean 此外,我希望为注入点提供配置注释,例如: @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface Configuration { String value(); } 我不想为value的每个不同可能性编写一个单独的生产者
@ApplicationScoped
bean
此外,我希望为注入点提供配置注释,例如:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Configuration {
String value();
}
我不想为value
的每个不同可能性编写一个单独的生产者
方法 通常的方法是制作生产者并处理注入点注释:
@Produces
public Object create(InjectionPoint injectionPoint) {
Configuration annotation = injectionPoint.getAnnotated().getAnnotation(Configuration .class);
...
}
因此,bean不能再被应用程序限定范围,因为每个注入点可能不同(producer的参数injectionpoint不适用于@aplicationscope
注释的生产者)
所以这个解决方案不起作用
问题 我需要具有相同值的注入点获得相同bean实例的可能性 是否有一种内置的CDI方式?或者我是否需要在列表中以某种方式“记住”bean,例如在包含生产者的类中
我需要的基本上是针对每个不同的
值的应用程序实例,您尝试实现的不是CDI中的现成功能,而是由于其SPI和便携扩展,您可以实现您所需的功能
此扩展将分析给定类型的所有注入点,在每个注入点上获取@Configuration
注释,并将在应用程序中为注释中成员value()
的每个不同值创建一个bean
由于您将使用同一类型注册多个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();
}
}
通过将其完全限定的类名添加到META-INF/services/javax.enterprise.inject.spi.extension
文本文件,可以激活此扩展名
有其他方法可以通过扩展创建功能,但我尝试给您一个从CDI 1.0开始工作的代码(除了@Vetoed
注释)
您可以在my中找到此扩展的源代码
代码非常简单,但如果您有疑问,请不要犹豫。您尝试实现的不是CDI中的现成功能,而是由于其SPI和可移植扩展,您可以实现所需的功能
此扩展将分析给定类型的所有注入点,在每个注入点上获取@Configuration
注释,并将在应用程序中为注释中成员value()
的每个不同值创建一个bean
由于您将使用同一类型注册多个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();
}
}
通过将其完全限定的类名添加到META-INF/services/javax.enterprise.inject.spi.extension
文本文件,可以激活此扩展名
有其他方法可以通过扩展创建功能,但我尝试给您一个从CDI 1.0开始工作的代码(除了@Vetoed
注释)
您可以在my中找到此扩展的源代码
代码非常直截了当,但如果您有疑问,请不要犹豫