#java #spring #autowired
#java #весна #автоматическое подключение
Вопрос:
Возникли проблемы с получением экземпляров компонента из методов контроллера через SpringApplicationContext. То, что мне требуется в моем методе контроллера, — это хорошо заполненный экземпляр класса B
. Определение класса B
приведено ниже:
@Component
public class ADep {
}
@Component
public class A {
@Autowired
private ADep aDep;
public void printDep() {
System.out.println("aDep is " aDep);
}
}
@Component
public class B extends A {
public void printAMethod() {
super.printDep();
}
}
При вызове следующего метода контроллера:
@CrossOrigin
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/method1")
public MappingJacksonValue method1(HttpServletRequest request, HttpServletResponse response, B b) throws Exception {
b.printAMethod();
return null;
}
Я вижу следующий ответ:
aDep is null
Вместо получения компонента в методе контроллера, если я получаю его из контекста приложения, ответ будет другим:
@Autowired
private ApplicationContext applicationContext;
@CrossOrigin
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/hardware")
public MappingJacksonValue getHardware(HttpServletRequest request, HttpServletResponse response) throws Exception {
B b = applicationContext.getBean(B.class);
b.printAMethod();
return null;
}
Результат:
aDep is ADep@2e468dfa
Что мне требуется, так это экземпляр компонента, как в последнем случае. Как я могу получить это в методе контроллера без использования SpringApplicationContext?
Комментарии:
1. В вашем первом случае
b
это параметр метода. Не могу сказать, как вы вызываете этот метод, но, скорее всего, вы переходитеnull
в него2. Аргумент метода никогда не будет автоматически подключен, будут только зависимости на уровне класса. Если только вы не прибегнете к полномасштабному использованию AspectJ (компиляция или переплетение времени загрузки) и не используете
@Configured
. Итак, зачем вам нужен B как для привязки, так и для автоматической проводки?3. @M.Deinum, не знал, что экземпляры становятся доступными по-разному в случае вызова метода через автоматически подключаемую переменную экземпляра. Есть ли какой-либо способ получить функциональность типа Autowire для аргумента метода? Пробовал автозапуск в переменной метода, но не получил никакой разницы.
4. Нет. Вы не можете ввести компонент в аргумент метода. Если только вы не напишете свою собственную реализацию a
HandlerMethodArgumentResolver
, которая это делает. Но зачем вам вообще нужен объект autowired в методе? Вместо того, чтобы вводить его на уровне класса.5. Я не могу установить область действия класса B для запроса. Следовательно, любое значение, установленное в предыдущих запросах, сохраняется в переменной экземпляра класса B.
Ответ №1:
Вы пытаетесь передать объект b типа B в качестве параметра, поэтому в этом случае вы должны создать и передать объект b и передать его методу, я думаю, вы присваиваете этому аргументу нулевое значение, но если вы хотите, вы можете использовать @Autowired вместо контекста приложения, потому чтоB уже является компонентом, например:
@Autowired
private B b;
@CrossOrigin
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/hardware")
public MappingJacksonValue getHardware(HttpServletRequest request, HttpServletResponse response) throws Exception {
b.printAMethod();
return null;
}
Редактировать:
Чтобы изменить область действия компонента, другого компонента для другого запроса, вы можете добавить @Scope(value = WebApplicationContext.SCOPE_REQUEST)
аннотацию над B
классом
Комментарии:
1. Верно, что компонент здесь хорошо вводится. С областью действия по умолчанию один и тот же экземпляр становится общим для всех запросов и, таким образом, сохраняет поля, установленные в предыдущих запросах.
2. Вы можете изменить область действия компонента B, если хотите, для запроса scoped .
Ответ №2:
Параметр в вашем методе предоставляется Spring MVC-распознавателем аргументов. Здесь он не вводит компонент. Я немного удивлен, что в этом случае значение b не равно null, возможно, поведение по умолчанию заключается в создании нового экземпляра этого класса, и в этом случае, конечно, aDep равно null .