监听器未接收ApplicationPreparedEvent

时间:2017-08-23 17:28:11

标签: java spring-boot

我有一个Spring Boot 1.5.4应用程序,它可以在启动时注册日志appender,这要归功于一个监听器,它可以使用这里解释的解决方案register custom log appender in spring boot starter。监听器是我编写的启动器的一部分,我的@EnableAutoConfiguration应用程序按预期工作。

我有2个其他应用程序使用相同的Spring Boot版本,我想使用相同的启动器。我相信它们与工作应用程序或多或少具有相同的配置,但 onApplicationEvent 方法永远不会被调用,因此我的日志追加器未注册。下面是我的配置+监听器类。

我在supportsEventType方法中放了一个断点,并且在那里传递的所有事件都没有,就像在我的第一个应用程序中一样是ApplicationPreparedEvent类型。

@Configuration
@EnableConfigurationProperties(MetricProperties.class)
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class MetricsAutoConfiguration implements GenericApplicationListener {

private final MetricProperties metricProperties;
private boolean addedCustomAppender = false;

public MetricsAutoConfiguration(MetricProperties metricProperties) {
    this.metricProperties = metricProperties;
}


@Bean
@ConditionalOnProperty(name = "metrics.enabled", havingValue = "true")
public EventsPublisher metricPublisher() {
    metricProperties.validate();
    return new EventsPublisher(metricProperties);
}



@Override

public void onApplicationEvent(ApplicationEvent event) {
    if (metricProperties.isEnabled() && !addedCustomAppender) {

        ApplicationPreparedEvent applicationEvent = (ApplicationPreparedEvent) event;
        EventsPublisher eventPublisher = applicationEvent.getApplicationContext().getBean(EventsPublisher.class);

    //register the log appender
    // removed for brevity

        addedCustomAppender = true;
    }
}


@Override
public int getOrder() {
    // this must be higher than LoggingApplicationListener.DEFAULT_ORDER
    return Ordered.HIGHEST_PRECEDENCE + 21;
}

@Override
public boolean supportsEventType(ResolvableType eventType) {

    return  ApplicationPreparedEvent.class.isAssignableFrom(eventType.getRawClass());
}

@Override
public boolean supportsSourceType(Class<?> sourceType) {
    return true;
}

}

在它运行的应用程序中,我看到构建了3个ApplicationPreparedEvent,并且supportsEventsType返回true两次(并且onApplicationEvent被调用两次,具有相同的事件):这发生在构建第三个ApplicationPreparedEvent之后,而不是之前。 / p>

应用程序注释是:

@SpringBootApplication
@EnableZuulProxy
@EnableBinding(OutPutChannel.class)
@EnableAutoConfiguration(exclude = MetricsDropwizardAutoConfiguration.class)
@IntegrationComponentScan

对于其不起作用的其他应用程序,我发现在启动时只构建了1个ApplicationPreparedEvent并且它不会触发侦听器,因为调用supportsEventsType但从不返回true:

  • 对于第一个应用程序,它通过以下方式连续调用:

    • org.springframework.boot.builder.ParentContextApplicationContextInitializer $ ParentContextAvailableEvent(两次)
    • org.springframework.context.event.ContextRefreshedEvent(两次)
    • org.springframework.boot.context.event.ApplicationReadyEvent(两次)

应用注释是:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,
    DataSourceTransactionManagerAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class,
    MetricsDropwizardAutoConfiguration.class,
    JestAutoConfiguration.class})
  • 对于第二个应用:
    • org.springframework.context.event.ContextRefreshedEvent(两次)
    • org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent(两次)
    • org.springframework.boot.context.event.ApplicationReadyEvent(两次)
带注释的

@SpringBootApplication
@EnableAutoConfiguration(exclude = JestAutoConfiguration.class)

对于两者而言,没有跟踪ApplicationPreparedEvent&#34;测试&#34;听众......

任何提示?我很困惑......

由于

1 个答案:

答案 0 :(得分:0)

逐个删除/添加依赖项并进行每次比较后,我发现是什么使它工作(或不是),即使我不明白为什么......

为了我的应用程序正确注册监听器,我需要依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency> 

它没有多大意义,但是有一些东西可以很早地生成ApplicationPreparedEvent,之前 Spring横幅显示在日志中。在横幅显示和日​​志行

之后构建第二个事件
The following profiles are active: XXXX

使用该配置,我可以看到我的侦听器接收第二个事件并进行配置。

如果我将依赖项移除到spring-cloud-starter-feign,那么只有一个ApplicationPreparedEvent被构建,在横幅显示之后(之前没有任何内容)并且我的监听器永远不会收到它。

在挖掘依赖树后,我将其缩小到spring-cloud-context (我使用1.2.2.RELEASE)。那里有一些东西触发了非常早期的ApplicationPreparedEvent,它使我的监听器能够被注册。我甚至排除了它必须确定的唯一依赖:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-context</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-crypto</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

如果有人对此有更多信息或更好的方法来实现这一目标,请随时发表评论

相关问题