Introduction
This illustrates how to use IoC and why use IoC containers. The container used in this example is PicoContainer, others could be used also.
Motivation
We want to build an AuthenticationService (AS) to authenticate users. This service should run as a component so it's easily usable and reusable. The AS component needs another component called UserManager (UM) to get users from the user base. We want to make the UM easily exchangeable. The AS should use the UM that's available. To satisfy the dependency we write a SimpleUserManager (SUM).
AuthenticationService.java
public class AuthenticationService { private UserManager manager;public AuthenticationService(UserManager manager) { this.manager = manager; } public boolean authenticate(String name, String password) { if (manager.exists(name)) { User user = manager.get(name); return user.getPassword().equals(password); } else { return false; } }}
UserManger.java
public interface UserManager { public boolean exists(String login); public User get(String login);}
SimpleUserManager.java
public class SimpleUserManager implements UserManager { public boolean exists(String login) { return "stephan".equals(login); }public User get(String login) { return new User(login,login); }}
User.java
public class User { private String login, password;public User(String login, String password) { this.login = login; this.password = password; }
public String getPassword() { return password; }
public String getLogin() { return login; }
}
PicoContainer is only an interface so we have to use an implementation. For simpleness we use StringRegistrationNanoContainer from NanoContainer. NanoContainer is a project that supplies different containers which are PicoContainer compatible. We now can use the AuthenticationService this way:
// Build container StringRegistrationNanoContainer container = new StringRegistrationNanoContainerImpl.Default();try { container.registerComponent("AuthenticationService"); container.registerComponent("SimpleUserManager"); container.start(); } catch (Exception e) { e.printStackTrace(); }
// We only need to know about Container from here // and we usually return container from our container // creation so the container is also exchangeable // (to an XML container e.g.) Container c = container;
AuthenticationService as = (AuthenticationService) c.getComponent(AuthenticationService.class); System.out.println("stephan.authenticated = " + as.authenticate("stephan", "stephan"));
System.out.println("leo.authenticated = " + as.authenticate("leo", "wrong")); }
The nice thing is that AS get's the UM that's available, SUM in this example. If we would change "SimpleUserManager" to "LDAPUserManager" then AS would get the LDAP manager for getting users. Easily exchangeable.