Java 故意将springbean设置为null

Java 故意将springbean设置为null,java,spring,Java,Spring,我正在使用Spring将JMS连接工厂注入到我的Java应用程序中。因为这个工厂只在生产环境中需要,而不是在我开发的时候,所以我将bean定义放入一个单独的XML中,并将其包含在我的主applicationContext.XML中。在生产环境中,这个额外的文件包含常规bean定义。在我的本地开发环境中,我希望这个bean为null。当Spring遇到一个它不知道的引用ID时,试图完全删除bean定义显然会导致一个错误 所以我尝试创建一个只返回null的工厂bean。如果我这样做,Spring(2

我正在使用Spring将JMS连接工厂注入到我的Java应用程序中。因为这个工厂只在生产环境中需要,而不是在我开发的时候,所以我将bean定义放入一个单独的XML中,并将其包含在我的主applicationContext.XML中。在生产环境中,这个额外的文件包含常规bean定义。在我的本地开发环境中,我希望这个bean为null。当Spring遇到一个它不知道的引用ID时,试图完全删除bean定义显然会导致一个错误

所以我尝试创建一个只返回null的工厂bean。如果我这样做,Spring(2.5.x)会抱怨工厂返回null,尽管基于FactoryBean接口的SpringAPI文档,我希望它能正常工作(请参阅)

XML如下所示:

<bean id="jmsConnectionFactoryFactory" class="de.airlinesim.jms.NullJmsConnectionFactoryFactory" />

<bean id="jmsConnectionFactory" factory-bean="jmsConnectionFactoryFactory" factory-method="getObject"/>
@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


这样做的“正确”方法是什么?

您可以使用特殊的
bean元素吗?e、 g

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


从中,第3.3.2.5节

工厂bean
/
工厂方法
不适用于
null
,但自定义的
工厂bean
实现工作正常:

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;
    }
}
公共类NullFactoryBean实现FactoryBean{
public Void getObject()引发异常{
返回null;
}
公共类<代码>

我很确定Spring不允许您将
null
与bean id或别名关联。您可以通过将属性设置为null来处理此问题

下面是您在Spring2.5中如何做到这一点的

<bean class="ExampleBean">
    <property name="email"><null/></property>
</bean>
其中,
some.prop
可以在属性文件中定义为:

some.prop=null


上面提到的一些问题,axtact的答案在Autowiring contextes中不起作用,Spring将依赖getObjectType()方法的正确信息。因此,您可能会出现以下错误:

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 原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到依赖项类型为[XXXXXXXXXXXX]的匹配bean:应至少有1个bean符合此依赖项的autowire候选项。依赖项批注:{@org.springframework.beans.factory.annotation.Autowired(必需=true),@org.springframework.beans.factory.annotation.Qualifier(value=yyyyyyyyy)} 位于org.springframework.beans.factory.support.DefaultListableBeanFactory.RaiseNouchBeanDefinitionException(DefaultListableBeanFactory.java:920) 位于org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789) 位于org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703) 位于org.springframework.beans.factory.annotation.AutoWiredNotationBeanPostProcessor$AutoWiredFeldElement.inject(AutoWiredNotationTio 这里有一个小的变化,它允许用户在构造时强制使用ObjectType。使用属性而不是构造函数参数不起作用,因为Spring在这个上下文中没有完全初始化bean

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;
    }
}
公共类NullFactoryBean实现FactoryBean{
私有最终类objectType;
公共NullFactoryBean(类objectType){
this.objectType=objectType;
}
@凌驾
公共对象getObject()引发异常{
返回null;
}
@凌驾
公共类getObjectType(){
返回objectType;
}
@凌驾
公共布尔isSingleton(){
返回false;
}
}

对于任何回答此问题的人,请记住只需将@Autowired注释设置为可选即可(即,如果未找到符合条件的bean,Spring将保留空引用)


请注意,在引用bean的任何地方都必须这样做,这可能比如上所述创建空工厂更麻烦。

在测试中,空bean也可以这样注入:

<bean id="jmsConnectionFactoryFactory" class="de.airlinesim.jms.NullJmsConnectionFactoryFactory" />

<bean id="jmsConnectionFactory" factory-bean="jmsConnectionFactoryFactory" factory-method="getObject"/>
@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

对于遇到这种情况的其他人:如果您使用Java 8,另一种方法是使用
Supplier
函数接口包装一个可能为空的bean:

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

然后
SomeService
中的
someBean
字段可以为null或非null。

这可能在设置最终应用程序bean的属性时起作用。但此时,我只提供了引用id“jmsConnectionFactory”,它应该引用实际bean或null(如果可能的话)。对此有一个开放的功能请求,但已经存在了2年……投票可能会有所帮助:如果我在
@Autowired
上下文中使用bean,这对我不起作用。如果我返回null,我会得到BeanCreationException。原因:org.springframework.beans.factory.BeanCreationException:创建名为“nullObject”的bean时出错在类路径资源[XXX.xml]中定义:工厂bean'NullFactoryBean'返回null我更喜欢此解决方案;它不需要创建自定义工厂beanGreat catch!是否有一个源/文档链接确认Spring不处理“null”作为有效的bean值?我有一个Spring
@Configuration
类,其中包含一个返回
@bean
的方法。但是该方法在返回实例之前进行了一些检查。当检查失败时,它返回null,并导致
未满足的PendencyException
@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
@Bean
@Scope("singleton")
public Supplier<SomeBean> getSomeBean() {
  SomeBean myBean = null;  // or can set to a SomeBean instance
  return () -> myBean;
}
private SomeBean someBean;

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