I am using spring 3.2 and would like to dynamically choose a service implementation in my controller depending on a condition. Consider I have an interface and two implementations as follows :
public interface DevService {
public void add(Device device);
}
public class DevServiceImpl implements DevService {
public void add(Device device) {
}
}
public class RemoteDevServiceImpl implements DevService {
public void add(Device device) {
}
}
So in my controller, depending on whether the action is to be executed on the local site or remote site, I need to either execute it locally or send a command to the remote site to execute it. Essentially the site on which the user clicks determines which service impl to call. Can anybody suggest a clean way to achieve this ?
@Resource: annotation based on JSR-250. @Resource is quite similar to @Autowired and @Inject, but the main difference is the execution paths taken to find out the required bean to inject. @Resource will narrow down the search first by name then by type and finally by Qualifiers (ignored if match is found by name).
BeanFactory will create a bean object when the getBean() method is called thus making it Lazy initialization. ApplicationContext loads all the beans and creates objects at the time of startup only thus making it Eager initialization. BeanFactory interface provides basic features only thus requires less memory.
BeanFactoryPostProcessor is an interface and beans that implement it are actually beans that undergo the Spring lifecycle (Example below) but these beans don't take part of the other declared beans' lifecycle.
Assuming you need both implementations in production environment (if not - use Spring profiles to clearly split beans between environments). Simple approach would be:
interface DevService
{
void add(Device d);
String getName();
}
@Service("devServiceLocal")
class DevServiceLocalImpl implements DevService
{
void add(Device d) {...}
String getName() {return "local";}
}
class Controller
{
@Autowired
Collection<DevService> services;
void doSomethingWithService()
{
// TODO: Check type somehow
String servType = "local";
for(DevService s: services)
{
if(servType.equals(s.getName())
{
// Call service methods
break;
}
}
}
}
Your question implies that by "dynamically" you mean that you'd like to be able to select at startup time, but that you don't need to be able to change it midrun. If that's the case, I very strongly recommend using @Profile
. My usual practice, using annotation-based configuration, is to have a separate @Configuration
class for each profile that defines the profile-specific @Bean
s that need to be available there. It's even easy to define development-only @Controller
s that are completely disabled in production mode. Define a class with String
constants for each profile to avoid typos.
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