如果未找到,Spring Autowired null

now*_*y94 6 java spring

@Autowired当没有定义应该自动装配的 bean 时,默认的Spring 实现会抛出错误。是否可以配置 Spring,将 null 分配给对象而不是抛出异常?

编辑:

我已经添加required=falseAutowired但它仍然无法正常工作。那是我的代码:

@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;
}
Run Code Online (Sandbox Code Playgroud)

在第一个请求中它是自动装配的,但是在删除 bean 后的下一个请求中factory.removeBeanDefinition("helloService"),再次构造控制器 bean,我得到NoSuchBeanDefinitionException

编辑2:

我创建了另一个具有以下主体的控制器:

@Autowired(required = false)
private TestService testService;

@RequestMapping(method = RequestMethod.GET)
public ModelAndView hello() {
    ModelAndView modelAndView = new ModelAndView("hello");
    return modelAndView;
}
Run Code Online (Sandbox Code Playgroud)

并且它工作正常 - 对象为空并且不会出错。也许我应该使用不同的方法从 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] 
...
Run Code Online (Sandbox Code Playgroud)

重现步骤:

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

Bye*_*Bye 7

您可以通过将required属性设置为 false来禁用此功能。

@Autowired(required=false)

如果 Spring 找不到 bean,它将使字段未设置为 null。


小智 4

问题是 AutowiredAnnotationBeanPostProcessor 缓存注入结果。因此,当您从上下文中删除bean时,此类认为该对象实际上存在(请参阅AutowiredAnnotationBeanPostProcessor.class中的私有类AutowiredFieldElement扩展InjectionMetadata.InjectedElement和方法inject)。因此,您应该清除该缓存。

我发现的最愚蠢的方法是,但看起来你想做

@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();
        }


    }

}
Run Code Online (Sandbox Code Playgroud)