【问题标题】:How to change @autowired bean implementations in runtime?如何在运行时更改 @autowired bean 实现?
【发布时间】:2014-04-16 10:09:37
【问题描述】:

我正在开发一个 Spring MVC 3.2 应用程序,该应用程序部署为具有多个 Web 应用程序 (WARS) 的 EAR,这些 Web 应用程序重用了许多常见的数据访问和服务 bean,但最终可以为一个或多个服务提供自定义实现。

基本上每个 Web 应用程序都是通用解决方案的变体,在某些服务中具有不同的 UI 体验和不同的业务规则。这些服务被实现为不同的无状态和有状态 bean,它们之间存在依赖关系。

应用程序具有应用程序上下文的父子结构,因此每个 Web 应用程序都有自己的上下文。大致思路如下:

-dao
  |-services
        |-one-app-context
               |-one-servlet-context
        |  
        |-two-app-context
               |-two-servlet-context

要构建它,我已按照以下说明进行操作:

http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.html

我正在使用基于 XML 配置 + 注释的 bean 扫描,默认共享单例 bean 范围实例化。有一个全局属性文件,每个 Web 应用程序都有自己的属性文件,其中包含新属性或全局属性的变体 - 例如不同的值或字符串。此外,所有对服务的依赖都是通过接口实现的。

我的问题是我不得不为每个服务初始化一个具体的实现,以满足启动共享上下文时的自动装配要求 - 但是对于给定的 Web 应用程序,我想使用不同的实现或新实例不同的设置。

编辑

@Prasad 给了我一个很好的实用答复——但是我应该添加两个控制器使用相同的有状态服务实现的情况,但是这些是用不同的设置/值初始化的——只有每个 web 层包知道。 我希望看到一个解决方案(如果可能的话),我使用注释/扫描并且不需要进行实例化杂技来获得正确的布线 - 也许是配置文件?

最后,依赖项看起来像这样:

one-web-controller -> serviceA-impl-1
                   -> serviceB-impl -> serviceD-impl (with one.properties)
                   -> serviceC-impl
                   -> serviceE-impl (with one.properties)

two-web-controller -> serviceA-impl-2
                   -> serviceB-impl -> serviceD-impl (with two.properties)
                   -> serviceE-impl (with two.properties)

牢记 KISS,我如何有效地设置 Spring MVC,以便每个 Web 应用程序都可以选择自定义服务实例或实现(或插件,无论您喜欢什么),同时最大限度地重用?

感谢您的帮助。

【问题讨论】:

    标签: java spring spring-mvc applicationcontext


    【解决方案1】:

    假设您正在以父上下文分层形式实现服务层(检查在我给出的this answer 中实现父、根和子上下文),可以使用限定符注入服务实现。

    例如你有一个接口:

        public interface ServiceA {
            public void yourMethod();
        }
    

    及其实现类为:

        @Component(value="serviceAImpl1")
        public class ServiceAImpl1 implements ServiceA {
    
        }
    
        @Component(value="serviceAImpl2")
        public class ServiceAImpl2 implements ServiceA{
    
        }
    

    在web app 1中,如果要访问ServiceAImpl1,可以这样获取:

        @Component
        public class WebApp1Class {
          @Autowire
          @Qualifier("serviceAImpl1")
          ServiceA serviceA;
          ...
        }
    

    在web app 2中,如果要访问ServiceAImpl2,可以这样获取:

        @Component
        public class WebApp2Class {
          @Autowire
          @Qualifier("serviceAImpl2")
          ServiceA serviceA;
          ...
        }
    

    【讨论】:

    • 这解决了自定义实现的问题 - 但我已经编辑了我的问题以展示一个案例,例如ServiceAImpl1 依赖于具有一些设置的有状态 ServiceBImpl1,serviceAImpl2 也依赖于相同的 ServiceBImpl1,但设置不同。
    猜你喜欢
    • 2016-09-28
    • 2015-01-15
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多