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

space.yizhu.record.aop.AopFactory Maven / Gradle / Ivy

There is a newer version: 1.3.2
Show newest version
package space.yizhu.record.aop;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;


public class AopFactory {

    
    protected ConcurrentHashMap, Object> singletonCache = new ConcurrentHashMap, Object>();

    
    protected HashMap, Class> mapping = null;

    protected static int MAX_INJECT_DEPTH = 7;            

    protected boolean singleton = true;                    
    protected boolean enhance = true;                    
    protected int injectDepth = 3;                        

    public  T get(Class targetClass) {
        try {
            return doGet(targetClass, injectDepth);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public  T get(Class targetClass, int injectDepth) {
        try {
            return doGet(targetClass, injectDepth);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    protected  T doGet(Class targetClass, int injectDepth) throws ReflectiveOperationException {
        
        

        targetClass = (Class) getMappingClass(targetClass);

        Singleton si = targetClass.getAnnotation(Singleton.class);
        boolean singleton = (si != null ? si.value() : this.singleton);

        Object ret;
        if (!singleton) {
            ret = createObject(targetClass);
            doInject(targetClass, ret, injectDepth);
            return (T) ret;
        }

        ret = singletonCache.get(targetClass);
        if (ret == null) {
            synchronized (this) {
                ret = singletonCache.get(targetClass);
                if (ret == null) {
                    ret = createObject(targetClass);
                    doInject(targetClass, ret, injectDepth);
                    singletonCache.put(targetClass, ret);
                }
            }
        }

        return (T) ret;
    }

    public  T inject(T targetObject) {
        try {
            doInject(targetObject.getClass(), targetObject, injectDepth);
            return targetObject;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public  T inject(T targetObject, int injectDepth) {
        try {
            doInject(targetObject.getClass(), targetObject, injectDepth);
            return targetObject;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    
    public  T inject(Class targetClass, T targetObject) {
        try {
            doInject(targetClass, targetObject, injectDepth);
            return targetObject;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public  T inject(Class targetClass, T targetObject, int injectDepth) {
        try {
            doInject(targetClass, targetObject, injectDepth);
            return targetObject;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    protected void doInject(Class targetClass, Object targetObject, int injectDepth) throws ReflectiveOperationException {
        if ((injectDepth--) <= 0) {
            return;
        }

        targetClass = getUsefulClass(targetClass);
        Field[] fields = targetClass.getDeclaredFields();
        if (fields.length == 0) {
            return;
        }

        for (Field field : fields) {
            Inject inject = field.getAnnotation(Inject.class);
            if (inject == null) {
                continue;
            }

            Class fieldInjectedClass = inject.value();
            if (fieldInjectedClass == Void.class) {
                fieldInjectedClass = field.getType();
            }

            Object fieldInjectedObject = doGet(fieldInjectedClass, injectDepth);
            field.setAccessible(true);
            field.set(targetObject, fieldInjectedObject);
        }
    }

    
    @SuppressWarnings("deprecation")
    protected Object createObject(Class targetClass) throws ReflectiveOperationException {
        Enhance en = targetClass.getAnnotation(Enhance.class);
        boolean enhance = (en != null ? en.value() : this.enhance);

        return targetClass.newInstance();
    }

    
    protected Class getUsefulClass(Class clazz) {
        
        
        return (Class) (clazz.getName().indexOf("$$EnhancerBy") == -1 ? clazz : clazz.getSuperclass());
    }

    
    @Deprecated
    public AopFactory setEnhance(boolean enhance) {
        this.enhance = enhance;
        return this;
    }

    
    public AopFactory setSingleton(boolean singleton) {
        this.singleton = singleton;
        return this;
    }

    public boolean isSingleton() {
        return singleton;
    }

    
    public AopFactory setInjectDepth(int injectDepth) {
        if (injectDepth <= 0) {
            throw new IllegalArgumentException("注入层数必须大于 0");
        }
        if (injectDepth > MAX_INJECT_DEPTH) {
            throw new IllegalArgumentException("为保障性能,注入层数不能超过 " + MAX_INJECT_DEPTH);
        }

        this.injectDepth = injectDepth;
        return this;
    }

    public int getInjectDepth() {
        return injectDepth;
    }

    public AopFactory addSingletonObject(Object singletonObject) {
        if (singletonObject == null) {
            throw new IllegalArgumentException("singletonObject can not be null");
        }
        if (singletonObject instanceof Class) {
            throw new IllegalArgumentException("singletonObject can not be Class type");
        }

        Class type = getUsefulClass(singletonObject.getClass());
        if (singletonCache.putIfAbsent(type, singletonObject) != null) {
            throw new RuntimeException("Singleton object already exists for type : " + type.getName());
        }

        return this;
    }

    public synchronized  AopFactory addMapping(Class from, Class to) {
        if (from == null || to == null) {
            throw new IllegalArgumentException("The parameter from and to can not be null");
        }

        if (mapping == null) {
            mapping = new HashMap, Class>(128, 0.25F);
        } else if (mapping.containsKey(from)) {
            throw new RuntimeException("Class already mapped : " + from.getName());
        }

        mapping.put(from, to);
        return this;
    }

    public  AopFactory addMapping(Class from, String to) {
        try {
            @SuppressWarnings("unchecked")
            Class toClass = (Class) Class.forName(to.trim());
            if (from.isAssignableFrom(toClass)) {
                return addMapping(from, toClass);
            } else {
                throw new IllegalArgumentException("The parameter \"to\" must be the subclass or implementation of the parameter \"from\"");
            }
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    
    public Class getMappingClass(Class from) {
        if (mapping != null) {
            Class ret = mapping.get(from);
            return ret != null ? ret : from;
        } else {
            return from;
        }
    }
}











© 2015 - 2025 Weber Informatics LLC | Privacy Policy