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

为什么用Java配置配置的JPAPagingItemReader的destroy方法“close”失败?

微生承业
2023-03-14

我们正在尝试将Spring-Batch作业从XML配置转换为Java配置。我们正在使用Spring 4.0.1.Release和Spring Batch 2.2.1.Release。

转换一个作业后,日志文件中开始出现以下警告:

15-apr-2014 09:59:26.335[Thread-2]警告O.S.B.F.S.DisposableBeanAdapter-在名为“File reader”的bean上调用destroy方法“close”失败:org.SpringFramework.Batch.item.ItemStreamException:关闭项目读取器时出错

org.springframework.batch.item.ItemStreamException: Error while closing item reader
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.close(AbstractItemCountingItemStreamItemReader.java:131) ~[spring-batch-infrastructure-2.2.1.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25]
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25]
    at org.springframework.beans.factory.support.DisposableBeanAdapter.invokeCustomDestroyMethod(DisposableBeanAdapter.java:349) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:272) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:540) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:516) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:824) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:485) [spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:921) [spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:895) [spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:809) [spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
Caused by: java.lang.IllegalStateException: EntityManager is closed
    at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:132) ~[hibernate-entitymanager-4.2.5.Final.jar:4.2.5.Final]
    at sun.reflect.GeneratedMethodAccessor14.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25]
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:334) ~[spring-orm-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at $Proxy67.close(Unknown Source) ~[na:na]
    at org.springframework.batch.item.database.JpaPagingItemReader.doClose(JpaPagingItemReader.java:236) ~[spring-batch-infrastructure-2.2.1.RELEASE.jar:na]
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.close(AbstractItemCountingItemStreamItemReader.java:128) ~[spring-batch-infrastructure-2.2.1.RELEASE.jar:na]
    ... 13 common frames omitted
xml prettyprint-override"><batch:step id="createFile" next="insertFile">
    <batch:tasklet>
        <batch:chunk reader="fileReader" writer="fileWriter"
            commit-interval="#{jobProperties[commit_interval]}" />
    </batch:tasklet>
</batch:step>

<bean id="fileReader"
    class="org.springframework.batch.item.database.JpaPagingItemReader">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="queryString"
        value="select mt from MyTable mt where status in ('1','2','3')" />
    <property name="pageSize" value="1000" />
</bean>

Java配置是:

@Bean
public Job fileProcessJob(JobBuilderFactory jobBuilders,
        Step loadConfig,
        Step createFile,
        Step insertFile
        ) {
    return jobBuilders.get(moduleName)
            .start(loadConfig)
            .next(createFile)
            .next(insertFile)
            .build()
            .build();
}

@Bean
public ItemReader<MyTable> cetFileReader(EntityManagerFactory entityManagerFactory) {
    JpaPagingItemReader<MyTable> itemReader = new JpaPagingItemReader<MyTable>();
    itemReader.setEntityManagerFactory(entityManagerFactory);
    itemReader.setQueryString("select mt from MyTable mt where status in ('1','2','3')");
    itemReader.setPageSize(1000);
    return itemReader;
}

为什么在使用Java配置而不是XML配置时,日志中会出现此警告?

共有1个答案

叶浩荡
2023-03-14

TLDR;

Spring尝试在使用Java配置时自动推断出destroymethod(但在使用XML配置时不这样做)。要禁用此自动推断,请使用:

@bean(destroymethod=“”)

为了方便用户,容器将尝试根据@bean方法返回的对象推断destroy方法。例如,给定一个返回Apache Commons DBCP BasicDataSource的@Bean方法,容器将注意到该对象上可用的close()方法,并自动将其注册为destroyMethod。此“destroy method inference”目前仅限于检测名为“close”的公共无参数方法。该方法可以在继承层次结构的任何级别上声明,并且无论@bean方法的返回类型如何,都将被检测(即,在创建时针对bean实例本身反射性地进行检测)。

要禁用特定@bean的destroy方法推断,请指定一个空字符串作为值,例如@bean(DestroyMethod=“”)。注意,org.springframework.beans.factory.DisposableBean和java.io.closeable/java.lang.AutoCloseable接口仍然会被检测到,并调用相应的destroy/close方法。

注意:仅在其生命周期处于工厂完全控制之下的bean上调用,这对于单例总是如此,但对于任何其他范围都不保证。

@Bean(destroyMethod="")
public ItemReader<MyTable> cetFileReader(EntityManagerFactory entityManagerFactory) {
    JpaPagingItemReader<MyTable> itemReader = new JpaPagingItemReader<MyTable>();
    itemReader.setEntityManagerFactory(entityManagerFactory);
    itemReader.setQueryString("select mt from MyTable mt where status in ('1','2','3')");
    itemReader.setPageSize(1000);
    return itemReader;
}

警告不再出现了。通过在org.springframework.beans.factory.support.DisposableBeanAdapter.destroy()方法上放置一个断点并启动XML配置的作业和Java配置的作业,我能够确认这一点。

对于XML配置:

  • DisposableBeanAdapter.InvokeDisposableBean=false
  • DisposableBeanAdapter.DestroyMethod=null
  • DisposableBeanAdapter.DestroyMethodName=null
    null
  • DisposableBeanAdapter.InvokeDisposableBean=false
  • DisposableBeanAdapter.DestroyMethod=null
  • DisposableBeanAdapter.DestroyMethodName=null

基于这些观察,我得出结论:容器在通过XML配置时不会尝试推断destroy方法;但在通过Java配置时会出现这种情况。这就是为什么会出现Java配置而不是XML配置的警告。

此外,容器推断为destroyMethod的方法似乎来自org.springframework.batch.item.itemStreamSupport.close()。因此,实现通过@bean注释配置的ItemStreamSupport接口的任何bean都可能发生这种情况。

 类似资料:
  • 本文向大家介绍Nginx配置文件nginx.conf的常用配置方法,包括了Nginx配置文件nginx.conf的常用配置方法的使用技巧和注意事项,需要的朋友参考一下 Nginx使 用有两三年了,现在经常碰到有新用户问一些很基本的问题,我也没时间一一回答,今天下午花了点时间,结合自己的使用经验,把Nginx的主要配置参数说明 分享一下,也参考了一些网络的内容,这篇是目前最完整的Nginx配置参数中

  • 我有一个常春藤和人工制品设置要发布,并依赖于构建。 在Artifactory中,我有一个Ivy文件,大致如下: 当我在另一个项目中依赖这个模块时,我指定了编译配置,但IvyDE告诉我编译不存在。 在这个设置中,我得到了错误消息 “在组织#模块中找不到配置;0.277-快照:'编译'” 如果依赖conf更新为编译,我确实会得到jar- 有什么建议吗?

  • 下面的方法从 Servlet 3.0 开始添加到 ServletContext,以便启用编程方式定义 Servlet、Filter 和它们映射到的 url 模式。这些方法只能从 ServletContextListener 实现的 contexInitialized 方法或者ServletContainerInitializer 实现的 onStartup 方法进行的应用初始化过程中调用。 除了添

  • 但是,我在spring-boot文档中发现了以下内容。https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-configuration-classes.html 它赞成使用Java配置而不是XML配置。Java配置中的更改需要重新编译。然而,这让我想到为什么文档偏爱Java配置。 Internet上已经发

  • 从2.0开始Spring Security对服务层的方法的安全有了实质性的改善。他提供对JSR-250的注解安全支持象框架原生的@Secured注解一样好。从3.0开始你也可以使用新的基于表达式的注解。你可以应用安全到单独的bean,使用拦截方法元素去装饰Bean声明,或者你可以在整个服务层使用AspectJ风格的切入点保护多个bean。 EnableGlobalMethodSecurity 我们

  • 本文向大家介绍详解spring 配置的两种方式:JAVA配置和注解配置,包括了详解spring 配置的两种方式:JAVA配置和注解配置的使用技巧和注意事项,需要的朋友参考一下 众所周知,spring自从3.0开始以后,就全面推荐使用配置的方式进行代码编写了,这种方式确实可以避免了之前一个项目里面一大堆XML的情况,毕竟XML的可读性实在不怎么样,而且一会写JAVA,一会写XML,确实还是蛮麻烦的