我有一个像这样定义的单例实例:
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {
}
public Singleton getInstance() {
return INSTANCE;
}
}
现在,由于一些更改,此类必须依赖于一些(3)依赖项。因此,这些依赖关系必须注入。
我们如何为这样设计的Singleton类实现依赖注入?
问题是Singleton.getInstance()
上已有很多调用者,因此无法使getInstance方法接受依赖项。
P.S:我正在使用Guice进行依赖注入。
答案 0 :(得分: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()
返回bean。
@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;
}
}
答案 1 :(得分: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的例子:
答案 2 :(得分: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;
}
...
}
答案 3 :(得分:0)
如果您使用Spring,即使没有公共构造函数,也可以实现依赖注入。只需标记依赖关系@Autowired。 Spring将通过反射注入它们。 :)