All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nikedlab.android.inject.processors.Injector Maven / Gradle / Ivy

The newest version!
package com.nikedlab.android.inject.processors;

import com.nikedlab.android.inject.annotations.Autowired;
import com.nikedlab.android.inject.annotations.Component;
import com.nikedlab.android.inject.annotations.Resource;
import com.nikedlab.android.inject.exceptions.InjectException;
import com.nikedlab.android.inject.interfaces.ApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Injector {
	
    private ApplicationContext applicationContext;
	private Map, Object> singletons;
	private Map singletonsByName;
    
    /**
     * Constructor.
     * @param applicationContext Context to retrieve beans from.
     */
	public Injector(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		singletons = new HashMap, Object>();
		singletonsByName = new HashMap();
	}
	
	/**
	 * Inject dependencies into target.
	 * @param target Target with dependencies.
	 */
	public void inject(Object target) {
		Class targetClass = target.getClass();
		Method[] methods = targetClass.getMethods();
		for (Method method : methods) {
			if (method.getName().startsWith("set")) {
				Object[] parameters = null;
				Autowired autowired = method.getAnnotation(Autowired.class);

				if (autowired != null) {
					parameters = getAutowireParameters(method);
				} else {
					Resource resource = method.getAnnotation(Resource.class);
					if (resource != null) {
						parameters = getResourceParameters(resource, method);
					}
				}

				if (parameters != null) {
					try {
						method.invoke(target, parameters);
					} catch (IllegalArgumentException e) {
						throw new InjectException("Failed to inject setter: " + method.getName() + ", target: " + target.getClass(), e);
					} catch (IllegalAccessException e) {
						throw new InjectException(e);
					} catch (InvocationTargetException e) {
						throw new InjectException(e);
					}
				}
			}
		}
	}
	
	/**
	 * Inject application context beans into parameters.
	 * @param method Method to be invoked.
	 */
	private Object[] getAutowireParameters(Method method) {
		Class[] parameterTypes = method.getParameterTypes();
		Object[] parameters = new Object[parameterTypes.length];

		int parameterIndex = 0;
		boolean allParametersInstantiated = true;
		for (Class parameterType : parameterTypes) {
            Autowired annotation = method.getAnnotation(Autowired.class);
            Class clazz = annotation.implementation();
            if (clazz != Autowired.None.class) {
                parameterType = clazz;
            }

            if (applicationContext.containsType(parameterType)) {
				Object bean = getBean(parameterType);
				inject(bean);
				parameters[parameterIndex] = bean;
			} else {
				allParametersInstantiated = false;
			}
			parameterIndex++;
		}
		if (!allParametersInstantiated) {
			parameters = null;
		}
		return parameters;
	}

	/**
	 * Inject application context beans into parameters.
	 * @param method Method to be invoked.
	 */
	private Object[] getResourceParameters(Resource resource, Method method) {
		Object[] parameters = null;
		Class[] parameterTypes = method.getParameterTypes();
		if (parameterTypes.length == 1) {
			parameters = new Object[parameterTypes.length];
			parameters[0] = getBean(resource.value());
		}
		
		return parameters;
	}

	@SuppressWarnings("unchecked")
    private  T getBean(Class interfaceClass) {
	    T bean;
		if (singletons.containsKey(interfaceClass)) {
            bean = (T) singletons.get(interfaceClass);
		} else {
		    bean = applicationContext.getBean(interfaceClass);
		    Class implementationClass = bean.getClass();
	        Component component = implementationClass.getAnnotation(Component.class);
	        if (component != null) {
	            inject(bean);
	        }
			singletons.put(interfaceClass, bean);
		}
	    
	    return bean;
	}
	
    private Object getBean(String name) {
	    Object bean;
		if (singletonsByName.containsKey(name)) {
			bean = singletonsByName.get(name);
		} else {
			bean = applicationContext.getBean(name);
		    Class implementationClass = bean.getClass();
	        Component component = implementationClass.getAnnotation(Component.class);
	        if (component != null) {
	            inject(bean);
	        }
			singletonsByName.put(name, bean);
			Class[] interfaces = implementationClass.getInterfaces();
			for (Class interfaceClass : interfaces) {
				singletons.put(interfaceClass, bean);
			}
		}
	    
	    return bean;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy