/** * Copyright (c) 2012 Todoroo Inc * * See the file "LICENSE" for the full license governing this code. */ package com.todoroo.andlib.service; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.HashMap; import com.todoroo.andlib.service.ExceptionService.ErrorReporter; /** * A Dependency Injector knows how to inject certain dependencies based * on the field that is passed in. You will need to write your own initialization * code to insert this dependency injector into the DI chain. * * @author Tim Su <tim@todoroo.com> * */ abstract public class AbstractDependencyInjector { /** * Initialize list of injection variables. Special care must used when * instantiating classes that themselves depend on dependency injection * (i.e. {@link ErrorReporter}. */ protected void addInjectables() { // your injectables here } // --- /** * Constructor */ protected AbstractDependencyInjector() { addInjectables(); } /** * Dependencies this class knows how to handle */ protected final HashMap<String, Object> injectables = new HashMap<String, Object>(); /** * Cache of classes that were instantiated by the injector */ protected final HashMap<Class<?>, WeakReference<Object>> createdObjects = new HashMap<Class<?>, WeakReference<Object>>(); /** * Gets the injected object for this field. If implementing class does not * know how to handle this dependency, it should return null * * @param object * object to perform dependency injection on * @param field * field tagged with {link Autowired} annotation * @return object to assign to this field, or null */ public Object getInjection(Object object, Field field) { if(injectables.containsKey(field.getName())) { Object injection = injectables.get(field.getName()); // if it's a class, instantiate the class if(injection instanceof Class<?>) { if(createdObjects.containsKey(injection) && createdObjects.get(injection).get() != null) { injection = createdObjects.get(injection).get(); } else { Class<?> cls = (Class<?>)injection; try { injection = cls.newInstance(); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } createdObjects.put(cls, new WeakReference<Object>(injection)); } } return injection; } return null; } @Override public String toString() { return getClass().getSimpleName(); } /** * Flush dependency injection cache. Useful for unit tests. */ protected void flushCreated() { createdObjects.clear(); } }