【问题标题】:spring - forcing cglib proxies for @Autowired fieldsspring - 为 @Autowired 字段强制使用 cglib 代理
【发布时间】:2014-10-07 23:59:50
【问题描述】:

我有混合堆栈:EJB 和 Spring。对于将 Spring 自动装配到 EJB,我使用 SpringBeanAutowiringInterceptor(不确定这是否会影响我遇到的问题)。

尝试通过以下方式自动装配 bean:

@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, value="singleton")
@Repository
public class ClassA imlpements IfA {
    ...
}


@Scope(value="singleton")
@Repository
public class ClassB {
    @Autowired
    private ClassA classA;

    ...
}

我得到错误:

Could not autowire field: private ClassA ClassB.classA; nested exception is java.lang.IllegalArgumentException: Can not set ClassA field ClassB.classA to com.sun.proxy.$Proxy257. Please see server.log for more details.

据我了解,问题在于使用了 JDK 代理(因为 ClassA 实现了接口 IfA),而我需要 cglib 代理。

但我不明白。根据文档,注释:@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, 应该在这里完成工作。

好吧,我不能选择使用接口(作为字段类型)。

知道如何在此处强制 cglib 代理吗?

编辑

不确定是否相关,但我正在运行 glassfish 3.1.x。

还有stacktrace(部分,因为我不能在这里公开所有的类名:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'classB': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ClassA ClassB.classA; nested exception is java.lang.IllegalArgumentException: Can not set ClassA field ClassB.classA to com.sun.proxy.$Proxy257.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:912)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
    ... 89 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ClassA ClassB.classA; nested exception is java.lang.IllegalArgumentException: Can not set ClassA field ClassB.classA to com.sun.proxy.$Proxy257. Please see server.log for more details.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
    ... 100 more
Caused by: java.lang.IllegalArgumentException: Can not set ClassA field ClassB.classA to com.sun.proxy.$Proxy257
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:741)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:510)
    ... 102 more

【问题讨论】:

  • 你能发布一个完整的堆栈跟踪吗?
  • 你在使用 spring-data-jpa 作为存储库吗?
  • spring-data-jpa?没有

标签: java spring proxy cglib


【解决方案1】:

您不应该对单例使用 aop 范围代理。

在你的 spring 配置文件或类中使用 <aop:aspectj-autoproxy proxy-target-class="true" />@EnableAspectJAutoProxy(proxyTargetClass=true) 来强制 cglib 代理。

【讨论】:

  • 建议的 2 个都不适合我:既不能用 @EnableAspectJAutoProxy(proxyTargetClass=true) 标记 ClassA,也不能用 <aop:aspectj-autoproxy proxy-target-class="true" /> 标记。不过,只是出于好奇:为什么我不应该使用单例?
  • ClassA 不是配置类。您应该只在配置类中使用@EnableAspectJAutoProxy。但是标签应该可以工作。你能发布你的上下文文件的相关部分吗?对单人使用范围代理毫无意义,请参阅docs.spring.io/spring/docs/current/spring-framework-reference/…中的注释
  • @PeterButkovic 如果 aspectj 标签不起作用,您的代理不是来自AutoProxyCreator。你知道是谁在为 ClassA 创建代理吗?
  • 好的,所以要求 xml 配置文件是正确的,正如我发现的那样,<context:annotation-config /> 丢失了 => 我对注释的尝试是无用的。所以我指出,事情开始对我有用:<bean id="classA" class="ClassA"> <aop:scoped-proxy/> </bean><bean id="classB" class="ClassB"> <property name="classA" ref="classA"> </bean>。但是我想知道是否有一种不那么冗长的方式,比如启用:<aop:scoped-proxy/> globaly,而不是每个类。
  • @PeterButkovic 恕我直言,您应该专注于配置创建存储库代理的代理工厂,通常是 AutoproxyCreator 并忘记了作用域代理,单例作用域永远不会改变,所以你真的不需要它们。跨度>
猜你喜欢
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-11
相关资源
最近更新 更多