2013-10-07 58 views
4

我配置了两个公共类,如Spring应用程序上下文如下:为什么混合的Spring AOP代理机制(CGLIB和JDKDynmic)不起作用

public class LoadErrorData{ 
    private ExceptionData exceptionData; 
    public LoadErrorData() { } 
    // reminder 
} 

public class ExceptionData implements Serializable{ 
    private Resource exceptionDataResource; 
    public ExceptionData() { } 
    // reminder 
} 

春天的applicationContext.xml:

<beans:bean id="loadErrorData" class="com.startup.LoadErrorData" init-method="startup"> 
    <beans:property name="exceptionData" ref="exceptionData"/> 
</beans:bean> 

<beans:bean id="exceptionData" class="com.server.ExceptionData" init-method="startup"> 
    <beans:property name="exceptionDataResource" value="classpath:${exception.datafile.path}"/> 
</beans:bean> 

它给下面的异常而初始化:

2013年10月7日下午1点45分21秒org.apache.catalina.core.Stand ardContext listenerStart严重:异常发送上下文初始化事件来 类的 监听器实例org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException:错误 创建具有名称豆“loadErrorData”类路径限定资源 [spring/startup-config.xml]:bean初始化失败;嵌套0​​例外是 org.springframework.beans.ConversionNotSupportedException:未能类型的 转换属性值“com.sun.proxy $ Proxy12实施 了java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework。 aop.framework.Advice' '所需类型'com.server.IICExceptionData'属性 'exceptionData';嵌套异常是java.lang.IllegalStateException: 无法转换[com.sun.proxy。$ Proxy12实现 java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised]类型的值, 所需类型[com.server.IICExceptionData用于属性 “exceptionData”: 在 不匹配编辑器或转换策略在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)发现org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory $ 1.getObject(AbstractBeanFact ory.java:294) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java: 291) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383) 在 org.springframework.web.context .ContextLoader.initWebApplicationContext(ContextLoader.java:283) 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) 在 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java :4723) at org.apache.catalina.core.StandardContext $ 1.call(StandardContext。java:5226) at org.apache.catalina.core.StandardContext $ 1.call(StandardContext.java:5221) at java.util.concurrent.FutureTask $ Sync.innerRun(FutureTask.java:334) at java。 util.concurrent.FutureTask.run(FutureTask.java:166)在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java :615) at java.lang.Thread.run(Thread.java:724)引起: org.springframework.beans.ConversionNotSupportedException:未能到 转换类型为'com.sun.proxy。$ Proxy12的属性值实施 java.io.Serializable接口,org.springframework.aop.SpringProxy,org.springframewo rk.aop.framework.Advice' to required type'com.server.IICExceptionData'for property 'exceptionData';嵌套异常是java.lang.IllegalStateException: 无法转换[com.sun.proxy。$ Proxy12实现 java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised]类型的值, 所需类型[com.server.IICExceptionData用于属性 “exceptionData”:没有在 org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:485) 发现在 org.springframework匹配编辑器或转换策略。 beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:516) 在 org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:510) 在 org.springframework.beans.fact ory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1406) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1365) 在 org.springframework.beans.factory.support。 java.lang.IllegalStateException:AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) ... 19多个所致不能转换 类型为[com.sun.proxy。$ Proxy12的值,实现为 java.io.Serializable,org.springframework.aop.SpringProx y,org.springframework.aop.framework.Advised] 必需类型[com.server.IICExceptionData]属性 'exceptionData':没有匹配的编辑器或转换策略在 找到org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate的.java:241) 在 org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:470) ...... 25多个

但是当我把

<aop:scoped-proxy proxy-target-class="true"/> 

ExceptionData bean的配置或者如果我删除

implements Serializable 

ExceptionData

异常消失。我的AOP切入点如下:

expression="execution(* com..*(..))" 

看来,春天正试图建立CGLIB代理豆LoadErrorData ,因为它确实实现(因为它没有实现任何接口)和JDKdynamicProxy它的依赖ExceptionData (接口Serializable)。它不能这样做。因为当我告诉spring为ExceptionData显式创建CGLIB代理时,它工作正常。这是为什么?为什么它不能为一个bean(ExceptionData)创建JDKDynamic Proxy,它是它尝试创建CGLIB代理的bean(LoadErrorData)的依赖关系?据文件说,Spring会自动检测它。

回答

2

其实你描述的情况正是发生了什么事情。

LoadErrorData将是一个CGLIB代理(由于没有接口。 ExceptionData将是JDK动态代理。

但是你LoadErrorData预计ExceptionData类型的豆,JDK的动态代理仅仅是一个(因为它只会代理接口而不是类),它永远不可能将其转换为ExceptionData的实例,因此上下文的加载将失败(这也是stacktrace告诉你的错误信息)

如果您强制基于类代理的一切或通过删除接口。无论哪种方式都会导致基于类的代理。

+0

如果我将LoadErrorData中存储的实例变量的类型更改为Serializable,它会起作用吗?从逻辑上讲,它应该正确吗? –

+1

然后注入将会发生,但是你只用'Serializable'做什么?你不能将它转换为ExceptionData ... –

+1

correct..it意味着我应该编程到一些有意义的接口,而不仅仅是分类或标记接口(好的旧设计主体),感谢@M。 Deinum –