Spring依赖注入取决于请求对象

时间:2013-07-24 03:09:40

标签: spring dependency-injection httprequest

我正在使用spring进行Web应用程序。应用程序配置了属性文件。 在不同的服务器中有多个应用程序实例,每个实例都有不同的配置文件(每个实例都是为不同的客户定制的)我使用的是控制器和服务。像这样:

public class Controller1 {
    @Autowired
    Service1 service1;

    @RequestMapping(value = "/page.htm", method = { RequestMethod.GET, RequestMethod.POST })
    public ModelAndView serve(HttpServletRequest request, HttpServletResponse response) {
        service1.doSomething();
        return new ModelAndView("/something");
    }
}

@Service
public class Service1 {
    @Autowired
    Service2 service2;
    public void doSomething () {
            …
            service2.doAnotherThing();
            …
        }
}

@Service
public class Service2 {
    @Value("${propertyValue}")
    private String propertyValue;

    //doAnotherThing()  will use propertyValue
    public void doAnotherThing () {
        …
        //Do something with propertyValue
        …
        }
}

现在我有了新的要求。每个客户不会有多个实例,但只有一个实例为所有客户提供多个域。 应用程序必须根据控制器中请求对象的主机名决定配置。因此,如果客户将浏览器指向www.app1.com,我必须使用配置文件1,但如果客户使用www.app2.com,我必须使用配置2,依此类推。

我将配置文件移动到数据库,但后来我意识到我不知道如何进行依赖注入。服务是链接的,service1使用service2,service2是必须使用取决于配置的值的服务。服务2不知道请求对象。

有没有一种干净的方法来解决这个问题?

谢谢,

1 个答案:

答案 0 :(得分:1)

一种方法是在spring config上为所有客户创建配置对象:

<bean id="customerAConfig"../>
<bean id="customerBConfig"../>
<bean id="customerCConfig"../>

并且有一个会话范围的ConfigurationService,它充当指向配置活动的指针

public class ConfigurationService {

   private CustomerConfig activeConfig;

   // getters & setters..
}

在spring配置中为此服务配置单例代理,以便将其注入单例组件。您需要在Spring的类路径中使用cglib来创建代理:

<bean class="com.mycompany.ConfigurationService" scope="session">
  <aop:scoped-proxy/>
</bean>

在您的登录控制器上,选择虚拟主机名应使用的配置,并将其存储到ConfigurationService中以供以后检索(请记住ConfigurationService是会话范围的)

public class LoginController {

  @Autowired private CustomerConfig[] custConfigs;
  @Autowired private ConfigurationService configService;

  @RequestMapping(method = POST)
  public String login(HttpServletRequest request, ..) {
    ...
    String host = request.getServerName();
    CustomerConfig activeConfig = // decide which one based on host..
    configService.setActiveConfig(activeConfig);
    ...
  }
}

下面是一个读取客户特定配置的示例FooController

@Controller
@RequestMapping("/foo")
public class FooController {

  @Autowired private ConfigurationService configService;

  @RequestMapping(method = "GET")
  public String get() {
    ...
    CustomerConfig config = configService.getActiveConfig();
    ...
  }

  ...
}

如果您的程序没有像登录页面那样的单个入口点,则可以将类似的逻辑编码为过滤器。检查是否在会话中设置了活动配置,如果没有根据主机名

查找