Класс автопроводки с аргументами управляемого конструктора не SpringBoot - PullRequest
0 голосов
/ 27 февраля 2019

Как показывает вопрос, как вам Autowire класс с не управляемым SpringBoot классом в качестве аргумента конструктора.

Ниже приведен блок кода, иллюстрирующий это:

@Component
class Prototype
{
    @Autowired
    private Repository repository;

    private NonSpringBootManagedBean bean;

    Prototype(NonSpringBootManagedBean bean)
    {
        this.bean = bean;
    }
}

@Component
class PrototypeClient
{
    @Autowired
    private ApplicationContext context;

    private void createNewPrototype(NonSpringBootManagedBean bean)
    {

        // This throws an error saying no bean of type NonSpringBootManangedBean found
        Prototype prototype = context.getBean(Prototype.class, bean);
    }
}

Причина, по которой я использую ApplicationContext для получения экземпляра Prototype вместо @Autowired, заключается в том, что мне нужноновый экземпляр Prototype в методе createNewPrototype() каждый раз, когда он вызывается, а не одноэлементный экземпляр (Также, пожалуйста, сообщите, если этот способ получения нового экземпляра неверен).

Обновление: как уже говорили другиепереместить мое создание bean-компонента в класс конфигурации Java и добавить метод, аннотированный @Bean, и создать экземпляр NonSpringBootManagedBean в методе @Bean.Но я думаю, что это невозможно, так как этот NonSpringBootManagedBean передан вызывающей стороной PrototypeClient.createNewPrototype().

Update Я обновил приведенный выше пример кода с большей ясностью.Пожалуйста, отошлите это сейчас.

@Component
class Prototype
{
    @Autowired
    private Repository repository;

    // Here Session is part of javx.websocket package and cannot be added as part of 
    // Java configuration class with a @Bean annotation
    // In this case how can I use constructor injection?
    private Session session;

    Prototype(Session session)
    {
        this.session = session;
    }
}

@Component
class PrototypeClient
{
    @Autowired
    private ApplicationContext context;

    private void createNewPrototype(Session session)
    {
        Prototype prototype = context.getBean(Prototype.class, session);
    }
}

@ServerEndpoint(value = "/resources")
class WebSocketController
{
    private PrototypeClient client = ApplicationContext.getBean(PrototypeClient.class);

    @OnMessage
    void handleMessage(Session session, String message)
    {
        client.createNewPrototype(session);
    }
}

Ответы [ 3 ]

0 голосов
/ 27 февраля 2019

Spring не может автоматически связать объект, если он не знает об этом.В некоторых случаях необходимо указывать @Component, @Bean или другие аннотации, например, @Service и т. Д., Чтобы сообщить Spring для управления экземпляром.

Также рекомендуется, чтобы при использовании закрытой переменной в Autowire это былодолжна быть предоставлена ​​часть конструктора (для внедрения конструктора) или метод установки (внедрение сеттера)

Чтобы устранить ошибку: вы можете создать класс конфигурации java и поместить его в базовый пакет pkg (такой же, как @SpringBootApplication илидобавить @ComponentScan («pkg, в котором присутствует конфиг») в классе с @SpringBootApplication)

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;

    @Configuration
    public class myconfig {

        @Bean
        public NonSpringBootManagedBean nonSpringBootManagedBean()
        {
            return new NonSpringBootManagedBean();

        }

    }
0 голосов
/ 27 февраля 2019

Определение компонента с областью действия прототип

То есть каждый раз, когда вводится новый экземпляр SpringBoot вы можете использовать аннотацию @Scope("prototype") для вашего класса бинов Prototype.

@Component
@Scope("prototype")
class Prototype {

    @Autowired
    private Repository repository;

    private NonSpringBootManagedBean bean;

    Prototype() {
        // you can only modify this 'NonSpringBootManagedBean' later
        // because Spring calls constructor without knowing NonSpringBootManagedBean  
        this.bean = new NonSpringBootManagedBean();

        // do something with 'repository' because its defined
    }

    public void setNonSpringBootManagedBean(NonSpringBootManagedBean bean) {
        this.bean = bean;        
    }        
}

Использовать экземпляры этого бина

С помощью инъекции (например, @Autowired в конструктор) вы можете использовать различные экземпляры этого прототипа bean-компонента в других bean-компонентах.

@Component
class PrototypeClient {
    // ApplicationContext still used?
    @Autowired
    private ApplicationContext context;

    private Prototype prototypeInstance;

    @Autowired  // injects the new instance of Prototype
    public PrototypeClient(Prototype p)
        this.prototypeInstance = p;

        // here you can change the NSBMB
        modifyPrototype();
    }

    private void modifyPrototype(NonSpringBootManagedBean bean) {
         this.prototypeInstance.setNonSpringBootManagedBean( new NonSpringBootManagedBean() );
    }
}

Почему выдается исключение?

no bean ofОбнаружен тип NonSpringBootManangedBean

Spring сообщает, что пытается создать экземпляр объекта типа Prototype

Prototype prototype = context.getBean(Prototype.class, bean);

, поскольку для вызова его конструктора ему необходимо передать аргумент типа NonSpringBootManagedBean,Так как все это создание экземпляра бина выполняется внутри Spring (Boot), вы не можете перехватить и сказать Spring: «Эй, используйте этот бин класса NonSpringBootManagedBean», как вы пытались в методе createNewPrototype(NonSpringBootManagedBean bean).

Почему могРазве NonSpringBootManagedBean не будет управляться как bean-компонентом Spring (Boot)?

Автоматическое подключение в SpringBoot - это способ внедрение зависимостей .Это означает, что SpringBoot ранее создавал экземпляр компонента, автоматически при запуске (при загрузке Spring).И этот боб теперь вводится как зависимость в другой бин и т. Д., Потому что этот другой бин зависит от него.

Если вы расскажете нам еще кое-что, мы могли бы пролить свет на вашу ситуацию.Это могут быть некоторые ответы на следующие вопросы:

  1. Что такое NonSpringBootManagedBean и почему отсутствует управляемый компонент ?
  2. Что такое Прототип и для каких целей он использует NonSpringBootManagedBean ?
  3. Что такое PrototypeClient и почему он создает свой собственный Prototype ?

Я не уверен, понял ли я связь и цель между вашими объектами / классами.

0 голосов
/ 27 февраля 2019

Знаете ли вы, что вы можете изменить область своего боба, чтобы она стала ссылкой на прототип вместо одиночного.Таким образом, вы можете ограничить определение одного бина любым количеством экземпляров объекта.

https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html

private NonSpringBootManagedBean bean = new NonSpringBootManagedBean();

@Bean
public Prototype getPrototype(){
  return new Prototype(bean);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...