java - 如何在运行时更改 @autowired bean 实现?

标签 java spring spring-mvc applicationcontext

我正在开发一个 Spring MVC 3.2 应用程序,该应用程序部署为 EAR,具有多个 Web 应用程序 (WARS),这些应用程序重用许多常见的数据访问和服务 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 应用程序都有自己的属性文件,其中包含新属性或全局属性的变体 - 例如不同的值或字符串。此外,所有对服务的依赖都是通过接口(interface)实现的。

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

编辑

@Prasad 给了我一个很好的实用答复 - 但是我应该添加两个 Controller 使用相同的有状态服务实现的情况,但这些是使用不同的设置/值初始化的 - 仅每个 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 应用程序都可以选择自定义服务实例或实现(或插件,无论您喜欢什么),但同时最大限度地重用?

感谢您的帮助。

最佳答案

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

例如,您有一个界面:

    public interface ServiceA {
        public void yourMethod();
    }

及其实现类为:

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

    }

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

    }

在Web应用1中,如果要访问ServiceAImpl1,可以通过以下方式获取:

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

在Web应用2中,如果要访问ServiceAImpl2,可以通过以下方式获取:

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

关于java - 如何在运行时更改 @autowired bean 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23106319/

相关文章:

java - Autowired 在自定义约束 validator 中给出 Null 值

java - 如何关闭 X 按钮的可见性并禁用 alt + F4 功能

java - 如何将 S3 对象直接从 Java Web 服务器流式传输到浏览器

java - 如何使用 JPA 查询在同一字段中选择可变数量的相似字符串?

java - @ControllerAdvice 不返回 json 响应

java - 如何在控制台中打印 Hibernate ID?

java - Spring MVC中的隐藏字段

Spring Boot 测试 MockMvc 执行后 - 不工作

java - 无法为 IntelliJ IDE 加载 native hadoop 库

java - 汉诺塔计划为何有效?