如何根据某些会话信息自动装配 spring bean
How to autowire a spring bean based on some session info
我们正在开发基于多语言 Spring 的 Web 应用程序(不是 Spring Boot)。
现在我们正在搜索 "spring way" 执行以下操作。
- 用户使用一些参数启动一个 http 会话,例如语言环境 "de" and/or 国家代码 "DE" (参数类型并不重要)
- 用户使用应用程序
- 在某个时刻,用户触发了一个动作,而这个动作在内心深处需要一个 "localized" 功能
示例(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 之类的东西?
(要使用的服务实现不一定取决于用户的语言环境,而是取决于其他一些 session/request 信息)
感谢您的回答。
实际上,我们最终得到了以下适合我们的解决方案。
我们创建了一个名为 CustomServiceProxy 的 ICustomService 的附加实现。
这个服务有 @Primary 注释来告诉 Spring 在没有提供显式限定符时应该注入这个组件。
该服务获取 sessionData 和一个映射,其中注入了所有 Spring 管理的 ICustomService-Components(Map-Key = 组件的限定符)。
现在,当调用 CustomServiceProxy 上的某些方法时,它会根据实际的会话数据(例如语言)生成 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
}
}
我们正在开发基于多语言 Spring 的 Web 应用程序(不是 Spring Boot)。
现在我们正在搜索 "spring way" 执行以下操作。
- 用户使用一些参数启动一个 http 会话,例如语言环境 "de" and/or 国家代码 "DE" (参数类型并不重要)
- 用户使用应用程序
- 在某个时刻,用户触发了一个动作,而这个动作在内心深处需要一个 "localized" 功能
示例(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 之类的东西?
(要使用的服务实现不一定取决于用户的语言环境,而是取决于其他一些 session/request 信息)
感谢您的回答。
实际上,我们最终得到了以下适合我们的解决方案。
我们创建了一个名为 CustomServiceProxy 的 ICustomService 的附加实现。 这个服务有 @Primary 注释来告诉 Spring 在没有提供显式限定符时应该注入这个组件。 该服务获取 sessionData 和一个映射,其中注入了所有 Spring 管理的 ICustomService-Components(Map-Key = 组件的限定符)。 现在,当调用 CustomServiceProxy 上的某些方法时,它会根据实际的会话数据(例如语言)生成 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
}
}