Spring 3.2升级到4.3获取BeanNotOfRequiredTypeException

时间:2017-04-20 04:11:01

标签: java spring java-8 autowired

我正处于弹簧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。

我很想听到别人对此的看法,或者有人可以解释这里真正发生的事情。

0 个答案:

没有答案