Создание прототипа области действия в методе обработчика запросов Spring - PullRequest
0 голосов
/ 03 ноября 2019

Я пишу приложение Spring и изучаю Spring на ходу. До сих пор всякий раз, когда я хотел что-то дать ссылку на ApplicationContext, это означало, что я пытался сделать что-то не так, поэтому я думал, что я спрошу, прежде чем я это сделал.

Мне нужно создать экземпляр прототипа для каждого запроса:

@Component
@Scope("prototype")
class ComplexThing {
    @Autowired SomeDependency a
    @Autowired SomeOtherDependency b
    public ComplexThing() { }
    // ... complex behaviour ...
}

Итак, я попробовал это:

@Controller
@RequestMapping ("/")
class MyController {
    @GetMapping
    public String index (ComplexThing complexThing, Model model) {
        model.addAttribute("thing", complexThing);
        return "index"
    }
}

И я ожидал, что Spring добавит новый ComplexThing для запроса, простокак это введено Model. Но потом я обнаружил, что правильная интерпретация этого заключается в том, что вызывающая сторона отправит ComplexThing в запросе.

Я думал, что будет способ внедрить Beans в обработчики запросов, но Я нездесь его не видно .

Так что в этом случае я должен сделать мой контроллер ApplicationContextAware и getBean?

Ответы [ 2 ]

0 голосов
/ 03 ноября 2019

Я решил это с помощью интерфейса ObjectProvider:

@Controller
@RequestMapping ("/")
class MyController {
    @Autowired 
    ObjectProvider<ComplexThing> complexThingProvider;
    @GetMapping
    public String index (Model model) {
        model.addAttribute("thing", complexThingProvider.getObject());
        return "index"
    }
}

Другое преимущество ObjectProvider заключается в том, что он мог передавать некоторые аргументы конструктору, что означало, что я мог пометить некоторыеполя как final.

@Controller
@RequestMapping ("/")
class MyController {
    @Autowired 
    ObjectProvider<ComplexThing> complexThingProvider;
    @GetMapping
    public String index (String username, Model model) {
        model.addAttribute("thing", complexThingProvider.getObject(username));
        return "index"
    }
}
@Component
@Scope("prototype")
class ComplexThing {
    @Autowired SomeDependency a
    @Autowired SomeOtherDependency b
    final String username;
    public ComplexThing(String username) {
        this.username = username;
    }
    // ... complex behaviour ...
}
0 голосов
/ 03 ноября 2019

Ваша точка зрения верна. Нет никакого способа, bean-объекты с прототипом (также как и с любым другим типом bean-компонента) могут быть напрямую вставлены в обработчик запросов контроллера. У нас есть только 4 варианта.

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

  2. При создании класса контроллера ApplicationContextAware установите объект applicationContext, переопределив метод setApplicationContext()и использовать его для получения экземпляра bean-компонента.

  3. Создайте личную переменную типа bean-компонента и аннотируйте ее с помощью @Autowired.

  4. Createзакрытая переменная типа bean-компонента и аннотируйте ее с помощью @Inject (@Autowired и @Inject имеют одинаковую функциональность. Но @Autowired зависит от пружины).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...