繁体   English   中英

Spring Autowired null如果找不到null

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

重现步骤:

https://github.com/nowszy94/Autowired-null

您可以通过将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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM