JPA 使用 hibernate,将 AvailableSettings.USE_CLASS_ENHANCER 属性设置为 true 会引发 java.lang.ClassCircularityError

Bas*_*sit 5 spring-mvc hibernate-entitymanager maven-3 load-time-weaving tomcat8

我设置了 spring 应用程序。一切正常。但是当我将 Hibernate AvailableSettings.USE_CLASS_ENHANCER 属性设置为 true 时,我得到java.lang.ClassCircularityError.

这是我的配置。首先,我使用的是 log4j2。这是我的 log4j2 文件。

log4j-xinclude-appenders.xml:

<appenders>
    <Console name="Console" target="SYSTEM_OUT">
        <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>

    <RollingFile name="WroxFileAppender" fileName="${filename}.log" filePattern="${filename}-%d{MM-dd-yyyy}-%i.log">      
        <PatternLayout pattern= "%d{HH:mm:ss.SSS} [%t] %X{id} %X{username} %-5level %c{36} %l: %msg%n" />

        <Policies>
            <SizeBasedTriggeringPolicy size="10 MB" />
        </Policies>

        <DefaultRolloverStrategy min="1" max="4" />
    </RollingFile>      
</appenders>
Run Code Online (Sandbox Code Playgroud)

log4j-xinclude-loggers.xml:

<loggers>
    <root level="warn">
        <!--  
        <appender-ref ref="Console" />
        <appender-ref ref="WroxFileAppender" />
        -->
    </root>

    <logger name="my.package" level="info" />
    <logger name="org.apache" level="info" />
    <logger name="org.springframework" level="info" /> 
    <logger name="org.hibernate" level="info" />
</loggers>
Run Code Online (Sandbox Code Playgroud)

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>

<configuration xmlns:xi="http://www.w3.org/2001/XInclude" status="WARN">

    <Properties>
        <Property name="filename">D:/Basit/apache-tomcat-8.0.26/logs/support</Property>
    </Properties>

    <xi:include href="log4j-xinclude-appenders.xml" />
    <xi:include href="log4j-xinclude-loggers.xml" />
</configuration>
Run Code Online (Sandbox Code Playgroud)

这是我的 Spring 设置

@Order(1)
public class FrameworkBootstrap implements WebApplicationInitializer {
    private static final Logger log = LogManager.getLogger();
    ....

    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(RootContextConfiguration.class);
    container.addListener(new ContextLoaderListener(rootContext));

    AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
    webContext.register(WebServletContextConfiguration.class);
    ServletRegistration.Dynamic dispatcher = container.addServlet("springWebDispatcher", new DispatcherServlet(webContext));
    dispatcher.setLoadOnStartup(1);
    dispatcher.setMultipartConfig(new MultipartConfigElement(null, 20_971_520L, 41_943_040L, 512_000));
    dispatcher.addMapping("/");
    ....
Run Code Online (Sandbox Code Playgroud)

根上下文配置

@Configuration
@EnableLoadTimeWeaving
@ComponentScan(.. )
@Import({AsyncConfig.class, PersistenceConfig.class,  EmailConfig.class, SecurityConfiguration.class })
public class RootContextConfiguration {
    private static final Logger log = LogManager.getLogger();

    @Bean
    public MessageSource messageSource() {
        ....
    }

    ....
}
Run Code Online (Sandbox Code Playgroud)

持久化配置

@Configuration
@EnableTransactionManagement(mode = AdviceMode.PROXY, proxyTargetClass = false, order = 2)
@EnableJpaRepositories(...)
public class PersistenceConfig {

    @Inject 
    private LoadTimeWeaver loadTimeWeaver;

    @Bean(destroyMethod = "close")
    public DataSource dataSource() {
         JndiDataSourceLookup lookup = new JndiDataSourceLookup();
         return lookup.getDataSource("jdbc/dev");
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {  

        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabasePlatform("org.hibernate.dialect.SQLServer2012Dialect");
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(adapter);
        factory.setDataSource(this.dataSource());
        factory.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
        factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
        factory.setValidationMode(ValidationMode.NONE);
        factory.setLoadTimeWeaver(this.loadTimeWeaver); // TODO: remove when SPR-10856 fixed
        factory.setJpaPropertyMap(this.jpaHibernateProperties());
        return factory;
    }

    private Map<String, Object> jpaHibernateProperties() {
        Map<String, Object> properties = new Hashtable<>();
         properties.put(AvailableSettings.SCHEMA_GEN_DATABASE_ACTION, "none");
         properties.put(AvailableSettings.USE_CLASS_ENHANCER, "true");
         ....
         return properties; 
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我取消注释我伐木工人在log4j-xinclude-loggers.xml

<root level="warn">
    <appender-ref ref="Console" />
    <appender-ref ref="WroxFileAppender" />  
</root>
Run Code Online (Sandbox Code Playgroud)

然后我得到这个异常跟踪

17:12:00.572 [localhost-startStop-1] INFO  org.hibernate.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
Sep 15, 2015 5:12:00 PM org.apache.catalina.loader.WebappClassLoaderBase addTransformer
INFO: Added class file transformer [Standard ClassFileTransformer wrapping JPA transformer:     org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl@2cf5594c] to web application [LMS-Java8].
2015-09-15 17:12:00,986 ERROR Recursive call to appender WroxFileAppender
Sep 15, 2015 5:12:01 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.ClassCircularityError: org/apache/logging/log4j/core/impl/ThrowableProxy
at         org.apache.logging.log4j.core.impl.Log4jLogEvent.getThrownProxy(Log4jLogEvent.java:323)
at     org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter.format(ExtendedThrowablePatternConverter.java:64)
at     org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:36)
at     org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:196)
at     org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:55)
at     org.apache.logging.log4j.core.layout.AbstractStringLayout.toByteArray(AbstractStringLayout.java:71)
at     org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:108)
at     org.apache.logging.log4j.core.appender.RollingFileAppender.append(RollingFileAppender.java:88)
at     org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:99)
at     org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:430)
at     org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:409)
at     org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:412)
at     org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:367)
at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:112)
at     org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:722)
at     org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:693)
at org.apache.logging.log4j.jcl.Log4jLog.error(Log4jLog.java:116)
at     org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:358)
at     org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at     org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4727)
at     org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at     org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

17:12:01.046 [localhost-startStop-1] INFO      org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Closing Root WebApplicationContext: startup date [Tue Sep 15 17:11:57 PKT 2015]; root of context hierarchy
Sep 15, 2015 5:12:01 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: One or more listeners failed to start. Full details will be found in the appropriate container log file
Sep 15, 2015 5:12:01 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/LMS-Java8] startup failed due to previous errors
Sep 15, 2015 5:12:01 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Sep 15, 2015 5:12:01 PM org.apache.catalina.core.StandardContext listenerStop
SEVERE: Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.ClassCircularityError: org/apache/logging/log4j/core/impl/ThrowableProxy
at org.apache.logging.log4j.core.impl.Log4jLogEvent.getThrownProxy(Log4jLogEvent.java:323)
at org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter.format(ExtendedThrowablePatternConverter.java:64)
at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:36)
at org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:196)
at org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:55)
at org.apache.logging.log4j.core.layout.AbstractStringLayout.toByteArray(AbstractStringLayout.java:71)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:108)
at org.apache.logging.log4j.core.appender.RollingFileAppender.append(RollingFileAppender.java:88)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:99)
at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:430)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:409)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:412)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:367)
at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:112)
at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:722)
at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:693)
at org.apache.logging.log4j.jcl.Log4jLog.error(Log4jLog.java:116)
at org.springframework.orm.jpa.persistenceunit.ClassFileTransformerAdapter.transform(ClassFileTransformerAdapter.java:66)
at org.apache.catalina.loader.WebappClassLoaderBase.findResourceInternal(WebappClassLoaderBase.java:2648)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2428)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1301)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1166)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:954)
at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:925)
at org.springframework.web.context.ContextLoader.closeWebApplicationContext(ContextLoader.java:583)
at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:116)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4774)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5390)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)

为什么有线2015-09-15 17:12:00,986 ERROR Recursive call to appender WroxFileAppender?看到它的模式与我在附加程序中定义的不同。

现在,如果我注释掉我的WroxFileAppenderThen,我的Console appender.. 如果我注释掉我的两个附件。然后我得到以下异常跟踪

INFO: Initializing Spring root WebApplicationContext
Sep 15, 2015 5:20:08 PM org.apache.catalina.loader.WebappClassLoaderBase addTransformer
INFO: Added class file transformer [Standard ClassFileTransformer wrapping JPA transformer: org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl@781e38b3] to web application [LMS-Java8].
Sep 15, 2015 5:20:08 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: Could not weave class [org/springframework/util/ConcurrentReferenceHashMap$EntrySet]
at org.springframework.orm.jpa.persistenceunit.ClassFileTransformerAdapter.transform(ClassFileTransformerAdapter.java:68)
at org.apache.catalina.loader.WebappClassLoaderBase.findResourceInternal(WebappClassLoaderBase.java:2648)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2428)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1301)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1166)
at org.springframework.util.ConcurrentReferenceHashMap.entrySet(ConcurrentReferenceHashMap.java:366)
at java.util.AbstractMap$1$1.<init>(AbstractMap.java:332)
at java.util.AbstractMap$1.iterator(AbstractMap.java:331)
at org.springframework.beans.CachedIntrospectionResults.clearClassLoader(CachedIntrospectionResults.java:164)
at org.springframework.context.support.AbstractApplicationContext.resetCommonCaches(AbstractApplicationContext.java:874)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:559)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4727)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCircularityError: org/hibernate/bytecode/enhance/spi/Enhancer
at org.hibernate.jpa.internal.enhance.EnhancingClassTransformerImpl.transform(EnhancingClassTransformerImpl.java:38)
at org.springframework.orm.jpa.persistenceunit.ClassFileTransformerAdapter.transform(ClassFileTransformerAdapter.java:56)
... 23 more

INFO: Closing Spring root WebApplicationContext
Sep 15, 2015 5:36:27 PM org.apache.catalina.core.StandardContext listenerStop
SEVERE: Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: Could not weave class [org/springframework/web/context/ContextCleanupListener]
at     org.springframework.orm.jpa.persistenceunit.ClassFileTransformerAdapter.transform(ClassFileTransformerAdapter.java:68)
at org.apache.catalina.loader.WebappClassLoaderBase.findResourceInternal(WebappClassLoaderBase.java:2648)
....
Run Code Online (Sandbox Code Playgroud)

为什么我会收到这些 ClassCircularityError 错误。我做错了什么?我正在使用Maven, Java 8 update 60, Spring 4.2.1, Hibernate 5.0.2, Spring-data-JPA 1.9.0. Maven 依赖是否会导致这些问题?

如果我将属性设置为falselikeproperties.put(AvailableSettings.USE_CLASS_ENHANCER, "false");那么一切正常。我想使用它是因为(mappedBy)JPA 的反面导致的延迟加载问题。

谢谢

编辑

我的POM

<properties>
    <java-version>1.8</java-version>
    <javax.annotation-api.version>1.2</javax.annotation-api.version>
    <javax.persistence.version>2.1.0</javax.persistence.version>
    <javax.transaction-api.version>1.2</javax.transaction-api.version>
    <spring.framework.version>4.2.1.RELEASE</spring.framework.version>
    <spring-ws-core.version>2.2.2.RELEASE</spring-ws-core.version>
    <xmlschema-core.version>2.2.1</xmlschema-core.version>
    <spring.security.version>4.0.2.RELEASE</spring.security.version>
    <spring-data-jpa.version>1.9.0.RELEASE</spring-data-jpa.version>
    <wsdl4j.version>1.6.3</wsdl4j.version>
    <commons-lang3.version>3.4</commons-lang3.version>
    <org.apache.velocity-version>1.7</org.apache.velocity-version>
    <validation-api.version>1.1.0.Final</validation-api.version>
    <hibernate-validator.version>5.2.2.Final</hibernate-validator.version>
    <hibernate-entitymanager.version>5.0.2.Final</hibernate-entitymanager.version>
    <sqljdbc4.version>4.0</sqljdbc4.version>
    <javassist.version>3.20.0-GA</javassist.version>
    <jboss-logging.version>3.3.0.Final</jboss-logging.version>
    <junit.version>4.12</junit.version>
    <jackson.version>2.6.2</jackson.version> 
    <log4j.version>2.4</log4j.version>
    <slf4j-api.verion>1.7.12</slf4j-api.verion>
    <javax.mail.version>1.5.4</javax.mail.version>

    <tomcat-directory-path>D:\Basit\apache-tomcat-8.0.27</tomcat-directory-path>
</properties>

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>${commons-lang3.version}</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson.version}</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${jackson.version}</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j.version}</version>
        <scope>compile</scope>
    </dependency&g