[英]Spring Autowired null if not found
默認@Autowired
Spring實現在未定義應自動裝配的bean時拋出錯誤。 是否可以配置Spring,將null賦給對象而不是拋出異常?
編輯:
我已將required=false
添加到Autowired
但它仍然無法正常工作。 那是我的代碼:
@Autowired
private ApplicationContext applicationContext;
@Autowired(required = false)
private HelloService helloService;
public HelloController() {
message = "Hello World";
System.out.println("Controller constructor");
}
@RequestMapping(method = RequestMethod.GET)
public ModelAndView helloWorld() {
ModelAndView modelAndView = new ModelAndView("hello");
if (helloService == null) {
System.out.println(message);
} else {
helloService.hello();
BeanDefinitionRegistry factory = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory();
factory.removeBeanDefinition("helloService");
}
return modelAndView;
}
在第一個請求中它是自動裝配的,但在使用factory.removeBeanDefinition("helloService")
刪除bean后的下一個請求中,控制器bean再次構造,並且我得到NoSuchBeanDefinitionException
EDIT2:
我用以下主體創建了另一個控制器:
@Autowired(required = false)
private TestService testService;
@RequestMapping(method = RequestMethod.GET)
public ModelAndView hello() {
ModelAndView modelAndView = new ModelAndView("hello");
return modelAndView;
}
並且它正常工作 - 對象為空並且不會出錯。 也許我應該使用不同的方法從Spring上下文中刪除bean?
堆棧跟蹤:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'helloService' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$200(AutowiredAnnotationBeanPostProcessor.java:115) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:538) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
...
重現步驟:
您可以通過將required
屬性設置為false來禁用此功能。
@Autowired(required=false)
如果Spring找不到bean,它會將字段unset設置為null。
問題是AutowiredAnnotationBeanPostProcessor緩存注入結果。 因此,當您從上下文中刪除bean時,此類認為此對象實際存在(請參閱私有類AutowiredFieldElement在AutowiredAnnotationBeanPostProcessor.class和方法注入中擴展InjectionMetadata.InjectedElement)。因此,您應該清除該緩存。
我找到的最愚蠢的方式是,但看起來你想要這樣做
@Controller
@RequestMapping("/hello")
public class HelloController {
@Autowired(required = false)
private HelloService helloService;
@Autowired
private ApplicationContext applicationContext;
@RequestMapping(method = RequestMethod.GET)
public ModelAndView modelAndView() {
ModelAndView modelAndView = new ModelAndView("hello");
if (helloService != null) {
helloService.hello();
removeBean("helloService");
}
return modelAndView;
}
private void removeBean(String beanName) {
BeanDefinitionRegistry factory = (BeanDefinitionRegistry) applicationContext
.getAutowireCapableBeanFactory();
factory.removeBeanDefinition(beanName);
clearCache(factory);
}
private void clearCache(BeanDefinitionRegistry beanFactory){
AutowiredAnnotationBeanPostProcessor processor = null;
for (BeanPostProcessor beanPostProcessor : ((DefaultListableBeanFactory) beanFactory).getBeanPostProcessors()){
if (beanPostProcessor.getClass().equals(AutowiredAnnotationBeanPostProcessor.class)){
processor = (AutowiredAnnotationBeanPostProcessor) beanPostProcessor;
}
}
try {
Field injectionMetadataCache = processor.getClass().getDeclaredField("injectionMetadataCache");
injectionMetadataCache.setAccessible(true);
Method clear = Map.class.getMethod("clear");
clear.invoke( injectionMetadataCache.get(processor));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.