【问题标题】:Why @Validated + @Component + implement leads type misleading error in spring boot?为什么@Validated + @Component + 实现会在 Spring Boot 中导致类型误导错误?
【发布时间】:2019-01-08 08:29:38
【问题描述】:

这里的代码示例列表:

基础

@Validated
@Component
public class MyImpl1 {}

@Validated
@Component
public class MyImpl2 {}

@Service
public MySelector {
    private final MyImpl1 myImpl1;
    private final MyImpl2 myImpl2;

    @Autowired
    public MySelector(MyImpl1 myImpl1, MyImpl2 myImpl2) {
        this.myImpl1 = myImpl1;
        this.myImpl2 = myImpl2;
    }

    public Object select (Long id) {
        switch (id) {
            case 1:
                return myImpl1;
            case 2:
                return myImpl1;
        }
    }
}

工作:bean 被注入,这里没问题。这里的重要说明是 MyImpl beans 是代理,这是 否 自动装配问题

但是当我像这样添加implements 时,情况就不同了:

实现

@Validated
@Component
public class MyImpl1 implements MyInterface{}

@Validated
@Component
public class MyImpl2 implements MyInterface{}

public interface MyInterface {}

@Service
public MySelector {
    private final MyImpl1 myImpl1;
    private final MyImpl2 myImpl2;

    @Autowired
    public MySelector(MyImpl1 myImpl1, MyImpl2 myImpl2) {
        this.myImpl1 = myImpl1;
        this.myImpl2 = myImpl2;
    }

    public Object select (Long id) {
        switch (id) {
            case 1:
                return myImpl1;
            case 2:
                return myImpl2;
        }
    }
}

我得到了:

Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'myImpl1' is expected to be of type 'MyImpl1' but was actually of type 'com.sun.proxy.$Proxy108'

如果我删除@Validated eve 你又开始工作了。

我了解 spring 使用代理,最好使用接口。但我不明白为什么我在这里遇到问题? 如果spring 可以通过类名自动装配代理,为什么在添加implements时它不能这样做,特别是当这个接口没有用于自动装配字段时。

更新

Spring-boot 版本是2.0.3 spring-core 版本为5.0.7.RELEASE

【问题讨论】:

  • 我无法使用 Spring Boot 2.0.6 默认设置复制它。你有哪个 Spring Boot 版本?
  • 使用接口 JDK 动态代理(基于接口),否则您使用基于类的代理。较新的 Spring Boot 版本强制始终使用基于类的代理。无论哪种方式,它都使用代理,但对于接口,它只使用接口代理,否则使用基于类 (CGLIB) 的代理。
  • 适用于 Spring Boot 2.1.1.RELEASE

标签: java spring spring-boot proxy bean-validation


【解决方案1】:

使用接口 JDK 动态代理(基于接口),否则 您正在使用基于类的代理。较新的 Spring Boot 版本强制 总是使用基于类的代理。无论哪种方式,它都使用代理,但使用 接口它只使用接口代理,否则使用基于类的 (CGLIB) 代理。

来自M. Deinumcomment

确实如此,添加接口导致jdk代理不是原始类的子类。

要强制子类代理子类,请在 bean 声明中添加以下内容:

@Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )

例如:

@Validated
@Component
@Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
public class MyImpl2 implements MyInterface{}

【讨论】:

    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 2020-07-16
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多