Spring 使用 scheduler-BeanCreationNotAllowedException 启动:创建名称为 'entityManagerFactory' 的 bean 时出错:不允许创建单例 bean

Spring boot with scheduler-BeanCreationNotAllowedException: Error creating bean with name 'entityManagerFactory': Singleton bean creation not allowed

我们有一个 spring 带有调度程序的启动项目,它以固定的时间间隔从数据库中读取数据。

当使用 Maven 从 STS 构建项目时,我们在控制台中遇到错误 虽然它是 运行 测试用例 即使最终构建状态是成功的。

org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'entityManagerFactory': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:216) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:523) at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:276) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:162) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:145) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy70.findByTraIdAndTransactionNameAndExecutionTime(Unknown Source) at

申请文件

@SpringBootApplication
@PropertySource("classpath:application.properties")
@EnableScheduling
public class ProvisioningApplication {

    public static void main(String[] args) {

        SpringApplication.run(ProvisioningApplication.class, args);

    }
}

调度程序文件

BusinessService有读取数据库的逻辑

@Component
public class SchedulerJob {

    @Autowired
    BusinessService service;

    @Scheduled(fixedRate=300000) //5mnts
    public void schdeule() {
        service.startService();

    }
}

测试文件

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ProvisioningApplication.class)
public class ProvisioningApplicationTests {

    @Test
    public void contextLoads() {
    }

}

这里的问题是为什么springboot在构建项目的时候运行调度任务,为什么会抛出上面的异常?

Spring Boot 中,当您进行 maven 构建时,测试用例默认为 运行。在这种情况下,集成测试 脚本是 运行,它将尝试连接到您的数据库。 由于您没有任何东西可以作为项目集成测试的一部分执行。 一种可能的解决方案是将您的 class ProvisioningApplicationTests 声明为 abstract。 这将限制 ProvisioningApplicationTests class.

的实例创建
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ProvisioningApplication.class)
public abstract class ProvisioningApplicationTests {
    @Test
    public void contextLoads() {
    }
  }

解决此问题的另一种方法是在 pom.xml

中包含以下代码
<plugins>
   <plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
     <skipTests>false</skipTests>
     <excludes>
      <exclude>**/*IT.java</exclude>
     </excludes>
    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <executions>
     <execution>
      <id>integration-test</id>
      <goals>
       <goal>integration-test</goal>
      </goals>
      <configuration>
       <skipTests>true</skipTests>
       <includes>
        <include>**/*IT.class</include>
       </includes>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>

这将排除在构建您的项目时要执行的集成测试 classes。 maven-surefire-plugin 用于 运行 单元测试。 maven-failsafe-plugin 用于 运行 集成测试。使用此方法时,请确保所有集成 class 文件名都以 'IT' 结尾。例如。 UserTestIT.java