当前位置: 首页 > 知识库问答 >
问题:

Springboot@PostCon构成t方法被调用两次

岳正阳
2023-03-14

我注意到我的bean在jar中的spring boot应用程序上一次调用@PostConstructinit()@Scheduled两次。下面是两次初始化的示例bean。

@Component
@ConfigurationProperties(prefix = "task")
public class CancelTask {
    private static Logger log = LoggerFactory.getLogger(CancelTask.class);

    @PostConstruct
    public void init() {
        log.info("CancelTask init:{}", this);
        printStackTrace();
    }

    private void printStackTrace() {
        StackTraceElement[] stackElements = new Throwable().getStackTrace();
        StringBuilder sb = new StringBuilder();
        if (stackElements != null) {
            for (int i = 0; i < stackElements.length; i++) {
                sb.append("" + stackElements[i] + "\n");
            }
        }
        log.info(sb.toString());
    }

    @Scheduled(cron = "0 */1 * * * ?")
    public void closeTask() {
        log.info("close task start....{}", this);
        printStackTrace();
    }
}

@PostConstruct@Scheduled被调用两次:

从日志中,PostConconfit首先被调用:

[INFO] [2017-12-20 19:54:29,872] [c.n.m.workbench.daemon.task.CancelTask]: CancelTask init:com.netease.mail.workbench.daemon.task.CancelTask@34451ed8
[INFO] [2017-12-20 19:54:29,873] [c.n.m.workbench.daemon.task.CancelTask]: com.netease.mail.workbench.daemon.task.CancelTask.printStackTrace(CancelTask.java:85)
com.netease.mail.workbench.daemon.task.CancelTask.init(CancelTask.java:81)
  sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366)
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311)
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134)
com.netease.mail.workbench.Application.main(Application.java:61)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)

第二个是:

[INFO] [2017-12-20 19:54:36,148] [c.n.m.workbench.daemon.task.CancelTask]: CancelTask init:com.netease.mail.workbench.daemon.task.CancelTask@34451ed8
[INFO] [2017-12-20 19:54:36,150] [c.n.m.workbench.daemon.task.CancelTask]: com.netease.mail.workbench.daemon.task.CancelTask.printStackTrace(CancelTask.java:85)
com.netease.mail.workbench.daemon.task.CancelTask.init(CancelTask.java:81)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366)
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311)
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:400)
org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.rebind(ConfigurationPropertiesRebinder.java:107)
org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.rebind(ConfigurationPropertiesRebinder.java:90)
org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.onApplicationEvent(ConfigurationPropertiesRebinder.java:138)
org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.onApplicationEvent(ConfigurationPropertiesRebinder.java:51)
org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration.afterSingletonsInstantiated(ConfigurationPropertiesRebinderAutoConfiguration.java:79)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:781)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134)
com.netease.mail.workbench.Application.main(Application.java:61)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)

@Scheduled被调用了两次一次:

[INFO] [2017-12-20 19:57:00,006] [c.n.m.workbench.daemon.task.CancelTask]: close task start....com.netease.mail.workbench.daemon.task.CancelTask@34451ed8
[INFO] [2017-12-20 19:57:00,006] [c.n.m.workbench.daemon.task.CancelTask]: close task start....com.netease.mail.workbench.daemon.task.CancelTask@34451ed8

当我删除@ConfigurationProperties时,@PostConstrt@Schedula只被调用了一次。我非常确定取消任务类只有一个实例。

共有1个答案

魏波娃
2023-03-14

这与Spring的云一点关系也没有(一些评论建议),因为我可以在没有它的情况下重现这种行为。

这是因为您正在为CancelTask创建两个bean。一个是由@Component创建的(由@ComponentScan扫描),另一个是因为@ConfigurationProperties而创建的(通过@enableCigurationproperties(CancelTask.class)启用)。

如果在本地运行相同的示例,则会得到不同的实例ID:

com.example.demo.CancelTask: CancelTask init:com.example.demo.SomethingProperties@273f65d9
com.example.demo.CancelTask: CancelTask init:com.example.demo.SomethingProperties@6066ff52

您不应该在单个Spring组件中混合应用程序特性和配置架构体系。您应该将这个组件分成两个;经验法则:如果您不能命名您的配置属性类某些属性,那么它可能做得比它应该做的要多。

由于配置属性是bean,所以可以将它们注入任何其他组件中。

 类似资料:
  • 我试图从配置包加载YML文件,但每当我使用@Value(“${..}”)注释@PostConstruct方法期间,它为空,导致指针为空。我需要@PostConstruct一次加载所有文件。 对如何缓解这个问题有什么想法吗? 硬编码directoryPath工作正常,但如果是硬编码的,我将无法使用测试配置文件,因为directoryPath是硬编码到主资源文件夹而不是测试资源文件夹的。 YML文件:

  • 我是个新手。我读了这个问题,但没有解决我的问题。我认为我对组件的理解是错误的。我的组件及其父组件如下所示:父组件: } 孩子: } 和索引。js: 首次安装后,控制台写入"id"两次。我不明白为什么?

  • 问题内容: 我在Go中关注一个简单的Web服务器示例。 我插入了一条语句,使生成的代码如下所示: 问题是,每当我在Web浏览器中加载端口8000时,此函数就会被调用两次。这是一个问题,因为我打算在每次页面访问时增加一个计数器。通过这种行为,计数器将增加两次。OTOH,如果我这样做,它只会被调用一次。 我觉得我在这里失踪真的很愚蠢。 问题答案: 只需记录请求。您将意识到您的浏览器还请求/favico

  • 我的react组件的构造函数被调用了两次,但我不知道为什么。我正在使用react redux存储我的应用程序的语言。我有一个基于浏览器语言设置默认语言的函数。LoginPage是第一个获得render的组件,因此我在其构造函数中调用了我的函数。基本上,它所做的就是比较并分派一个动作。当我用redux开发工具检查我的状态时,我看到它被调度了两次。我在构造函数中打印了虚拟数据,它也打印了两次。 登录页

  • 问题内容: 我在python中遇到了一个奇怪的错误,其中将类的方法用作工厂会导致实例化类的方法被调用两次。 最初的想法是使用母类的方法根据所传递的参数返回其孩子之一的特定实例,而不必在类外声明工厂函数。 我知道使用工厂功能将是在此处使用的最佳设计模式,但是在项目的这一点上更改设计模式将非常昂贵。因此,我的问题是:在这种模式中,是否有办法避免重复调用而仅获得单个调用? 任何帮助,不胜感激。 问题答案

  • 问题内容: 注意:这旨在作为常见问题的规范答案。 我有一个带有字段()的Spring 类(),但是该字段是我尝试使用它时所用的。日志显示同时创建了bean和bean,但是每当尝试在服务bean上调用方法时,我都会得到一个。Spring为什么不自动接线该领域? 控制器类: 服务等级: 应该自动连接的服务bean,但不是: 当我尝试时,出现以下异常: 问题答案: 带注释的字段是因为Spring不知道您