在Spring中隐式合格的自动装配

Ale*_*kiy 6 java spring

我有一个带有一些独立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配置进行配置.

Jud*_*ing 1

您的示例有点令人困惑,因为您的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)