gpt4 book ai didi

cdi - 使用 CDI 的工厂模式取决于运行时参数

转载 作者:行者123 更新时间:2023-12-04 19:20:14 25 4
gpt4 key购买 nike

我想用 CDI 实现工厂模式。这里我们有一个商业案例示例:

A client provides a string representing a type. Depending on this type the factory returns an implementation of an interface.



我知道有很多关于工厂模式和 CDI 的问题。我这里的区别是我根据运行时参数解析工厂返回的实现。

我正在考虑使用生产者方法,但后来我想不出如何将解析的实现注入(inject)到需要实现的 bean 中,因为这是一个运行时参数,在构建时不一定知道。

所以我想到了使用 Instance 类的非常直接的方法。

这是基本实现:

// the interface. Instances of this class are returned from the factory
public interface Product {
}

// one implementation may be returned by the factory
@ProductType("default")
public class DefaultProduct implements Product {
}

// another implementation may be returned by the factory
@ProductType("myProduct")
public class MyProduct implements Product {
}

// the qualifier annotation
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface ProductType {
String value();
}

// the Annotation implementation to select
// the correct implementation in the factory
public class ProductTypeLiteral extends AnnotationLiteral<ProductType>
implements ProductType {

private String type;

public ProductTypeLiteral(String type) {
this.type = type;
}

@Override
public String value() {
return type;
}
}

// the factory itself. It is annotated with @Singleton because the
// factory is only needed once
@Singleton
public class Factory {

@Inject
@Any
private Instance<Product> products;

public Product getProduct(String type) {
ProductTypeLiteral literal = new ProductTypeLiteral(type);
Instance<Product> typeProducts = products.select(literal);
return typeProducts.get();
}
}

在我看来,使用 Instance 是非常复杂的。
但这有一个主要缺点:
每次调用 Instance.get()检索 Product 的新实例的方法.这可能没问题,但 Instance instance 在内部保留返回实例的引用。所以只要 Factory生活和每次 Instance.get()被称为 Product 的更多实例将存在于内存中并且永远不会被垃圾回收,因为引用仍然保留在 Instance 中.

我想过不做 Factory一个单例,但这只是转移了问题,并没有解决它。当然,这违反了工厂模式。

我尝试的另一个解决方案是遍历 Instance而不是在注释的帮助下选择实现:

@Singleton
public class Factory {

@Inject
@Any
private Instance<Product> products;

public Product getProduct(String type) {
Product product = null;
for(Product eachProduct : products) {
ProductType productType = eachProduct.getClass().
getAnnotation(ProductType.class)
if(productType.value().equals(type) {
product = eachProduct;
break;
}
}
return product;
}
}

基本上这是有效的。现在每次根据给定的类型,我都会检索 Product 的相同实例.这样内存就不会被消耗。
但是当我有可能更优雅地解决正确的实现时,我不喜欢迭代集合。

你有什么想法可以解决这个问题吗?否则我可能不得不保留迭代解决方案。

最佳答案

这就是你的问题。 Instance 使用 get() 保持对您从中获取的实例的引用因为它负责在它们超出范围时回收它们(即当注入(inject)的 Instance 超出范围时。但是因为您使您的工厂成为单例,所以它永远不会超出范围。所以,让您的工厂成为一个短的-lived 范围,例如 @RequestScoped 甚至 @Dependent ,这样所有返回的实例都将被正确回收。

关于cdi - 使用 CDI 的工厂模式取决于运行时参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16955446/

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