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

时间:2014-04-16 10:09:38

标签: java spring spring-mvc applicationcontext

我正在开发一个部署为EAR的Spring MVC 3.2应用程序,该应用程序具有多个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 config + annotation的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应用程序都可以选择自定义服务实例或实现(或插件,无论您喜欢什么),同时最大限度地重用?

感谢您的帮助。

1 个答案:

答案 0 :(得分: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{

    }

在网络应用1中,如果您想访问ServiceAImpl1,可以将其命名为:

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

在Web应用程序2中,如果要访问ServiceAImpl2,可以将其命名为:

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