Spring Autowired如果未找到,则返回null
默认@Autowired
未定义应该自动装配的Bean时,Spring实现抛出错误。有没有可能配置Spring,这将分配空对象而不是抛出异常?Spring Autowired如果未找到,则返回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")
去除豆后下一个请求,控制器豆再次施工,我得到NoSuchBeanDefinitionException
EDIT2:
我已经创建了以下机构的另一个控制器:
@Autowired(required = false)
private TestService testService;
@RequestMapping(method = RequestMethod.GET)
public ModelAndView hello() {
ModelAndView modelAndView = new ModelAndView("hello");
return modelAndView;
}
它正常工作 - Obj ect为空并且不会出错。也许我应该使用不同的方法从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]
...
重现步骤:
问题是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();
}
}
}
这个巨大的反射只是调用'processor.injectionMetadataCache.clear();'但这是私人的方法,所以用反射做到这一点 –
谢谢,这是有效的。你能否在这里发布你的答案 - http://stackoverflow.com/questions/39043038/autowiredrequired-false-fails-after-removing-bean? – nowszy94
您可以通过required
属性设置为false禁用此。
@Autowired(required=false)
如果春天找不到豆,它会离开现场未设置为空。
请参阅我的版本的问题 – nowszy94
请告诉我们你的异常 – xenteros
的[@Autowired可能重复的堆栈跟踪的构造函数(必需= FALSE)给NoSuchBeanDefinitionException](http://stackoverflow.com/questions/23267440/autowiredrequired-false-on-constructor-giving-nosuchbeandefinitionexception) – xenteros
我不能重现你的问题。请发布[mcve]。 –