Skip to content

Instantly share code, notes, and snippets.

@amoerie
Created June 20, 2013 19:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amoerie/5826079 to your computer and use it in GitHub Desktop.
Save amoerie/5826079 to your computer and use it in GitHub Desktop.
public class SmartBox {
private Map<Class, Class> bindings;
public SmartBox() {
this.bindings = new HashMap<>();
}
/**
* Binds {@TService} class to {@TInstance}
*
* @param service
* the service class to bind to
* @param instance
* the instance that will be bound to the service
* @param <TService>
* the type of the service
* @param <TInstance>
* the type of the instance that must extend (or implement) {@TService}
*/
public <TService, TInstance extends TService> void bind(Class<TService> service, Class<TInstance> instance) {
bindings.put(service, instance);
}
/**
* Gets an instance of {@TService}
*
* @param service
* the class of the requested service
* @param <TService>
* the requested service
* @return an instance of {@TService}
*/
public <TService> TService get(Class<TService> service)
throws IllegalAccessException, InstantiationException, InvocationTargetException {
if (bindings.containsKey(service))
// this service is bound! Let's get the bound instance for it.
return (TService) get(bindings.get(service));
else
// no registered binding, let's see if we can resolve it
return resolve(service);
}
private <TService> TService resolve(Class<TService> service)
throws IllegalAccessException, InvocationTargetException, InstantiationException {
// get constructor
Constructor<?>[] constructors = service.getConstructors();
if (constructors.length == 0)
throw new IllegalArgumentException("No public constructor found for " + service);
if (constructors.length > 1)
throw new IllegalArgumentException("More than one public constructor found in " + service);
Constructor constructor = constructors[0];
// inspect the constructor parameters
Class[] requestedServices = constructor.getParameterTypes();
// resolve each constructor parameter
Object[] resolvedServices = new Object[requestedServices.length];
for (int i = 0; i < requestedServices.length; i++) {
resolvedServices[i] = get(requestedServices[i]);
}
// invoke constructor
return (TService) constructor.newInstance(resolvedServices);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment