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
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.
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
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.
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;
}
}
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
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" />