Условная аннотация Spring не работает

Я определил класс с конфигурацией аннотации

    @Configuration
    @AutoConfigureAfter(EndpointAutoConfiguration.class)
    public class EndpointConfiguration {
        @Resource
        private MetricsEndpoint metricsEndpoint;

        @Bean
        public MetricsFormatEndpoint metricsFormatEndpoint() {
            return new MetricsFormatEndpoint(metricsEndpoint);
        }
    }

MetricsFormatEndpoint работает хорошо.

но я использую аннотацию conditionalOnBean, она вообще не работает.

    @Bean
    @ConditionalOnBean(MetricsEndpoint.class)
    public MetricsFormatEndpoint metricsFormatEndpoint() {
        return new MetricsFormatEndpoint(metricsEndpoint);
    }

см. localhost: 8080 / beans, у Spring applicationContext есть bean-компонент metricsEndpoint,

    {"bean":"metricsEndpoint","scope":"singleton",
     "type":"org.springframework.boot.actuate.endpoint.MetricsEndpoint",
     "resource":"class path resource 
    [org/springframework/boot/actuate/autoconfigure/EndpointAutoConfiguration.class]",
    "dependencies":[]}

Я прочитал документ аннотации @ConditionalOnBean, в нем написано Тип класса bean-компонента, который следует проверить. Условие соответствует, когда любой из указанных классов содержится в {@link ApplicationContext}.

кто может сказать мне почему


person zhangzhide    schedule 04.08.2015    source источник
comment
Когда вы говорите, что это вообще не работает, что происходит? Какие неудачи / неожиданное поведение вы видели?   -  person Andy Wilkinson    schedule 04.08.2015


Ответы (2)


Документ javadoc для @ConditionalOnBean описывает это как:

Conditional, который соответствует только тогда, когда указанные классы и / или имена компонентов уже содержатся в BeanFactory.

В этом случае ключевая часть «уже содержится в BeanFactory». Ваши собственные классы конфигурации рассматриваются перед любыми классами автоконфигурации. Это означает, что автоконфигурация bean-компонента MetricsEndpoint еще не произошла к тому моменту, когда ваша собственная конфигурация проверяет его существование, и в результате ваш MetricsFormatEndpoint bean-компонент не создается.

Один из возможных подходов - создайте собственный класс автоконфигурации для MetricsFormatEndpoint bean-компонента и аннотируйте его с помощью @AutoConfigureAfter(EndpointAutoConfiguration.class). Это гарантирует, что его условия будут оценены после определения bean-объекта MetricsEndpoint.

person Andy Wilkinson    schedule 04.08.2015
comment
Я также пробую это, @ AutoConfigureAfter (EndpointAutoConfiguration.class), он тоже не работает. - person zhangzhide; 05.08.2015
comment
@AutoConfigureAfter будет работать только с классом автоконфигурации. Вы создали свой собственный, как я предлагал выше? - person Andy Wilkinson; 05.08.2015
comment
Я добавляю аннотацию @AutoConfigureAfter (EndpointAutoConfiguration.class) в класс EndpointConfiguration, она по-прежнему не работает. - person zhangzhide; 06.08.2015
comment
Не могли бы вы привести конкретный пример того, что вы описываете. Я добавил класс FlywayAutoConfiguration в spring.factories, поэтому миграция с пролетного пути выполняется до моего класса конфигурации, но этого не происходит, когда я использую AutoConfigureAfter. Мне нужно автоматически подключить FlywayMigrationInitializer, чтобы убедиться, что он делает то, что мне не нравится, прежде чем я фактически не использую bean-компонент. - person Olayinka; 16.03.2017
comment
@AndyWilkinson Ваши собственные классы конфигурации рассматриваются перед любыми классами автоконфигурации ''. Но тогда как мы можем внедрить стартовые компоненты в класс конфигурации нашего приложения? - person Whimusical; 16.02.2019
comment
@Whimusical Ответ в контексте определения bean-компонента, а не внедрения зависимостей. При определении bean-компонентов ваши собственные классы конфигурации рассматриваются перед любыми классами автоконфигурации. Когда создаются bean-компоненты и внедряются зависимости, все определенные bean-компоненты считаются одинаковыми. Это позволяет внедрить компонент из автоконфигурации в собственный компонент или класс конфигурации приложения. - person Andy Wilkinson; 18.02.2019
comment
@AndyWilkinson Ах, хорошо, это имеет смысл. Спасибо - person Whimusical; 18.02.2019
comment
Если вы пытаетесь @AutoConfigureAfter(EndpointAutoConfiguration.class), и это не работает, это потому, что, по крайней мере, в последних версиях, эта автоконфигурация не привязана к каким-либо конкретным автоконфигурациям конечных точек и не гарантирует, что конечные точки будут автоматически настроены после того, как это будет выполнено. Я столкнулся с этой проблемой с StartupEndpoint, и мне пришлось добавить конкретно @AutoConfigureAfter(StartupEndpointAutoConfiguration.class), чтобы она заработала. А если у вас несколько конечных точек, да, там будет длинный список конфигураций. - person eduard.dudar; 29.04.2021

ConditionalOnClass тоже работал.

В Javadoc сказано, что AutoConfigureAfter следует применять после других specified auto-configuration классов.

И ConditionalOnClass соответствует, когда указанные классы находятся в пути к классам. Я думаю, что это проперрер

person yiming xie    schedule 22.06.2018