@ConditionalOnBean не работает с JdbcTemplate.class - PullRequest
2 голосов
/ 21 июня 2019

У меня есть некоторый компонент пружины:

@Component
@ConditionalOnBean(value={JdbcTemplate.class})
public class DictionaryHandler implements Handler {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public DictionaryHandler(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //some methods
}

В отладке я вижу, что создан боб JdbcTemplate: enter image description here

Но, мойбин не создан. Он не входит в конструктор.Но почему?Бин JdbcTemplate существует, но мой бин не создан.

Условие работает неправильно?Я не хочу создавать DictionaryHandler, если отсутствует JdbcTemplate.Без этого я получаю ошибку.

Ответы [ 3 ]

2 голосов
/ 21 июня 2019

Вы должны использовать @ConditionalOnBean только для классов автоконфигурации (в противном случае порядок не указан)

Условие может соответствовать только определениям бина, которые были обработаныконтекст приложения, и поэтому настоятельно рекомендуется использовать это условие только для классов автоконфигурации.Если потенциальный бин может быть создан другой автоконфигурацией, убедитесь, что после этого выполняется тот, который использует это условие.

Поскольку ваш бин JdbcTemplate определен внутри класса JdbcTemplateAutoConfiguration, поэтому я предполагаю, чтоJdbcTemplateAutoConfiguration помечен @Configuration.

В этом случае вы можете обеспечить создание экземпляра вашего компонента с помощью config:

@Configuration
@AutoConfigureAfter(JdbcTemplateAutoConfiguration.class)
public class DicationaryHandlerConfiguration {

    @Bean
    @ConditionalOnBean(JdbcTemplate.class)
    public DictionaryHandler handler(JdbcTemplate jdbcTemplate) {
         return new DictionaryHandler(jdbcTemplate)
    }

}

public class DictionaryHandler implements Handler {

    private final JdbcTemplate jdbcTemplate;

    public DictionaryHandler(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //some methods
}
1 голос
/ 21 июня 2019

Проверьте документацию для ConditionalOnBean. Он запускается один раз, и если требуемый компонент еще не создан, он не сработает. Порядок создания бобов имеет значение. Вы можете попытаться снизить приоритет вашего компонента с помощью аннотации @Order или увеличить приоритет вашего класса конфигурации / компонента, который содержит компонент JdbcTemplate.

1 голос
/ 21 июня 2019

С Тип аннотации ConditionalOnBean :

Условие может соответствовать только определениям компонентов, которые были обработаны контекстом приложения до сих пор, и поэтому настоятельно рекомендуется использовать это условие только для классов автоконфигурации. Если потенциальный компонент может быть создан другой автоконфигурацией, убедитесь, что после этого выполняется тот, который использует это условие.

В вашем случае проблема заключается в том, что DictionaryHandler bean-компонент пытается быть создан до обработки класса конфигурации, и, учитывая, что bean-компонент JdbcTemplate еще не находится в контейнере DI, ваш DictionaryHandler не создается.
Одним из обходных путей может быть инициализация DictionaryHandler в том же классе конфигурации, что и JdbcTemplate.
Также вы можете использовать другой класс конфигурации, но вам придется использовать аннотацию @DependsOn.

Пример:

@Component
@ConditionalOnBean(name = "bean1")
class AnotherBean {
}

@Configuration
class Config {
    @Bean
    public Object bean1() {
        return new Object();
    }
}

В предыдущем примере AnotherBean не будет создано, но будет так:

@Configuration
class Config {
    @Bean
    public Object bean1() {
        return new Object();
    }

    @Bean
    @ConditionalOnBean(name = "bean1")
    public AnotherBean anotherBean() {
        return new AnotherBean();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...