Почему @Validated + @Component + вводит в заблуждение тип ошибки при весенней загрузке? - PullRequest
0 голосов
/ 08 января 2019

Вот список примеров кода:

База

@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;
        }
    }
}

Это работает : бобы вводятся, здесь нет проблем. Важное замечание: MyImpl bean - это прокси , а нет проблема для автопроводки.

Но все становится иначе, когда я добавляю 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 канун Попробуй снова работать.

Я понимаю, что Spring использует проксирование, и лучше использовать интерфейсы. Но я не могу понять, почему у меня здесь проблемы? Если spring может автоматически подключать прокси-сервер по имени класса, почему он не может сделать это, когда добавлено implements, особенно если этот интерфейс не используется в полях автоматического подключения.

ОБНОВЛЕНО

Spring-boot версия - 2.0.3 версия с пружинным сердечником 5.0.7.RELEASE

1 Ответ

0 голосов
/ 11 января 2019

С интерфейсами JDK используются динамические прокси (на основе интерфейса), иначе Вы используете прокси на основе классов. Новые версии Spring Boot Force всегда использовать прокси на основе классов. В любом случае он использует прокси, но с интерфейсы он использует интерфейс только прокси и еще использует класс на основе (CGLIB) прокси.

С М. Deinum комментарий .

Это правда, добавление интерфейса приводит к JDK-прокси, который не является подклассом от исходного класса.

Чтобы заставить подкласс прокси подкласса, добавьте следующее к объявлению бина:

@Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )

например:.

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