将依赖项注入Singleton类

问题描述 投票:2回答:4

我有一个像这样定义的单例实例:

public class Singleton {
    private static Singleton INSTANCE = new Singleton();

    private Singleton() {

    }

    public Singleton getInstance() {
        return INSTANCE;
    }
}

现在,由于一些更改,此类必须依赖于一些(3)依赖项。因此,必须在此处注入这些依赖项。

我们如何为这样设计的Singleton类实现依赖注入?

问题是Singleton.getInstance()上已有很多调用者,因此无法使getInstance方法接受依赖项。

P.S:我明白使用Singletons并不总是更清洁的方式:)(这是现有的代码,我必须忍受它:))

P.S:我正在使用Guice进行依赖注入。

java dependency-injection singleton
4个回答
2
投票

您可以将您的类重构为依赖项,同时为客户端保留相同的API。 以Spring为例:

@Component
public class Singleton {

  private Foo foo;
  private Bar bar;
  private Any any;

  // inject dependencies 
  @Autowired
  // annotation not required in recent Spring versions
  public Singleton (Foo foo, Bar bar, Any any){
     this.foo = foo;
     this.bar = bar;
     this.any = any;
  }

  public Singleton getInstance() {
      return this;
  }
}

从客户端,如果客户端类不是bean,则可以注入bean或从bean容器中检索它。

从bean类访问的示例:

public class SingletonClient{

    @Autowired
    private Singleton singleton;

    public void foo(){
        singleton.getInstance().method();
    } 
}

避免客户类更改的想法。 免责声明:我不推广这种方式,因为它既反直觉,又容易出错,最重要的是保持单身人士静态访问的技术债务。 作为临时解决方案是可以接受的,但是应该尽快执行现有代码的重构。

因此,想法是在构造函数调用期间将bean实例存储在静态字段中。 通过这种方式,Singleton.getInstance()返回豆。

@Component
public class Singleton {

    private Foo foo;
    private Bar bar;
    private Any any;

    private static Singleton instance;

    // inject dependencies
    @Autowired
    // annotation not required in recent Spring versions
    public Singleton(Foo foo, Bar bar, Any any) {
      this.foo = foo;
      this.bar = bar;
      this.any = any;
      instance = this;
    }

    public static Singleton getInstance() {
      return instance;
    }

}

0
投票

您可以在Guice中使用@Singleton注释来告诉注入器只创建一个在应用程序中共享的实例。然后,您可以通过注释变量或选择的构造函数以通常的方式注入依赖项

    @Singleton
    public class Singleton {

      @Inject // Choose to put the annotation here OR on a constructor, not both
      private Foo foo;

      @Inject // only put this constructor here if you don't annotate the variable
      public Singleton (Foo foo){
         this.foo = foo;
      }

      public Singleton getInstance() {
          return this;
      }

...
    }

0
投票

如果您使用Spring,即使没有公共构造函数,也可以实现依赖注入。只需标记依赖关系@Autowired。 Spring将通过反射注入它们。 :)


0
投票

你可以这样做。

public class Singleton {

    private DependencyClass1 dependency1;

    private DependencyClass2 dependency2;

    private DependencyClass3 dependency3;

    private static Singleton INSTANCE = new Singleton(
            new DependencyClass1(...),
            new DependencyClass2(...),
            new DependencyClass3(...)
    );

    private Singleton(
            DependencyClass1 dependency1,
            DependencyClass2 dependency2,
            DependencyClass3 dependency3
    ) {
        this.dependency1 = dependency1;
        this.dependency2 = dependency2;
        this.dependency3 = dependency3;
    }

    public Singleton getInstance() {
        return INSTANCE;
    }
}

它与任何IOC容器相同。


如果所有注入的依赖项都有单例作用域,则可以执行此操作,否则每次需要时都需要创建注入类的实例。

有将Protype Beans注入Singleton Beans的例子:

https://stackoverflow.com/a/25165971/3058413

© www.soinside.com 2019 - 2024. All rights reserved.