如何基于一些会话信息自动装配Spring bean

时间:2019-05-24 09:15:44

标签: java spring autowired

我们正在开发基于多语言Spring的Web应用程序(不是Spring Boot)。

现在,我们正在寻找执行以下操作的“春季之路”。

  1. 用户使用某些参数启动http会话,例如区域设置“ de”和/或国家/地区代码“ DE”(参数的类型不是很重要)
  2. 用户使用应用程序
  3. 在某个时刻,用户触发了一项操作,该操作需要深入内部某处进行“本地化”功能

示例(java伪代码):

// service with functionality common for all users
@Service
class CommonService implements ICommonService
{
    // how to autowire a service based on some info in the actual HttpSession, eg. CustomServiceUK or CustomServiceDE
    @Autowired
    private ICustomService customServiceImpl;

    @Override
    public void doSomeAction(String param)
    {
        ... do some common stuff

        customResult = customServiceImpl.calculate(param);

        ... do some common stuff with custom result
    }
}

// custom service implementations
@Service("CustomServiceUK")
class CustomServiceUK implements ICustomService
{
    @Override
    public String calculate(String value)
    {
        ... execute logic on value for an "uk" user
    }
}

@Service("CustomServiceDE")
class CustomServiceDE implements ICustomService
{
    @Override
    public String calculate(String value)
    {
        ... execute logic on value for an "de" user
    }
}

如何基于实际HttpSession中的某些信息(例如CustomServiceUK或CustomServiceDE)将定制服务注入CommonService? 我们有什么解决方案?是否有动态@Qualifier之类的东西或某些@Autowired Spring-Factory之类的东西?

(要使用的服务实现不一定取决于用户的语言环境,而取决于其他一些会话/请求信息)

1 个答案:

答案 0 :(得分:1)

感谢您的回答。

实际上,我们最终得到了适用于我们的以下解决方案。

我们创建了名为CustomServiceProxy的ICustomService的其他实现。 该服务具有@Primary批注,以告知Spring在未提供显式限定符时应注入此组件。 该服务获取sessionData和一个Map,其中注入了所有Spring管理的ICustomService-Component(Map-Key =组件的限定符)。 现在,当调用CustomServiceProxy上的某个方法时,它会根据实际的sessionData(例如语言)生成Map-Key,然后在Map中查找ICustomService并将调用委派给该特定服务。

// service with functionality common for all users
@Service
class CommonService implements ICommonService
{
    // because of @Primary an instance of CustomServiceProxy will be injected
    @Autowired
    private ICustomService customServiceImpl;

    @Override
    public void doSomeAction(String param)
    {
        ... do some common stuff

        customResult = customServiceImpl.calculate(param);

        ... do some common stuff with custom result
    }
}

// custom service implementations
@Service
@Primary
class CustomServiceProxy implements ICustomService
{
    private CustomData sessionData;
    private Map<String, ICustomService> services;

    @Autowired
    public CustomServiceProxy(CustomData sessionData, Map<String, ICustomService> services)
    {
        this.sessionData = sessionData;
        this.services = services;
    }

    @Override
    public String calculate(String value)
    {
        String serviceName = "CustomService" + sessionData.getLanguage().toUpperCase();
        ICustomService customService = services.get(serviceName);
        // handle missing service: throw exception or maybe switch to a default implementation
        Objects.requireNonNull(customService, "missing CustomService with name " + serviceName);
        return customService.calculate(value);
    }
}

@Service("CustomServiceUK")
class CustomServiceUK implements ICustomService
{
    @Override
    public String calculate(String value)
    {
        ... execute logic on value for an "uk" user
    }
}

@Service("CustomServiceDE")
class CustomServiceDE implements ICustomService
{
    @Override
    public String calculate(String value)
    {
        ... execute logic on value for an "de" user
    }
}