- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题
使用 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/
我想用 CDI 实现工厂模式。这里我们有一个商业案例示例: A client provides a string representing a type. Depending on this type
我在这里的部分问题是使用正确的词汇,所以我提前为这可能是一个简单的术语问题道歉。 假设我有一个 Person接口(interface)和 PersonBean实现该接口(interface)的类。 进
我想我了解 CDI 的工作原理,为了深入研究它,我想尝试将它与现实世界的示例一起使用。我被一件事困住了,我需要你的帮助才能让我理解。我非常感谢您在这方面的帮助。 我有自己的工作流框架,使用 Java
来自 Guice 背景,我知道可以使用范围从范围中播种对象值。 scope.seed(Key.get(SomeObject.class), someObject); 我想可以通过注册一个从 Abs
JSR-299 (CDI) 引入了资源的(不幸命名的)概念:http://docs.jboss.org/weld/reference/1.0.0/en-US/html/resources.html#d
规范说,当作用域的上下文即将被销毁时,CDI 容器会删除 SFSB。它如何准确地删除 EJB?它似乎没有调用带有@Remove 注释的方法。 @Stateful public class Custom
我有一个手动初始化的对象(遗留代码)。我想将此对象放入应用程序上下文,以使其通过 CDI 可用。 如何在不编写 CDI 扩展的情况下做到这一点? 最佳答案 使用生产者。制作一个 @Produces 您
我有一个关于在 Java EE 中拥有一个尽可能不耦合的系统的最佳实现的问题,问题是使用 CDI 事件还是 CDI 拦截器更好,显然对于安全性之类的事情来说拦截器,对于日志,例如根据具体情况的两者中的
我正在尝试做简单的事情。注塑合格String (或 File )在 CDI 中。 所以我有一个限定符: @Retention(RetentionPolicy.RUNTIME) @Target({FIE
使用 Wildfly 8.2.0.Final(我相信它使用 Weld 2.2),我在 Maven 多模块项目中用 2 个简单的类重现了这个问题。一个生成一个 javax.ws.rs.client.Cl
我正在使用 picketlink 对项目中的用户进行身份验证。我还创建了一个 @produces 注释方法,因此我可以在其他地方注入(inject)经过身份验证的用户。现在,我正在使用 envers,
是否可以在使用 new 关键字创建的类中获取 CDI bean 的实例?我们目前正在对一个旧应用程序进行一些改进,我们总是得到一个 ContextNotActiveException每次我们做 pro
我正在尝试在 WildFly 8.1.0.Final 上使用 CDI 运行 Liquibase 脚本,但出现此错误: Unsatisfied dependencies for type Resourc
在没有值的情况下使用 CDI @Named 有什么意义吗?难道这不就相当于一起使用@Qualifier和@Default吗? @Named public class GifFileEditor imp
我在 JBoss-7 环境中使用 ReastEasy,目前正在实现安全功能。我正在使用带有 SSL 连接的 HTTP Basic。添加和评估 header 参数很容易(感谢 Passing param
我正在开发一些应用程序,它由三层组成: 数据库访问层(JPA + Hibernate 作为提供者) 业务逻辑层 表示层 (JSF 2.0) 在开始之前,我已经阅读了 David Geary 和 Cay
在 CDI 中,我能够注入(inject)具有特定范围的 bean,即定义 bean 类的范围。但是,如果我创建没有任何作用域的 bean 类,并且在注入(inject)时为该 bean 赋予作用域,
我们想使用 Jglue 框架对我们的 CDI 应用程序进行单元测试。我们使用 gradle 进行构建。 我们准备了这样的东西: 1) 要测试的类: @Default public class Rate
我已经有一个 session 范围的 CDI bean,它保持当前登录的用户数据。 现在,从另一个请求范围内,我想访问这个 bean 以获取一些数据。我有一些操作要做,这取决于用户登录。这是我需要的唯
有一个包 A,并且包 A 中有一个类 MyClass。我们假设 pax-cdi+weld 已打开。 我可以在不使用@Inject和其他CDI注释的情况下获取MyClass内bundle A的BeanM
我是一名优秀的程序员,十分优秀!