2017-04-14 53 views
1

我有一个名为Legacy的现有类,主要是用旧式单例模式编写的。现在我想介绍一个新的领域,我想用Guice。 Legacy本身不受Guice控制,它被另一个Service类使用(在Service类中,它调用Legacy类的getInstance()以立即检索Legacy对象),并且该Service类是使用Guice注入器创建的。如何在现有的单例类中使用guice注入?

public class Legacy { 

    public synchronized static Legacy getInstance() { 
     if(sInstance == null) { 
      sInstance = new Legacy(); 
     } 
     return sInstance; 
    } 

    private Legacy() { 
     legacyObj = LegacyField.getInstance(); // get a singleton 
    } 

    private static Legacy sInstance; 

    private LegacyField legacyObj; 

    private NewField newObj; // this is the new dependency I would like to add using Guice 
} 

我想那是什么我试图把方法注入到传统类

@Inject 
public void setNewField(NewField newObj) { 
    this.newObj = newObj; 
} 

而且在服务的模块文件,我绑定了新野物,但是当我运行该程序,它抛出了NullPointer异常。所以注射不起作用。关于如何让NewField注入我的程序的任何想法,但保持目前的老派单身模式,而不是改变太多的一切?

编辑 下面至少有三个解决方案,我不知道哪个是最好的或他们是否等价。

+1

这三种解决方案或多或少都是相同的。他们都直接或间接地调用'injectMembers'在你的单身人士身上。 –

回答

1

这是一个有点骇人听闻的解决方案。

在应用程序的引导, 可能在方法public static void main(String[] args), 你应该已经有类似下面的代码:

Injector injector = Guice.createInjector(yourModule); 

在这个地方添加以下行:

injector.injectMembers(Legacy.getInstance()); 

通过这样做,您的Legacy单身人士 中的所有@Inject都应该解决。
另请参阅Injector.injectMembers的javadoc。

2

虽然只比托马斯的答案稍微干净一点,但您可以使用requestInjectionrequestStaticInjection来配置从您的模块中注入单身人士。

// In your Module: 
requestInjection(Legacy.getInstance()); // for an instance field, or 
requestStaticInjection(Legacy.class); // for a static field. 

docs on the wiki警告的缺点,虽然:

此API不推荐用于一般用途,因为它受到许多相同的问题静态工厂:它的笨拙进行测试,它使依赖不透明,它依赖于全球性的状态。

3

我刚刚找到另一种解决办法:

// put in the module 
bind(Legacy.class).toInstance(Legacy.getInstance()); 

在这个例子中,你的模块本身,而不是吉斯,需要获得一个传统实例的责任,然后要求吉斯一直使用这个单一实例来满足所有遗留注入请求。 但根据javadoc 创建Injector时,它将自动为此实例执行字段和方法注入,但Legacy上的任何可注入构造函数都被忽略。请注意,使用这种方法会导致您无法控制的“急切加载”行为。

+0

这个解决方案还有其他的好处,你甚至可以使用'@Inject Legay legacy'来将你的单例注入其他类。 –