[英]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.