Let's assume I have an annotated bean property setter like this:
public class Foo {
...
@Autowired
public void setBar(Bar bar) {
...
}
The Springframework will lookup the matching Bar property as usual. However, I'd like to intercept the default bean resolving process and add a little bit of "magic" myself. I'd like to introduce a resolver like this:
public interface SomeResolverInterface<T> {
public T resolve(Class<T> beanClass);
}
public class BarResolver implements SomeResolverInterface<Bar> {
@Override
public Bar resolve(Class<Bar> beanClass) {
if(someCondition) {
return someBean;
} else {
return anotherBean;
}
}
...
I know I could alway introduce some kind of wrapper bean and move the resolving logic into this but I'd prefer a more generic way using a resolver like described above to make Foo completely independent of the resolving logic.
Is there a way within the Springframework to achieve something like this?
From your description it looks like you only need to perform additional logic at startup time (autowiring). There are several ways to tackle this problem (from worst to best):
AOP - bad idea, introduces runtime overhead by intercepting every call
custom scope - see: Custom spring scopes? Also works at runtime and also a bad idea
@Profile - define two matching beans and enable only one based on active profile. Pretty clean and introduces overhead only at startup time
@Configuration - defining beans in Java has an extra benefit of having full control over how are they created:
@Configuration
public class Config {
@Autowired
private Bar someBean;
@Autowired
private Bar anotherBean;
@Bean
@Primary
public Bar primaryBean() {
if(someCondition) {
return someBean;
} else {
return anotherBean;
}
}
}
As you can see in this case we have three beans of Bar type: someBean, anotherBean and primaryBean. The first two can also be configured using @Bean or via component scan with @Service. But to make autowiring possible the last primaryBean is marked as @Primary. This way it will be preferred over other two.
This is my recommended solution as the resolving logic is clean, maintainable and readable. IMHO this is the situation where Java-based @Configuration really shines.
Apart from the @Configuration option provided by Tomasz, you can use a simple FactoryBean. Just implement the interface, and declare the factory bean. In the getObject() method perform your custom logic.
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