Java tutorial
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2015, Markus Staudt <info@braffdev.com> * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package com.braffdev.server.core.container.injection; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.braffdev.server.core.container.Container; import com.braffdev.server.core.container.Registry; import com.braffdev.server.core.io.logger.Logger; import com.braffdev.server.lib.injection.Dependency; /** * */ public class DependencyInjector { private static final Logger LOGGER = Logger.getLogger(DependencyInjector.class); /** * Injects all suitable dependencies to the instances located in the <code>InstanceRegistry</code> of the given container. * * @param container the container. */ public static void inject(Container container) { Registry<Object> instanceRegistry = container.getInstanceRegistry(); Map<String, Object> instances = instanceRegistry.getMap(); Iterator<Object> iterator = instances.values().iterator(); while (iterator.hasNext()) { DependencyInjector.inject(iterator.next(), container); } } /** * Injects the dependencies of the given object. * * @param target the object to inject it's dependencies. * @param container the container. */ private static void inject(Object target, Container container) { List<Field> fields = DependencyInjector.getFields(target); for (Field field : fields) { DependencyInjector.injectField(field, target, container); } } /** * Injects the given field of the given object. * * @param field the field to inject. * @param target the object. * @param container the container. */ private static void injectField(Field field, Object target, Container container) { Dependency dep = field.getAnnotation(Dependency.class); String dependencyName = dep.value(); if (StringUtils.isBlank(dependencyName)) { // use the classes name if no name is provided dependencyName = DependencyInjectionUtils.getDefaultName(field); } Object dependency = container.getDependencyRegistry().get(dependencyName); if (dependency != null) { DependencyInjector.injectFieldDependency(field, target, dependencyName, dependency); } else { LOGGER.error("No dependency found with name \"" + dependencyName + "\" in class \"" + target.getClass().getSimpleName() + "\""); } } /** * Injects the given dependency to the given field of the given object. * * @param field the field to inject. * @param target the object. * @param dependencyName the name of the dependency. * @param dependency the dependency to inject. */ private static void injectFieldDependency(Field field, Object target, String dependencyName, Object dependency) { Class<?> fieldClass = field.getType(); if (!dependency.getClass().isAssignableFrom(fieldClass)) { LOGGER.error("Dependency \"" + dependencyName + "\" (class " + dependency.getClass().getName() + ") cannot be injected. This class is not assignable from the target field"); return; } try { field.setAccessible(true); field.set(target, dependency); LOGGER.debug("Injected dependency \"" + dependencyName + "\" of class \"" + target.getClass() + "\""); } catch (Throwable t) { LOGGER.error("Cannot inject dependency \"" + dependencyName + "\"", t); } } /** * Determines the list of fields that need to be injected. * * @param target the object. * @return the list of fields. */ private static List<Field> getFields(Object target) { List<Field> fields = new ArrayList<Field>(); Class<?> clazz = target.getClass(); while (!Object.class.equals(clazz)) { Field[] declaredFields = clazz.getDeclaredFields(); for (Field field : declaredFields) { // is the Dependency annotation present? if (field.isAnnotationPresent(Dependency.class)) { fields.add(field); } } clazz = clazz.getSuperclass(); } return fields; } }