How to provide a default bean in Spring by condition?

安稳与你 提交于 2019-12-12 11:55:53

问题


I'd like to provide a default bean by a custom jar. Only if the user implements a specific abstract class the default bean injection should be skipped.

The following setup already works fine, except one thing: any injected classes within the default wired class are null! What might I be missing?

@Configration
public class AppConfig {
    //use the default service if the user does not provide an own implementation
    @Bean
    @Conditional(MissingServiceBean.class)
    public MyService myService() {
        return new MyService() {};
    }
}


@Component
public abstract class MyService {
    @Autowired
    private SomeOtherService other;

    //default impl of the method, that may be overridden
    public void run() {
        System.out.println(other); //null! Why?
    }
}

public class MissingServiceBean implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return context.getBeanFactory().getBeansOfType(MyService.class).isEmpty();
    }
}

The MyService bean is created and can also be injected. But contained classes are null.

If I remove the @Conditioanl annotation everything works as expected.


回答1:


Your simplest possibility is the usage of the @Primary annotation. You define your interface/abstract class and build a default implementation. Until here thats the basic spring autowiring.

Now you create another implementation with @Primary and make it available in the application context. Spring will now pick up the primary implementation for the autowiring.


Another possibilty in Spring 4.1+ would be to autowire an ordered List<Intf> and ask the interface with a supports(...) call to fetch the current implementation for whatever parameter you give into supports. You give the default implementation a low priority and the more detailed ones a higher priority. Like this you can even build a more detailed default behavior. I'm using this approach for several configurations to handle different classes with default and specific implementations.

One example would be during permission evaluation where we have a default config for the base classes, another higher one for domain classes, and a even higher possible one for specific domain entities. The permission evaluator goes through the list and checks each implementation if it supports that class and delegates to the implementation in that case.

I dont have the code here but i could share it later if desired to make that more clear.




回答2:


Change your code to the following:

public abstract class MyService {

    private final SomeOtherService other;

    public MyService(SomeOtherService other) {
       this.other = other;
    }

    //default impl of the method, that may be overridden
    public void run() {
        System.out.println(other);
    }
}

@Configration
public class AppConfig {

    @Autowired
    private SomeOtherService other;

    //use the default service if the user does not provide an own implementation
    @Bean
    @Condition(MissingServiceBean.class)
    public MyService myService() {
        return new MyService(other) {};
    }
}


来源:https://stackoverflow.com/questions/25522352/how-to-provide-a-default-bean-in-spring-by-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!