Intentionally setting a Spring bean to null

后端 未结 7 1907
孤独总比滥情好
孤独总比滥情好 2020-12-05 06:32

I\'m using Spring to inject JMS connection factory into my Java application. Since this factory is only required within the production environment, not while I\'m developing

相关标签:
7条回答
  • 2020-12-05 07:17

    For anyone else who comes across this: another approach if you're using Java 8 is to use the Supplier functional interface to wrap a potentially null bean:

    @Bean
    @Scope("singleton")
    public Supplier<SomeBean> getSomeBean() {
      SomeBean myBean = null;  // or can set to a SomeBean instance
      return () -> myBean;
    }
    

    With @Autowired constructor injection using this looks like:

    private SomeBean someBean;
    
    @Autowired
    SomeService(Supplier<SomeBean> someBeanSupplier) {
        this.someBean = someBeanSupplier.get();
    }
    

    Then the someBean field in SomeService can either be null or non-null.

    0 讨论(0)
  • 2020-12-05 07:17

    In tests null beans can also be injected like this:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = NullTest.class)
    @Configuration
    public class NullTest {
    
        @Bean(name = "em")
        public IEntityManager em() { return null; }
        @Bean
        public PlatformTransactionManager tm() { return null; }
    
        @Resource
        private SomeBean someBean; // this would get em and tm fields autowired to nulls
    
    0 讨论(0)
  • 2020-12-05 07:21

    For anyone coming to this question, keep in mind that simply setting the @Autowired annotation as optional will do the trick (i.e. Spring will leave the reference null if no qualifying bean is found).

    @Autowired(required = false)
    private SomeClass someBean
    

    Note that you would have to do this everywhere the bean is referenced, which may be a bigger hassle than creating a null-factory as mentioned above.

    0 讨论(0)
  • 2020-12-05 07:26

    Some noted above, axtact's answer doesn't work in Autowiring contextes, where Spring will rely on correct information from the getObjectType() method. So you might end up with errors like:

    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [xxxxxxxxxxxxx] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=yyyyyyyyyyyyyyyy)}
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotatio
    

    So here's a small variation which involves allowing users to force the objectype at construction. Using a property instead of a constructor-arg didn't work because Spring doesn't fully initialize the beans in this context.

    public class NullFactoryBean implements FactoryBean {
        private final Class<?> objectType;
    
        public NullFactoryBean(Class<?> objectType) {
            this.objectType = objectType;
        }
    
        @Override
        public Object getObject() throws Exception {
            return null;
        }
    
        @Override
        public Class<?> getObjectType() {
            return objectType;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:26

    Can you make use of the special <null> bean element ? e.g.

    <bean class="ExampleBean">
    <property name="email"><null/></property>
    </bean>
    

    from the doc, section 3.3.2.5

    0 讨论(0)
  • 2020-12-05 07:36

    factory-bean/factory-method doesn't work with null, but a custom FactoryBean implementation works fine:

    public class NullFactoryBean implements FactoryBean<Void> {
    
        public Void getObject() throws Exception {
            return null;
        }
    
        public Class<? extends Void> getObjectType() {
            return null;
        }
    
        public boolean isSingleton() {
            return true;
        }
    }
    
    <bean id="jmsConnectionFactory" class = "com.sample.NullFactoryBean" />
    
    0 讨论(0)
提交回复
热议问题