I'm in the process of moving some Xml-Based spring config over to Java-based.
Previously, I've consciously mixed Xml <bean class='foo' />
declarations with @Component
mappings on a case-by-case basis, as a means of documenting non-obvious beans.
A typical use case would be if I'm declaring beans that will modify the behaviour of spring itself, I'll declare these explicitly, rather than let them be discovered, purely to improve the clarity of the config file.
However, often these beans will need a degree of @Autowiring
. If I new
the bean up myself within a Java config, I become responsible for performing this wiring -- which is pointless.
Is there a pure Java configuration option that explicitly provides a class back to Spring, and let's it manage the instantiation?
ie:
Given the class:
public class MyFunkySpringBean implements InitializingBean {
@Autowired Foo foo;
}
In XML config, this would be declared as simply as:
<bean class="MyFunkySpringBean" />
Is there an equivalent in Java syntax, where I can explicitly declare the bean class to Spring, but not be responsible for providing the actual instance -- leaving that to Spring.
Eg:
@Configuration
public class MyAppConfig {
// Explictly provide the class, not the instance to Spring
@Bean
public MyFunkySpringBean funkyBean; // No instance -- it's up to Spring to build
}
To be clear, I don't want to have to do this:
@Configuration
public class MyAppConfig {
@Bean
public MyFunkySpringBean funkyBean() {
MyFunkySpringBean bean = new MyFunkySpringBean();
bean.foo = new Foo();
// other dependencies go here
return bean;
}
}
Does facility like this exist within Spring?
I understand from your comments that you are looking for a way how to achieve constructor autowiring (with type or annotation autowiring) in Java config... i.e. equivalent of:
<bean class="com.example.Foo" autowire="constructor" />
I've checked Spring's source to find who is actually responsible for the constructor resolution and autowiring and it is a combination of package private class ConstructorResolver
and AbstractAutowireCapableBeanFactory
. So that is something you will not be able to use on your own.
If you really really want to have constructor autowiring without XML, you can implement your own BeanDefinitionRegistryPostProcessor
and manually register that bean definitions yourself:
public class CustomBeanDefinitionRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Not interested in this method
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("foo", BeanDefinitionBuilder.
genericBeanDefinition(Foo.class).
setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR).
getBeanDefinition());
}
}
This bean factory post processor then needs to be registered via static @Bean
method in your @Configuration
:
@Configuration
public class MyAppConfig {
public static BeanFactoryPostProcessor customBeanDefinitionRegistrar() {
return new CustomBeanDefinitionRegistrar();
}
}
I admit it is a bit "wild approach", but it seems to be the only way how to achieve constructor autowiring with pure Java config.
In newer versions of Spring (as of 4.2) you can use org.springframework.context.annotation.Import
e.g.
@Configuration
@Import(MyFunkySpringBean.class)
public class MyAppConfig {
... other config ...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With