Spring autowire не работает в простом классе, но работает везде - PullRequest
0 голосов
/ 28 октября 2018

Я пытаюсь создать новую сущность X, которая имеет отношение к моей сущности User.Когда кто-то публикует новую X-сущность, я делаю «XForm», чтобы проверить результаты и т. Д. И если все верно, в методе «execute» я пытаюсь найти пользователя из userRepository на основе идентификатора из формы.

package app.form;

public class XForm {

@Autowired
private UserRepository userRepository;

private long userId;
//[.. other fields + getters and setters]

public X execute() throws Exception {
    X myX= new X();
    Optional<User> user = userRepository.findById(getUserId());
    if (!user.isPresent()) {
        throw new Exception("User not found");
    }
    myX.setUser(user.get());
    return myX;

}

И пользовательский репозиторий равен нулю.Я попытался аннотировать его с помощью @Component, @Service и т. Д., Но он все еще нулевой.И, как вы можете видеть, я не пытаюсь создать «новый» UserRepository.Автоматическое подключение хранилища работает отлично везде (в контроллерах, обработчиках аутентификации и т. Д.).

Вот контроллер:

public ResponseEntity<Object> testNewAction(@RequestBody @Valid XForm form,
                                         BindingResult result) {
    try {
        if (isValid(result)) {
            X myX = form.execute();
            XRepository.save(myX);
            //return success json
        }
        //return form errors json
    } catch (Exception ex) {
        //return exception json
    }
}

Базовый класс приложения выглядит следующим образом:убедился, что он тоже отсканирован (app.form):

@SpringBootApplication
@ComponentScan(basePackages = {"config", "app"})
@EntityScan(basePackages = {"app.entity"})
@EnableJpaRepositories(basePackages = {"config", "app"})
@EnableTransactionManagement
public class Application {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        app.run(args);
    }
}

Что я делаю не так?

Ответы [ 3 ]

0 голосов
/ 28 октября 2018

Вам необходимо все следующее:

  1. Аннотировать XForm с @Component
  2. Аннотировать UserRepository в XForm с @Autowired
  3. В вашей конфигурации Java определите bean-компонент UserRepository вместе с логикой создания
  4. В вашем @ComponentScan укажите пакет XForm (убедитесь, что синтаксис правильный)

Пример ниже:

@ComponentScan(basePackages = {
    "com.mycompany.app1",
    "com.mycompany.app2"
})

Из вашего описания, кажется, вы сделали первые 3 пункта.Отсутствует только последний.

0 голосов
/ 28 октября 2018

Диагноз

Я столкнулся с той же самой проблемой, и ее очень неприятная проблема, которую нужно решить.Вы не понимаете, что не так.Но я наконец понял, в чем проблема.Это не значит, что Spring не может обнаружить XForm, нет!Spring очень хорошо создаст для вас боб XForm.Вы можете проверить это, используя следующий код:

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
    return args -> {
    System.out.println("Let's inspect the beans provided by Spring:");

    String[] beanNames = ctx.getBeanDefinitionNames();
    Arrays.sort(beanNames);
    for (String beanName : beanNames) {
      System.out.println(beanName);
    }
  };
}

Проблема

Настоящая проблема заключается в @RequestBody.@RequestBody делает (с помощью HttpMessageConverter) то, что он сообщает контроллеру MVC создать экземпляр XForm с помощью конструктора no-arg, а затем вызывать методы setter со значениями входящего HTTP-запроса POST,Теперь, когда @RequestBody создает объект с помощью конструктора без аргументов, зависимости (UserRepository, в данном случае) никогда не внедряются, и вы получаете нулевой указатель для вашего сервиса.

Вид решения

То, что вы можете попробовать сделать, это попытаться создать еще один расширенный конструктор и вызвать его из конструктора без аргументов следующим образом:

public XFrom(UserService userService){
    this.userService = userService;
}

Я не уверен, будет ли это работать, но оно определенно стоитвыстрел.

0 голосов
/ 28 октября 2018

Ваша проблема в том, что XForm создается не как бин Spring, а как простой Java-объект.В таких случаях вы можете сделать класс @Configurable, и Spring поможет вам создать экземпляр во время вызова new.Вот пример того, как это сделать: https://sichernmic.blogspot.com/2015/04/use-of-configurable-annotation.html

...