服务器关闭期间无法停止Bean

时间:2018-02-07 18:54:43

标签: java spring

我有一个使用spring和stomp消息的war文件。一切都很好,但在关机或重启期间,我看到数百行,如:

07-Feb-2018 12:21:35.929 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.929 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.929 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.929 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.929 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.930 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.930 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.930 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.930 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.930 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.931 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.931 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.931 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.931 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.931 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.932 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.932 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.932 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.932 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.933 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:35.933 [INFO ] Stopping beans in phase 0
07-Feb-2018 12:21:35.933 [INFO ] Stopping beans in phase 2147483647
07-Feb-2018 12:21:36.394 [WARN ] Failed to stop bean 'accountEventPublisher'
java.lang.StackOverflowError: null

我的accountEventPublisher bean发布事件以允许服务器的其他部分拦截事件并对其进行操作。

这是我的accountEventPublisherBean:

@Configuration
public class AccountEventPublisherConfig {

  public static final String MULTICAST_NAME = "accountEventMulticaster";

  public static final String EVENT_PUBLISHER_NAME ="accountEventPublisher";

  @Autowired 
  private ApplicationEventPublisher publisher;

  @Bean(name=MULTICAST_NAME)
  public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
    SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
    eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
    return eventMulticaster;
  }

  @Bean(name=EVENT_PUBLISHER_NAME)
  public ApplicationEventPublisher simplePublisher() {
    return publisher;
  }
}

然后我在静态CommService中使用它来发送事件:

@Service
public class CommService {
  private static ApplicationEventPublisher accountEventPublisher;

  public static void sendEvent(ApplicationEvent event) {
    if (accountEventPublisher== null) {
      accountEventPublisher = (ApplicationEventPublisher) ApplicationContextHolder.getContext().getBean(AccountEventPublisherConfig.EVENT_PUBLISHER_NAME);
    }
    accountEventPublisher.publishEvent(event);
  }
}

以下代码拦截事件

@Component
public class FileUploadTriggerListener implements ApplicationListener<AccountTrigger> {

  @Autowired
  private PatchFileService fileService;

  @Autowired
  private ApplicationLogService appLogService;

  @Autowired
  private ExecutorService executor;

  @Override
  public void onApplicationEvent(AccountTrigger trigger) {
    if (trigger.getType() != TriggerType.FILE_UPLOADED) return;
    executor.schedule(new Runnable() {
      @Override
      public void run() {
         System.out.println("Hello World");
      });
    }
  }
}

以下是扩展ApplicationEvent

的类
public class AccountTrigger extends ApplicationEvent {

  private static final long serialVersionUID = 2139401946845273241L;

  private Integer userId;

  private TriggerType type;

  private List<Object> resources = new ArrayList<>();

  public Integer getUserId() {
    return userId;
  }

  public void setUserId(Integer userId) {
    this.userId = userId;
  }

  public List<Object> getResources() {
    return resources;
  }

  public void setResources(List<Object> resources) {
    this.resources = resources;
  }

  public TriggerType getType() {
    return type;
  }

  public void setType(TriggerType type) {
    this.type = type;
  }
}

所有ApplicationEvent都是AccountTrigger类型,带有枚举触发器类型。我现在使用的唯一触发器类型是FILE_UPLOAD

我不确定为什么这个豆子不会停止以及我做错了什么。

2 个答案:

答案 0 :(得分:1)

因为它不适合评论而移到这里。我无法证明,但似乎正在发生的事情:

AccountEventPublisherConfig.publisher是应用程序上下文。

但是,AccountEventPublisherConfig.simplePublisher()创建了一个名为“accountEventPublisher”的托管bean,它实际上是应用程序上下文的别名。

当停止应用程序时,上下文正在尝试关闭“accountEventPublisher”bean,它本身就是这样。这可能导致以StackOverflowError结束的递归调用。

尝试删除“accountEventPublisher”bean的定义。在服务中:

@Autowired 
private ApplicationEventPublisher accountEventPublisher;

并直接发布:

public static void sendEvent(ApplicationEvent event) {
     accountEventPublisher.publishEvent(event);
}

答案 1 :(得分:0)

我能够解决问题。我最终不得不将配置类更改为组件并实现ApplicationEventPublisherAware

@Component
public class AccountEventPublisher implements ApplicationEventPublisherAware {

  public static final String EVENT_PUBLISHER_NAME ="accountEventPublisher";

  private ApplicationEventPublisher publisher;

  public void publishEvent(AccountTrigger event) {
    publisher.publishEvent(event);
  }

  @Override
  public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    publisher = applicationEventPublisher;
  }
}

然后我修改了对其他发布者的引用,它似乎有效。不再收到错误。