2012-07-20 70 views
3

我有AOP彈簧應用程序中使用CGLIB代理的啓用日誌記錄:CGLIB彈簧拋出IllegalAccessError

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:aop="http://www.springframework.org/schema/aop" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 
<aop:aspectj-autoproxy proxy-target-class="true"/> 

<bean id="loggingPointcuts" class="com.coverall.integration.commons.logging.LoggingPointcuts"/> 

<bean id="loggingAspect" class="com.coverall.integration.commons.logging.LoggingAspect"/> 
</beans> 

我使用CGLIB的節點p-2.2.2.jar彈簧3.1.1 這種運作良好在tomcat或碼頭。然而,當我部署在此OC4J(與JDK1.6)我得到以下錯誤: 其試圖代理類 - ComponentRegistryImpl是包私有

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.company.int.components.core.registration.ComponentRegistryImpl]: Common causes of this problem include using a final class or a non-visible class; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null 
    at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:207) ~[org.springframework.aop-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112) ~[org.springframework.aop-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:476) ~[org.springframework.aop-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362) ~[org.springframework.aop-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322) ~[org.springframework.aop-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407) [org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461) [org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) [org.springframework.beans-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    ... 40 common frames omitted 
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null 
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237) ~[cglib-nodep-2.2.2.jar:na] 
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) ~[cglib-nodep-2.2.2.jar:na] 
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) ~[cglib-nodep-2.2.2.jar:na] 
    at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201) ~[org.springframework.aop-3.1.1.RELEASE.jar:3.1.1.RELEASE] 
    ... 47 common frames omitted 
Caused by: java.lang.reflect.InvocationTargetException: null 
    at sun.reflect.GeneratedMethodAccessor12.invoke(Unknown Source) ~[na:na] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_20] 
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_20] 
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384) ~[cglib-nodep-2.2.2.jar:na] 
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219) ~[cglib-nodep-2.2.2.jar:na] 
    ... 50 common frames omitted 
Caused by: java.lang.IllegalAccessError: class com.company.int.components.core.registration.ComponentRegistryImpl$$EnhancerByCGLIB$$730712da cannot access its superclass com.company.int.components.core.registration.ComponentRegistryImpl 
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.6.0_20] 
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) ~[na:1.6.0_20] 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:616) ~[na:1.6.0_20] 
    ... 55 common frames omitted 

回答

15

我不知道OC4J,但我們打在JBoss 6上完全相同的錯誤。

通常情況下,CGLIB可以增強(代理)程序包私有類。如你所見,這在Jetty & Tomcat上工作正常。但是,它在默認的JBoss 6 classloader安裝程序中不起作用。

問題基本上是Spring指示CGLIB使用與目標類(超類com.company.int.components.core.registration.ComponentRegistryImpl)不同的類加載器來創建代理類(子類com.company.int.components.core.registration.ComponentRegistryImpl$$EnhancerByCGLIB$$730712da)。因此,雖然這些類位於相同的文本包中,但它們實際上是在運行時在不同的包中創建的(因爲它們位於不同的類加載器中)。

CGLIB默認在與代理目標相同的類加載器中定義代理類。但是,Spring覆蓋了CGLIB增強器使用的類加載器。從org.springframework.aop.framework.Cglib2AopProxy.getProxy(ClassLoader)

  // Configure CGLIB Enhancer... 
      Enhancer enhancer = createEnhancer(); 
      if (classLoader != null) { 
       enhancer.setClassLoader(classLoader); 
       if (classLoader instanceof SmartClassLoader && 
         ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { 
        enhancer.setUseCache(false); 
       } 
      } 

跟蹤該類加載器的數據流示出了它來自對Bean工廠本身,其默認爲Thread.currentThread().getContextClassLoader()(在org.springframework.util.ClassUtils.getDefaultClassLoader())中定義的類加載器。

在理智的servlet容器(如Jetty和Tomcat)中,上下文類加載器與加載所有應用程序類(在WEB-INF/lib或WEB-INF/classes中)的類加載器相同。但是,在JBoss 6中(我猜測OC4J),這兩個不一樣。上下文類加載器實際上是webapp類加載器的子代。它實際上沒有定義任何類,只是將所有事情委託給父類。在JBoss中,上下文類加載器是WebCtxLoader$ENCLoader的一個實例)。

我們使用的解決方法是覆蓋您的WebApplicationContextBeanFactory)的類加載器,以便使用「真正的」webapp類加載器。您需要在web.xml添加類作爲上下文偵聽

public class MyContextLoaderListener extends ContextLoaderListener { 
    @Override 
    protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) { 
     ClassLoader classLoader = getClass().getClassLoader(); 
     logger.debug("Overriding WebApplicationContext classloader from %s to %s", applicationContext.getClassLoader(), classLoader); 
     ((DefaultResourceLoader) applicationContext).setClassLoader(classLoader); 
    } 
} 

<listener> 
    <listener-class>com.company.MyContextLoaderListener</listener-class> 
</listener> 
+0

我們通過建立我們自己的ContextLoaderListener(加載您MyContextLoaderListener實現本身就是我們想要的類加載器)這樣做感謝Eric,這對我有效。我們還決定從OC4J轉向Weblogic,因爲對OC4J的支持已經停止。希望我不會在weblogic上需要這種解決方法:) – 6ton 2013-01-03 06:13:23

+0

我們終於在weblogic上部署了我們的應用程序,並遇到了同樣的問題(以前在OC4J上看過)。我用這個解決方案,它的工作!再次感謝:) – 6ton 2013-05-01 12:20:06

+0

非常感謝,完美! – 2017-09-03 19:04:02

相關問題