我们有一个带有调度程序的spring boot项目,它以固定的时间间隔从数据库中读取数据。
在使用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() { } }
这里的问题是,为什么Spring Boot在构建项目时运行调度程序任务,为什么它会引发上述异常?
在 Spring Boot中 ,当您进行Maven构建时,默认情况下会运行测试用例。在这种情况下, 将 运行 集成测试 脚本,它将尝试连接到数据库。由于您没有任何要作为项目集成测试一部分的内容。一种可能的解决方案是将您的 ProvisioningApplicationTests 类声明为 abstract 。这将限制对 ProvisioningApplicationTests 类的实例创建。
@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>
这将排除在构建项目时要执行的集成测试类。 maven-surefire-plugin 用于运行单元测试。 maven-failsafe-plugin 用于运行集成测试。使用这种方法时,请确保所有集成类文件名都以 ‘IT’ 结尾。例如UserTestIT.java