在春季是否可以使Optional <t>和@Lazy一起工作?

时间:2019-01-22 08:15:01

标签: java spring

  1. 我不得不让我@Component @Lazy,因为它很少使用并且会产生循环依赖问题
  2. 我必须将其设为Optional<T>,因为它表示的功能可以在启动(@ConditionalOnProperty)时禁用,因此在运行时可能不可用

问题: 当我使用Optional<T>作为注入点时,bean会被初始化。

所以问题:

  1. 是否可以使它像这样工作?
  2. 我可以将Optional<T>替换为Provider<T>吗?如果功能被禁用,它会简单地返回null还是会引发异常?
  3. 可以用ObjectProvider<T>代替吗?
  4. 我想坚持使用@Resource@Inject注释,因此@Autowired(required=false)将是我的最后选择。

实际上没有可在此处共享的代码(因为这将是类和字段声明,因为它们仅与IMHO有关)

由于您不相信我,代码在这里毫无价值,所以让我分享:)

@Comonent
@Lazy
public class MyType{

}

注入点

@Lazy
@Autowired
private Optional<MyType> myType;

用法

  MyType instance=myType.getOrThrow(()->throw something)

IV已测试Optional,并且调试器在应用程序启动时命中MyType。当我使用纯字段,提供程序或对象提供程序时,它将被跳过。

2 个答案:

答案 0 :(得分:2)

在这种情况下,我不直接{@ {1}}进行接线,而是懒惰地进行接线。有多种选择:

浏览Component并在需要时检索ApplicationContext。仅当知道它已启用时,您才可以检索它:

MyType

提供者或工厂方法,其中具有自动连接的服务,可为您提供@Autowire private ApplicationContext context; ... MyType instance = context.getBean(MyType.class); 的实例。也仅在启用该功能时调用此服务。

MyType

使用@Autowire private MyTypeFactory factory; ... MyType instance = factory.getMyType(); 会要求您在配置中定义一个bean,因此,仅仅具有一个POJO服务就可以了,而您可以将Provider放在上面,这很容易。

答案 1 :(得分:2)

让我提出另一种观点。我认为为此使用Optional依赖是不合理的。

具有Autowired MyType的类可能依赖于此依赖关系(尽管如果一种不良做法,则对数据字段使用Optional是事实。

组件懒惰的原因似乎也比意图更“骇人”(循环依赖永远不是一件好事)。

因此,如果我们假装该类使某些东西“可选地可用”,则一种方法是为此有问题的MyType bean提供另外的无操作实现:

interface MyType {
   void doSomeHeavyStuff();
}

public class MyTypeRegularImpl() implements MyType {
   public void doSomeHeavyStuff() {
     ....work..work..work..
   }
}

public class NoOpMyType implements MyType {
   public void doSomeHeavyStuff() {
     // do nothing here
   } 
}

现在的诀窍是提供两个互斥条件,并确保这两个负载中只有一个bean(否则它将在bean中产生歧义,并且可能在应用程序启动期间失败)。

因此,使用MyType的类完全不需要Optional。

现在关于懒惰。 总的来说,懒豆只得到ini 可以使用Lazy Bean,因为将在具​​有该Lazy依赖关系的类中的第一次调用期间初始化Bean。

对于没有操作的豆,这根本没有关系。