使用getBean而不是Spring中的方法注入

时间:2009-07-20 15:16:28

标签: java spring

我的应用程序有多个屏幕,每个屏幕都是通过按钮选择的。每个屏幕都包含非常重的组件,因此重要的是只有激活屏幕在内存中 - 所有其他屏幕都应该可用于垃圾收集。

该应用程序使用Spring作为粘合剂,目前它使用getBean()来切换屏幕:

//event handler for a specific button
public void actionPerformed(Event e) {
    setScreen( (Screen) applicationContext.getBean("screen1"));
}

“screen1”是原型bean,因此在按下按钮时会创建一个新的屏幕实例。此外,setScreen()是唯一在应用程序中维护对屏幕的引用的位置,因此之前活动的屏幕可用于垃圾回收。我还没有测试过这个,但我希望它能正常工作 - 这里没有火箭科学!

问题是 - 在阅读this page之后关于为什么getBean()被认为是错误的 - 我想知道在删除对getBean()的依赖性时是否有一种更惯用的方法来实现相同的结果。

我已经研究了方法注入,它在我看来引入复杂性并没什么好处。这是学习的另一个概念,更多魔术,增加对CGLIB的依赖等。如果我真的想要删除对Spring的依赖,我可以引入一个暴露getBean()方法的接口。

在我的情况下getBean()和方法注入是唯一的选项还是我错过了什么?

如果是这样,getBean()真的那么糟糕吗?

3 个答案:

答案 0 :(得分:3)

Setter注入,属性注入或构造函数注入都创建了一个松散耦合的应用程序,通过模拟更容易测试。它还可以防止任何类直接依赖于Spring(或其他IoC容器)类。当您不必手动调用getBean()时,它最终只是一个更清晰的整体解决方案。

我认为您应该对配置依赖项的概念感到满意。 “魔法”根本不是真正的魔法,只是你在使用它时会感到舒服的东西。

答案 1 :(得分:0)

您是否考虑过工厂方法?

public interface ComponentFactory<T> {
  T create();
}

public class ScreenFactory implements ComponentFactory<Screen> {
  @Override
  Screen create() { ... }
}

public class MyApp {
  private ComponentFactory<Screen> screen1;

  public void actionPerformed(Event e) {
    setScreen(screen1.create());
  }

  public void setScreen1(ComponentFactory<Screen> screen1) {
    this.screen1 = screen1;
  }

  private void setScreen(Screen screen) { ... }
}

结合:

<bean id="screenFactory" class="com.myclass.ScreenFactory"/>

<bean id="myapp" class="...">
  <property name="screen1" ref="screenFactory"/>
</bean>

您当然可以自动连接上述内容。

你正在做的问题是它既硬编码你要实例化的bean,又将你的实现绑定到ApplicationContext。如果您需要模拟和/或单元测试您的应用程序/组件,那么这将使您的生活难以置信。上面的工厂解决方案将使其变得微不足道。

答案 2 :(得分:0)

如果您只是想摆脱getBean,请考虑使用ServiceLocatorFactoryBean。但是这对你有用的程度可能取决于你的应用程序中字符串“screen1”的来源。