【问题标题】:Use of getBean as opposed to method injection in Spring在 Spring 中使用 getBean 而不是方法注入
【发布时间】:2010-11-12 08:33:07
【问题描述】:

我有一个有多个屏幕的应用程序,每个屏幕都是通过一个按钮选择的。每个屏幕都包含相当重量级的组件,因此只有激活屏幕在内存中很重要——所有其他屏幕都应该可用于垃圾回收。

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

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

"screen1" 是一个原型 bean,因此当按下按钮时会创建一个新的屏幕实例。此外,setScreen() 是应用程序中唯一维护对 Screen 的引用的地方,因此以前活动的屏幕将可用于垃圾收集。我尚未对此进行测试,但我希望它会正常工作 - 这里没有火箭科学!

问题是 - 在阅读 this page 关于为什么 getBean() 被认为不好之后 - 我想知道是否有更惯用的方法来获得相同的结果,同时消除对 getBean() 的依赖。

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

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

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

【问题讨论】:

    标签: java spring


    【解决方案1】:

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

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

    【讨论】:

    • 我指的是使用查找方法标记的方法注入,IMO 与“标准”依赖注入不同 - 它是一个单独的功能,依赖于 AOP(因此依赖于 CGLIB),它是做什么的给你一个工厂(哪个 cletus 展示过?)
    • 工厂会隔离你对Spring的依赖,但它变成了我认为不需要维护的代码。 AOP 有什么问题? AOP 只是 Spring 如何进行 DI 的一个实现细节。
    【解决方案2】:

    您是否考虑过工厂方法?

    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 联系起来。如果您需要模拟和/或单元测试您的应用程序/组件,那么这将使您的生活变得异常困难。上面的工厂解决方案将使它变得微不足道。

    【讨论】:

    • 所以在您的解决方案中,getbean() 是在工厂 create() 方法中调用的,对吧?
    • 不完全是。它已被工厂方法取代,但模拟上述接口比模拟应用程序上下文要容易得多。另外它是可插拔的。归根结底,它是Spring的方法注入static.springsource.org/spring/docs/2.5.x/reference/…的一个更简单的实现
    • 我明白了,但是工厂 create() 方法从哪里获取其 Screen 实例?
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2014-08-24
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-12
      • 2019-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多