我正处于弹簧3.2到4.3升级过程中并遇到了注入依赖项问题。通过这项工作,我们也将从Java 7迁移到8。我提到这个,因为我不确定这是一个春天问题还是java 8问题。
我们有一个扩展org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices的类,它实现了org.springframework.security.web.authentication.RememberMeServices接口。 bean定义如下所示:
<bean id="myRememberMeServices" class="com.mycompany.spring.security.services.impl.MyRememberMeServices">
...
</bean>
该课程如下:
public class MyRememberMeServices extends AbstractRememberMeServices implements CompanyRememberMeServices {
...
}
这是注入另一个类:
public class MyLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Autowired
@Qualifier("myRememberMeServices")
private RememberMeServices rememberMeServices;
...
}
使用弹簧3.2,这工作正常。在4.3版本中,我在启动期间获得了无资格的bean异常。所以它没有找到任何候选bean。经过大量的敲击和谷歌搜索后,我将@Autowired更改为@Resource以专门注入名称,因为@Qualifier在找不到类型匹配时没有帮助。当我改为@Resource时,我得到以下异常:
使用名称&#39; com.mycompany.spring.security.web.hand创建bean时出错 lers.MyLogoutSuccessHandler#414fd67c&#39;:注入资源 依赖失败;嵌套异常是 org.springframework.beans.factory.Be anNotOfRequiredTypeException: Bean命名为myRememberMeServices&#39;预计将是类型 [org.springframework.security.web.authentication.Rem emberMeServices] 但实际上是类型 [com.mycompany.spring.security.services.impl.MyRememberMeServices]
如果我改变我的代码以使用具体类型MyRememberMeServices,则bean注入工作。我不明白为什么我无法注入到RememberMeServices的接口类型,因为我的类通过AbstractRememberMeServices实现了RememberMeServices接口?这也适用于Spring 3.2(java 7)
我已经阅读了spring框架参考和一些其他帖子和文档,并且没有找到任何可以解释在spring 3.2和4.3之间发生什么变化的东西,这会阻止注入接口。 ...
更新
看来我能解开这个谜团,至少我相信我有,如此 为什么依赖注入失败。当我偶然发现另一篇关于转换失败的帖子时,我的灵感和灵感都得到了启发,这个转换失败在性质上与我遇到的问题类似: Initialization of bean failed; ConversionNotSupportedException
总结一下,我通过执行以下操作解决了我发布的原始错误:
...
private RememberMeServices rememberMeServices;
@Resource
public void setRememberMeServices(MyRememberMeServices myRememberMeServices) {
this.rememberMeServices = myRememberMeServices;
}
这解决了原始错误,因为我使用setter方法注入了 具体类型为MyRememberMeServices,然后将其设置为接口 Spring抱怨的RememberMeServices类型。一旦修复了这个错误,我就得到了另一个依赖注入错误:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultS
ecurityFilterChain#5': Cannot create inner bean '(inner bean)#7d884002' of type [org.springframework.security.web.csrf.CsrfFilter] while set
ting constructor argument with key [6]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean wit
h name '(inner bean)#7d884002': Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException
: Failed to convert property value of type [com.mycompany.spring.security.web.handlers.MyAccessDeniedHandler] to required type [org.springf
ramework.security.web.access.AccessDeniedHandler] for property 'accessDeniedHandler'; nested exception is java.lang.IllegalStateException: C
annot convert value of type [com.mycompany.spring.security.web.handlers.MyAccessDeniedHandler] to required type [org.springframework.securi
ty.web.access.AccessDeniedHandler] for property 'accessDeniedHandler': no matching editors or conversion strategy found
这又是奇怪的,因为有问题的课被定义为:
public class MyAccessDeniedHandler extends AccessDeniedHandlerImpl {
...
}
阅读上面提到的帖子后,我决定检查类路径 更详细,我发现我们有2个spring-security-web-4.1.3.RELEASE.jar正在播放。
从/ WEB-INF / lib加载一个jar,从/ myproject / lib加载另一个jar。 在我们构建期间,使用maven将/ WEB-INF / lib文件夹中的jar拉入 使用以下pom snip-it:
<properties>
<springframework.version>4.3.3.RELEASE</springframework.version>
<springframework.security.version>4.1.3.RELEASE</springframework.security.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${springframework.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springframework.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.mobile</groupId>
<artifactId>spring-mobile-device</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
然而/ myproject / lib中的spring-security-web-4.1.3.RELEASE.jar是其中的一部分 我们正在使用的一个共同框架,并没有通过maven拉入。这是公正的 作为框架的一部分,如果你愿意的话。 jar是相同的版本, 和我所知道的一样。无论如何,在java编译期间,我们的代码是针对/myproject/libs/spring-security-web-4.1.3.RELEASE.jar编译的,但在运行时期间/WEB-INF/libs/spring-security-web-4.1.3.RELEASE .jar在类路径中更高。我决定要删除/WEB-INF/libs/spring-security-web-4.1.3.RELEASE.jar以查看会发生什么。惊喜,所有依赖注入。到底是什么?
似乎/WEB-INF/libs/spring-security-web-4.1.3.RELEASE.jar不知何故 导致Spring认为这些类与其中的类不同 /myproject/libs/spring-security-web-4.1.3.RELEASE.jar因此会在尝试解决依赖关系时给出关于没有匹配的bean或类型不匹配的各种错误。
现在这部分都是猜想,说实话我不确定这是Spring问题还是Java 8问题。似乎已经发生的事情是我的代码编译时使用了jar /myproject/libs/spring-security-web-4.1.3.RELEASE.jar。我们扩展的接口存在于这个jar中。
Example:
public class MyAccessDeniedHandler extends AccessDeniedHandlerImpl {
...
}
AccessDeniedHandlerImpl位于/myproject/libs/spring-security-web-4.1.3.RELEASE.jar中。在启动期间,例如运行时,Spring正在使用/WEB-INF/libs/spring-security-web-4.1.3.RELEASE.jar并为AccessDeniedHandler类型寻找匹配的bean。在这种情况下 spring没有找到类型为/WEB-INF/libs/spring-security-web-4.1.3.RELEASE.jar的AccessDeniedHandler,因为MyAccessDeniedHandler的类型为/myproject/libs/spring-security-web-4.1.3.RELEASE 。罐。 (我知道这些不是&#34;类型&#34;但我用它来说明这个想法)
无论出于何种原因,Spring或Java 8都会查看对象/对象层次结构,并得出结论:/myproject/libs/spring-security-web-4.1.3.RELEASE.jar中的AccessDeniedHander与/中的AccessDeniedHandler不同WEB-INF / libs / spring-security-web-4.1.3.RELEASE.jar因此无法解决依赖关系。
在我的例子中,修复是从/ WEB-INF / libs文件夹中删除此jar。
我很想听到别人对此的看法,或者有人可以解释这里真正发生的事情。