我有一个带有一些独立bean X的项目,它在一堆服务中自动装配.服务彼此使用,最后用于单入口点(控制器).现在有了新的要求:实现X的几个版本,并根据入口点的参数(枚举XType)决定使用一个版本.如果不改变服务就可以做到这一点.
我的解决方案是创建自定义范围UsesX和实现BeanFactoryPostProcessor,它将BeanDefinition使用UsesX 将每个范围转换为每个XType的单例集.此外,它还会为此bean添加限定符,以便在控制器中为X和基于参数的选择创建工厂方法.但是如何@Autowired隐式地在服务中添加这个限定符,而不更改它们的类?
UPD
好的,例如,我想"jdbc:mysql://Adb"在A请求"jdbc:mysql://Bdb"时使用db url ,以及何时B:
enum DatabaseType {A, B}
@Controller
@RequestMapping(/)
class MyController {
@Autowired ServiceProvider provider; // some way to get service by DatabaseType
void foo(@RequestParam DatabaseType dbType) {
ServiceA a = provider.getA(dbType);
a.bar();
ServiceB b = provider.getB(dbType);
b.baz();
}
}
@Service
class ServiceA {
// Don't want to get information about different databases in services
@Autowired ServiceB b;
@Autowired ServiceC c;
@Autowired DaoFoo dao;
//...
}
@Service
class ServiceB {
@Autowired ServiceC c;
@Autowired DaoFoo daoFoo;
@Autowired DaoBar daoBar;
//...
}
@Service
class ServiceC {
@Autowired DaoBar daoBar;
//...
}
@Repository
class DaoFoo {
DaoFoo(String dbURL) {/*...*/}
}
@Repository
class DaoBar {
DaoFoo(String dbURL) {/*...*/}
}
Run Code Online (Sandbox Code Playgroud)
此外,需要将"jdbc:mysql://Adb"和"jdbc:mysql://Bdb"在XML配置进行配置.
您的示例有点令人困惑,因为您的Services 被命名为 A 和 B,但您也将 A 和 B 用于您的DatabaseType. 但我想我明白你想要什么。
我不认为你可以用 来做到这一点Autowired,但你可以将你的Services 设置为@Scope("prototype")并从上下文中检索它们。上下文应该在Service您第一次请求时实例化,然后在提供相同的输入时重用相同的 bean。
@Configuration
public class ServiceProvider{
...
@Bean
@Scope("prototype")
public ServiceA serviceA(DatabaseType dbType) {
...
}
@Bean
@Scope("prototype")
public ServiceB serviceB(DatabaseType dbType) {
...
}
}
@Controller
@RequestMapping(/)
class MyController {
@Autowired
ConfigurableApplicationContext context
void foo(@RequestParam DatabaseType dbType) {
AutowireCapableBeanFactory beanFactory = context.getBeanFactory();
ServiceA serviceA = (ServiceA)context.getBean("serviceA", dbType);
...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
612 次 |
| 最近记录: |