
org.diablitozzz.jin.impl.JinFactoryAbstract Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jin Show documentation
Show all versions of jin Show documentation
Jin is a small library, without the dependencies, that implements the dependency injection using annotations or XML.
The newest version!
package org.diablitozzz.jin.impl;
import java.io.Closeable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.diablitozzz.jin.Jin;
import org.diablitozzz.jin.JinClose;
import org.diablitozzz.jin.JinException;
import org.diablitozzz.jin.JinFactoryInterface;
import org.diablitozzz.jin.JinInit;
import org.diablitozzz.jin.JinInject;
/**
* A default abstract implementation of the Jin factory.
*
* @author Vladimir Ionov
*/
abstract public class JinFactoryAbstract implements JinFactoryInterface {
protected static class InjectField {
private final Field field;
private final Class> injectClass;
private final String injectName;
private final boolean singleton;
public InjectField(final Field field) throws JinException {
this.field = field;
this.field.setAccessible(true);
final JinInject annotation = field.getAnnotation(JinInject.class);
this.injectClass = field.getType();
this.injectName = annotation.name();
this.singleton = annotation.singleton();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final InjectField other = (InjectField) obj;
if (this.field == null) {
if (other.field != null) {
return false;
}
} else if (!this.field.equals(other.field)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.field == null) ? 0 : this.field.hashCode());
return result;
}
public void inject(final Jin jin, final Object instance) throws JinException {
final Object injectInstance = this.singleton ? jin.singleton(this.injectClass, this.injectName) : jin.instance(this.injectClass, this.injectName, true);
try {
this.field.setAccessible(true);
this.field.set(instance, injectInstance);
} catch (final Throwable e) {
throw JinException.create(e, "Can't inject depends");
}
}
}
protected static Method findInitOrCloseMethod(final Class> clazz, final boolean init) throws JinException {
for (final Method method : clazz.getDeclaredMethods()) {
if (method.getParameterTypes().length != 0) {
continue;
}
if (method.isAnnotationPresent(init ? JinInit.class : JinClose.class)) {
method.setAccessible(true);
return method;
}
}
return null;
}
protected static Set findInjectFields(final Class> clazz) throws JinException {
final LinkedHashSet result = new LinkedHashSet<>();
final List> classChain = JinFactoryAbstract.getClassChain(clazz);
// make protected
for (final Class> chainItem : classChain) {
for (final Field field : chainItem.getDeclaredFields()) {
if (!Modifier.isPrivate(field.getModifiers())) {
continue;
}
if (!field.isAnnotationPresent(JinInject.class)) {
continue;
}
field.setAccessible(true);
result.add(new InjectField(field));
}
}
// make not protected
for (final Class> chainItem : classChain) {
for (final Field field : chainItem.getDeclaredFields()) {
if (Modifier.isPrivate(field.getModifiers())) {
continue;
}
if (!field.isAnnotationPresent(JinInject.class)) {
continue;
}
field.setAccessible(true);
result.add(new InjectField(field));
}
}
return result;
}
protected static List> getClassChain(final Class> clazz) {
final List> out = new ArrayList>();
Class> current = clazz;
while (true) {
if (current.isInterface()) {
break;
}
out.add(current);
current = current.getSuperclass();
if ((current == null) || current == Object.class) {
break;
}
}
Collections.reverse(out);
return out;
}
protected T singleton;
protected final Jin jin;
protected final Class targetClass;
protected final Set injectFields;
protected Method initMethod;
protected Method closeMethod;
protected final String name;
protected final boolean lazy;
public JinFactoryAbstract(final Jin jin, final Class targetClass, final String name, final boolean lazy) throws JinException {
this.targetClass = targetClass;
this.jin = jin;
this.lazy = lazy;
this.name = name;
if (targetClass == null) {
throw JinException.create("Can't create factory. Target class can't be a null");
}
this.injectFields = JinFactoryAbstract.findInjectFields(targetClass);
this.initMethod = JinFactoryAbstract.findInitOrCloseMethod(this.targetClass, true);
this.closeMethod = JinFactoryAbstract.findInitOrCloseMethod(this.targetClass, false);
}
@Override
public void close() {
if (this.singleton != null) {
this.close(this.singleton);
}
this.singleton = null;
}
protected void close(final T instance) {
try {
if (this.closeMethod != null) {
this.closeMethod.invoke(instance, new Object[] {});
} else if (instance instanceof AutoCloseable) {
((AutoCloseable) instance).close();
} else if (instance instanceof Closeable) {
((Closeable) instance).close();
}
} catch (final Throwable e) {
//ignore
}
}
abstract protected T createInstance() throws JinException;
@Override
public String getName() {
return this.name;
}
@Override
public Class getTargetClass() {
return this.targetClass;
}
protected void init(final T instance) throws JinException {
try {
if (this.initMethod != null) {
this.initMethod.invoke(instance, new Object[] {});
}
} catch (final Throwable e) {
throw JinException.create(e);
}
}
@Override
public JinFactoryInterface inject(final T instance) throws JinException {
if (instance == null) {
throw JinException.create("Can't inject to null instance");
}
if (!this.targetClass.isAssignableFrom(instance.getClass())) {
throw JinException.create("Can't inject instance class:%s not equals manager class:%s", instance.getClass(), this.targetClass);
}
for (final InjectField injectField : this.injectFields) {
injectField.inject(this.jin, instance);
}
return this;
}
@Override
public T instance(final boolean injectDepends) throws JinException {
final T instance = this.createInstance();
if (injectDepends) {
this.inject(instance);
}
this.init(instance);
return instance;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
public T singleton() throws JinException {
if (this.singleton == null) {
this.singleton = this.instance(true);
}
return this.singleton;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy