如何为@Autowire字段提供不同的bean,条件是拥有对象的注释也是@Autowired?

时间:2018-01-03 02:49:53

标签: java spring spring-boot dependency-injection spring-bean

我有一个配置类,它提供了相同基本bean接口的两个实现。我希望根据拥有的类自动装配的注释有条件地使用它们。

“拥有”类的用法:

public class MyController
{
    @Autowired
    private OwnerInterface baseOwner;

    @Autowired
    @MyAnnotation
    private OwnerInterface specialOwner;
}

拥有类:

public class OwningClass implements OwnerInterface
{
    //This is the one I want to supply a conditional bean for
    @Autowired
    private MyBeanInterface someBean;
}

这是配置类的pesudo代码:

@Configuration
public class ConfigClass
{
    @Bean
    //Should I use a different conditional?
    //And if I make a static method to use here, how would I pass the owning class to it?
    @ConditionalOnExpression(...elided...)
    public MyBeanInterface getNormalBeanInterface()
    {
        return new MyBeanInterfaceImpl();
    }

    @Bean
    @ConditionalOnExpression(...elided.../* MyAnnotation */)
    public MyBeanInterface getSpecialBeanInterface()
    {
        return new MyBeanInterfaceForMyAnnotation();
    }
}

对于条件,有没有办法将拥有对象传递给它?我会使用静态方法,如:

@ConditionalOnExpression(
    "#{T(MyAnnotationVerifier).isAnnotatedBy(ownignObject))}"
)

有更好的解决方案吗?

我不想使用AOP,因为这是在使用应用程序期间,并增加了每个调用的开销。如果我可以提供bean,那么它将在创建对象时在启动时发生。

我可以使用其他@Conditional注释来执行此操作吗?

1 个答案:

答案 0 :(得分:1)

如果必须静态决定(例如@MyAnnotation),您也可以使用@Primary

@Bean
@Primary
public MyBeanInterface getNormalBeanInterface()
{
    return new MyBeanInterfaceImpl();
}

@Bean
public MyBeanInterface getSpecialBeanInterface()
{
    return new MyBeanInterfaceForMyAnnotation();
}

这样,您可以按类型自动连接,它将始终引用带有@Primary的bean

替代方法:按名称使用自动连线

public class ConfigClass {
    @Bean
    public MyBeanInterface normalBean(){
        return new MyBeanInterfaceImpl();
    }

    @Bean
    public MyBeanInterface specialBean(){
        return new MyBeanInterfaceForMyAnnotation();
    }
}

public class MyController {
    @Autowired
    private OwnerInterface normalBean;

    @Autowired
    private OwnerInterface specialBean;
}

要注意:specialBean中的变量名称(normalBean / MyController)与ConfigClass中的@Bean方法完全匹配

希望这会对你有所帮助。