【问题标题】:Spring Transaction - Proxy confusionSpring Transaction - 代理混淆
【发布时间】:2010-02-10 15:38:10
【问题描述】:
 <tx:advice id="txAdvice" transaction-manager="jtaTxManager">
  <tx:attributes>
   <tx:method name="*" />
  </tx:attributes>
 </tx:advice>

 <aop:config proxy-target-class="true">
  <aop:pointcut id="fooServiceOperation"
   expression="execution(* x.y.SampClass.save(..))" />
  <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation" />
 </aop:config>

 <bean id="Samp1" class=" x.y.SampClass"></bean>

        <bean id="SearchDispatchRpcGwtServlet" class="x.y.server.SearchDispatchRpcGwtServlet">
  <constructor-arg>
       <list>
         <ref bean="webServiceClient"/>                          
       </list>
  </constructor-arg>      
 </bean>

 <!-- Service Clients --> 
 <bean id="webServiceClient" class="x.y.KSBClientProxyFactoryBean">
  <property name="serviceEndpointInterface" value="x.y.service.WebService" />
  <property name="serviceQName" value="{http://x.y.org/wsdl/organization}WebService" />
 </bean>

这是示例 spring 上下文文件的一部分。我正在尝试为SampClass 创建一个事务建议,以便在保存方法上执行。

所以据我了解,它应该只为SampClass 创建一个代理。

我有一个SearchDispatchRpcGwtServlet,它以一个 Web 服务客户端作为参数,它本身也是一个代理。由于无法创建代理的代理,此 bean 也因某种原因失败而被代理。

我必须补充一点,SearchDispatchRpcGwtServlet 创建了一个SampClass 的实例并调用了 save 方法。

我得到以下异常:

java.lang.IllegalArgumentException: 不能子类化最终类类 $Proxy118 在 net.sf.cglib.proxy.Enhancer.generateClass(增强器 .java:446) 在 net.sf.cglib.transform.TransformingClassGenerator。 generateClass(TransformingClassGenerator.java:33)

我不明白为什么要创建 SearchDispatchRpcGwtServlet 代理。有人可以解释一下。

加法堆栈跟踪

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy117]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy117
    at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:473)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:348)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:309)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:361)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1427)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:139)
    ... 85 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy117
    at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
    at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)

【问题讨论】:

  • 我们能看到更多的堆栈跟踪吗?你给我们的还不够。
  • 我会更详细地解释这个问题。我为 Bean A 定义了一个 aop 切入点。我在上下文文件中的 Bean A 之后定义了 Bean B。根据我的想象,应该只创建 Bean A 代理。但在这种情况下,还创建了 Bean B 代理,其中包含一个 webservice 客户端代理作为参数。这是一个有效的行为。我可以做些什么来避免这种情况。意思是 aop 只代理指定的 bean。
  • 仍然不够……请不要在您认为它不再有用的地方截断堆栈跟踪,将其全部添加。
  • “我必须补充一点,SearchDispatchRpcGwtServlet 创建一个 SampClass 实例并调用 save 方法。” ...您的服务如何创建 SampClass 实例?你在玩bean scope吗?这是这些代理错误配置的常见原因。
  • 出于好奇,是否有理由不使用“”而不是手动定义代理?根据您的描述,我会说您的配置中有其他内容导致创建了意外的代理,例如,您没有发现范围和加载正在发生的事情,例如 servlet 上下文。你能用一个小测试程序重现这种行为吗?

标签: java spring transactions


【解决方案1】:

AbstractAutoProxyCreator 的子类正在尝试代理 bean,但该 bean 本身已经是使用另一种机制(例如 aop:config proxy-target-class="true)创建的 CGLIB 代理。

为避免这种情况,请确保避免为同一个 bean 混合不同的方面编织机制(ProxyBeanFactory 和 aop:config)。

在这种情况下,事务方面也可以通过&lt;tx:annotation:driven/&gt; 通过@Transactional 注释进行编织。

或者,可以从 bean 中移除自动装配/扫描,并使用 setter 通过 XML 注入依赖项。

另一种选择是通过声明 &lt;context:load-time-weaver/&gt; 并添加所需的 jar 来使用加载时间编织。

也看看这个post,一般情况下最好只使用一种方式在整个应用程序中应用方面,以避免这个问题。

【讨论】:

  • 自动装配没有创建任何代理。
  • AbstractAutowireCapableBeanFactory 根据 javadoc 提供接线(包括自动接线)正在尝试通过 bean 处理器创建 CGLIB 代理,它在堆栈跟踪中
  • 不,不是... AbstractAutoProxyCreator 的子类正在尝试创建代理。这个后处理器可能正在由 AOP 配置注册。堆栈跟踪上有 AbstractAutowireCapableBeanFactory 的事实与问题无关。自动装配和组件扫描是与代理无关的一组功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多