gpt4 book ai didi

proxy - 带 Spring 的 CGLIB 抛出 IllegalAccessError

转载 作者:行者123 更新时间:2023-12-01 07:07:30 30 4
gpt4 key购买 nike

我有一个启用了 aop 的 spring 应用程序,使用 cglib 代理进行日志记录:

<?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-nodep-2.2.2.jar 和 spring 3.1.1
这在 tomcat 或 jetty 中运行良好。但是,当我在 OC4J(使用 jdk1.6)上部署它时,我收到以下错误:
它试图代理的类 - ComponentRegistryImpl 是包私有(private)的
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

最佳答案

我不确定 OC4J,但我们在 JBoss 6 上遇到了完全相同的错误。

通常,CGLIB 可以增强包私有(private)的(代理)类。正如您所观察到的,这在 Jetty & Tomcat 上运行良好。但是,它在默认的 JBoss 6 类加载器设置中不起作用。

问题基本上是Spring指示CGLIB使用与目标类(父类(super class),com.company.int.components.core.registration.ComponentRegistryImpl$$EnhancerByCGLIB$$730712da)不同的类加载器创建代理类(子类,com.company.int.components.core.registration.ComponentRegistryImpl)。因此,虽然这些类在同一个文本包中,但它们实际上是在运行时在不同的包中创建的(因为它们位于不同的类加载器中)。

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);
}
}

跟踪该类加载器的数据流显示它来自 BeanFactory 本身定义的类加载器,默认为 Thread.currentThread().getContextClassLoader() (在 org.springframework.util.ClassUtils.getDefaultClassLoader() 中)。

在健全的 servlet 容器(如 Jetty 和 Tomcat)中,上下文类加载器与加载所有应用程序类(在 WEB-INF/lib 或 WEB-INF/classes 中)的类加载器相同。但是,在 JBoss 6(我猜是 OC4J)中,这两者并不相同。上下文类加载器实际上是 webapp 类加载器的子类。它实际上没有定义任何类,只是将所有内容委托(delegate)给父级。在 JBoss 中,上下文类加载器是 WebCtxLoader$ENCLoader 的一个实例。 )。

我们使用的解决方法是覆盖 WebApplicationContext 的类加载器。 ( BeanFactory ) 以便使用“真正的”webapp 类加载器。我们通过创建自己的 ContextLoaderListener 来做到这一点。 (加载您的 MyContextLoaderListener 实现本身的类加载器是我们想要的):

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);
}
}

您需要在 web.xml 中添加类作为上下文监听器:
<listener>
<listener-class>com.company.MyContextLoaderListener</listener-class>
</listener>

关于proxy - 带 Spring 的 CGLIB 抛出 IllegalAccessError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11574049/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com