【问题标题】:Best Practise of injecting applicationContext in Spring3Spring 3 注入 applicationContext 的最佳实践
【发布时间】:2012-03-28 07:33:29
【问题描述】:

正如上面的标题,我对直接@Autowired注解注入applicationContext或在单例spring bean中实现ApplicationContextAware接口之间的利弊感到困惑。

在哪些情况下您更喜欢哪一种,为什么?谢谢。

【问题讨论】:

    标签: spring dependency-injection spring-3 applicationcontext


    【解决方案1】:

    实际上,两者都不好。它们都将您的应用程序绑定到 Spring 框架,从而颠倒了整个控制反转的概念。在理想情况下,您的应用程序根本不应该意识到由 ApplicationContext 管理。

    一旦你选择了违反这个原则,你怎么做都没有关系。 ApplicationContextAwareat least since Version 2.0 周围的旧版本。 @Autowired 是一种较新的机制,但它们的工作方式几乎相同。我可能会选择ApplicationContextAware,因为它在语义上清楚地表明了它的含义。

    【讨论】:

    • 谢谢。但是,如果注入到其中的 applicationContext bean 已经是 spring bean 怎么办?你认为这仍然是违规行为吗?顺便说一句,实际上我拥有的大多数 bean 都是我的应用程序中的一个 spring bean,这就是为什么我对你提到的有点困惑:'将你的应用程序绑定到 Spring 框架'。是在所有情况下都正确还是仅在我有一个与 Spring 框架部分分离的应用程序并且我仅将 Spring 用于某些 bean 以实现某些功能的情况下?
    • 这取决于你所说的 Spring Bean。如果您有由 Spring 从外部管理的普通 Java Bean,那么您的应用程序不会绑定到 Spring,并且您可能需要不到一天的时间来切换到不同的 IOC 容器。这是一个极端(当然,你几乎找不到),另一个极端是你所描述的:通过服务定位器进行依赖注入,或者我称之为:控制反转反转。仅在您确实必须这样做时尝试这样做。
    • 与我的问题相关的主要原因是将原型作用域 bean 注入单例作用域 bean。这就是为什么我必须为每个方法调用从 applicationContext(或 BeanFactory)获取 bean。顺便说一句,我的根包下的每个类(这意味着所有类)都在弹簧控制之下。所以最后一个问题,你能更详细地解释一下你提到的:“它在语义上清楚地说明了它是关于什么的。”?再次提前非常感谢您。
    • 顾名思义:类感知ApplicationContext,违反IOC原则。 Expressivele 在接口名称中提到违规对我来说似乎是个好主意。
    • 我会质疑违反国际奥委会的声明。利用@Autowired 或ApplicationContext 不违反IOC,它们被用于实现 IOC。关于您对“将自己与弹簧绑在一起”的评论,请提供对利用弹簧的提议替代方案的见解,而不会在您的脑海中“将自己绑起来”。我看不出这是怎么可能的,更不用说你可能试图提出什么观点了。感觉就像您在建议使用任何工具或技术来完全抽象。您是否还对 JDK 中的对象进行抽象以隔离未来的变化?
    【解决方案2】:

    正如@Sean Patrick Floyd 所说,对 ApplicationContext 的需求通常是由于糟糕的设计。但有时你别无选择。在这些情况下,我更喜欢使用@Autowired,因为这是我注入所有其他属性的方式。那么,如果我使用 @Autowired 来注入 MyRepository,为什么我不能将它用于 ApplicationContext 或任何其他 Spring bean?

    我只将 Spring 接口用于那些我不能用注解做的事情,例如 BeanNameAware。

    【讨论】:

      【解决方案3】:

      如果您需要在单例中获取原型,则可以使用方法注入。基本上,您创建一个返回所需对象的抽象方法,并且每次调用该方法时,spring 都会返回原型。您在 spring 配置中定义“查找方法”。以下是一些链接: http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#beans-factory-method-injection http://java.dzone.com/articles/method-injection-spring

      【讨论】:

        【解决方案4】:

        由于您没有扩展任何 spring 类,因此您的应用程序始终与框架分离。大多数情况下,您不想注入ApplicationContext,而是需要注入ApplicationContext 中定义的bean。

        最好的情况是始终坚持最低限度,除非您有任何特定要求,这对于 spring 非常简单。

        要么,

        1. application context 中注释您的bean 和scan,然后使用@Autowire 将它们连接起来。

        2. 使用application context 连接您的 bean 权宜之计(旧的 xml 样式配置)。您也可以通过这种方法使用@Autowire

        当您想控制 bean 生命周期时,您可以读取 API 并对其进行自定义,但大多数情况下这些常规设置可以完成工作。

        这里有一些例子。

        1. Spring Auto-Wiring Beans with @Autowired annotation
        2. Spring Auto-Wiring Beans XML Style
        3. Spring IoC container API Docs

        【讨论】:

        • 感谢您的评论,但我在常见情况和自动装配方面对 Spring 有足够的了解 :) 与我的问题相关的主要原因是将原型作用域 bean 注入单例作用域 bean 的能力.在这种情况下,只是普通的 bean 注入不能按预期工作,所以我应该为每个方法调用从 applicationContext(或更好的 BeanFactory)获取 bean。
        • “由于您没有扩展任何 spring 类,因此您的应用程序始终与框架分离”。这不是真的。只需注入 ApplicationContext 即可将应用程序与 Spring 联系起来。如果 Spring 不存在,它将无法编译
        【解决方案5】:

        根本不需要使用ApplicationContext

        对象工厂

        如果您需要在单例 bean 中使用原型作用域 bean,请注入 org.springframework.beans.factory.ObjectFactory。 例如使用构造函数注入:

        @Service
        class MyClass {
            private ObjectFactory<MyDependency> myDependencyFactory;
        
            public MyClass(ObjectFactory<MyDependency> prototypeFactory) {
                myDependencyFactory = prototypeFactory;
            }
        
        }
        

        为什么

        现在使用 ApplicationContext 有什么好处? 您可以通过简单地传递一个返回其存根版本的 lambda(因为 ObjectFactory 是一个 @FunctionalInterface)来替换此依赖项(例如在测试中)。

        虽然可以对 ApplicationContext 进行存根,但在这种情况下尚不清楚哪些 bean 将被查找并需要存根。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-10
          • 2013-04-21
          • 2010-12-11
          • 1970-01-01
          • 2015-03-18
          • 2015-09-11
          • 2020-03-08
          相关资源
          最近更新 更多