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

org.tinygroup.tinyioc.impl.BeanContainerImpl Maven / Gradle / Ivy

There is a newer version: 2.2.3
Show newest version
/**
 *  Copyright (c) 1997-2013, www.tinygroup.org ([email protected]).
 *
 *  Licensed under the GPL, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.gnu.org/licenses/gpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.tinygroup.tinyioc.impl;

import org.apache.commons.beanutils.BeanUtils;
import org.tinygroup.tinyioc.*;
import org.tinygroup.tinyioc.annotation.*;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * Created by luoguo on 13-12-27.
 */
public class BeanContainerImpl implements BeanContainer {
	private DynamicProxy proxy = new DynamicProxy();
    private ThreadLocal threadLocal = new ThreadLocal();
    private Map nameMap = new HashMap();
    private Map scopeMap = new HashMap();
    private List classList = new ArrayList();
    private Map objectMap = new HashMap();
    private Map typeConverterMap = new HashMap();
    private BeanContainer parent = null;
    private List beanContainerList = new ArrayList();

    private ClassLoader classLoader;

    public BeanContainerImpl() {

    }

    public BeanContainerImpl(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public  void registerClass(Class clazz) {
        Named named = clazz.getAnnotation(Named.class);
        if (named != null && named.value().length() > 0) {
            nameMap.put(named.value(), clazz);
        }
        String scope = "singleton";
        Request request = clazz.getAnnotation(Request.class);
        if (request != null) {
            scope = "request";
        }
        Prototype prototype = clazz.getAnnotation(Prototype.class);
        if (prototype != null) {
            scope = "prototype";
        }

        classList.add(clazz);
        scopeMap.put(clazz, scope);
    }

    public  T getBeanByName(String name) {
        Class clazz = nameMap.get(name);
        if (clazz == null) {
            throw new RuntimeException(String.format("bean with name [%s] not found", name));
        }
        try {
            return (T) getBeanByType(clazz);
        } catch (RuntimeException e) {
            if (parent != null) {
                return (T) parent.getBeanByName(name);
            } else {
                throw e;
            }
        }
    }

    public  T getBeanByType(String type) {
        Class clazz = null;
        try {
            clazz = Class.forName(type);
            return (T) getBeanByType(clazz);
        } catch (ClassNotFoundException e) {
            if (parent != null) {
                return (T) parent.getBeanByType(type);
            }
            throw new RuntimeException(e);
        }

    }

    public  T getBeanByType(Class clazz) {
        String scope = scopeMap.get(clazz);
        T object = null;

        if (scope != null) {
            if (("singleton").equalsIgnoreCase(scope)) {
                object = getSingletonObject(clazz);
            } else if (("prototype").equalsIgnoreCase(scope)) {
                object = getPrototypeObject(clazz);
            } else if (("request").equalsIgnoreCase(scope)) {
                object = getThreadObject(clazz);
            }
        } else {
            //如果是子孙类或实现了接口
            for (Class clz : classList) {
                if (isSubClass(clz, clazz)) {
                    object = (T) getBeanByType(clz);
                }
            }
        }
        if (object != null) {
            return object;
        }
        if (parent != null) {
            return parent.getBeanByType(clazz);
        }
        throw new RuntimeException(clazz.getName() + " not found in container.");
    }

    private  void buildObject(T object, Class clazz) {
        for (Field field : clazz.getDeclaredFields()) {
            Inject inject = field.getAnnotation(Inject.class);
            //如果属性上有注解
            if (inject != null) {
//                String name = null;
                Named named = field.getAnnotation(Named.class);
                Value valueAnnotation = field.getAnnotation(Value.class);
                if (named != null && named.value().length() > 0) {
//                    name = named.value();
                }
                Object value = null;
                Type fc = field.getGenericType();
                if (fc instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) fc;
                    Class genericClazz = (Class) pt.getActualTypeArguments()[0];
                    value = getCollectionObject(field, genericClazz);
                } else if (valueAnnotation != null && valueAnnotation.value().length() > 0) {
                    //如果是设置的固定值
                    value = getValueObject(field, valueAnnotation.value());
                } else {
                    value = getSingleObject(field, inject, named);

                }
                if (value != null) {
                    try {
                        BeanUtils.setProperty(object, field.getName(), value);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    throw new RuntimeException(String.format("类%s的属性%s对应的Bean找不到!", object.getClass().getName(), field.getName()));
                }
            }
        }
    }

    private Object getSingleObject(Field field, Inject inject, Named named) {
        Object value;
        if (named != null && named.value().length() > 0) {
            //如果是按名字
            value = getBeanByName(named.value());
        } else {
            //自动进行检测
            value = getBeanByType(field.getType());
            if (value == null) {
                value = getBeanByName(field.getName());
            }
        }
        return value;
    }

    private Object getValueObject(Field field, String stringValue) {
        Object value;
        TypeConverter converter = typeConverterMap.get(field.getType());
        if (converter != null) {
            value = converter.convert(stringValue);
        } else {
            value = stringValue;
        }
        return value;
    }

    private Object getCollectionObject(Field field, Class clazz) {
        Object value = null;
        if (field.getType().equals(List.class)) {
            value = getBeanList(clazz);
        } else if (field.getType().equals(Set.class)) {
            value = getBeanSet(clazz);
        } else if (field.getType().equals(Collection.class)) {
            value = getBeanCollection(clazz);
        }
        return value;
    }

    public static boolean isSubClass(Class a, Class b) {
        Type genericSuperclass = a.getGenericSuperclass();
        for (Type type : a.getGenericInterfaces()) {
            if (type.equals(b)) {
                return true;
            }
            boolean is = isSubClass((Class) type, b);
            if (is) {
                return true;
            }
        }
        if (genericSuperclass != null) {
            if (genericSuperclass.equals(b)) {
                return true;
            } else {
                boolean is = isSubClass((Class) genericSuperclass, b);
                if (is) {
                    return true;
                }
            }
        }
        return false;
    }

    private  T getThreadObject(Class clazz) {
        Map threadMap = (Map) threadLocal.get();
        if (threadMap == null) {
            threadMap = new HashMap();
            threadLocal.set(threadMap);
        }
        T object = (T) threadMap.get(clazz);
        if (object == null) {
            object = getPrototypeObject(clazz);
            threadMap.put(clazz, object);
        }
        return object;
    }

    private  T getPrototypeObject(Class clazz) {
        try {
            T object = null;
            if (!isInterceptorClass(clazz) && proxy.isMatchClassName(clazz.getName())) {
                object = proxy.getProxyObject(clazz);
            } else {
                object = clazz.newInstance();
            }
            buildObject(object, clazz);
            return object;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    boolean isInterceptorClass(Class clz) {
        if (isSubClass(clz, InterceptorAfter.class)) {
            return true;
        }
        if (isSubClass(clz, InterceptorBefore.class)) {
            return true;
        }
        return isSubClass(clz, InterceptorException.class);
    }

    private  T getSingletonObject(Class clazz) {
        T object = (T) objectMap.get(clazz);
        if (object == null) {
            object = getPrototypeObject(clazz);
            objectMap.put(clazz, object);
        }
        return object;
    }

    public  List getBeanList(String type) {
        Class typeClazz = null;
        try {
            typeClazz = Class.forName(type);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return getBeanList(typeClazz);
    }

    public  List getBeanList(Class clazz) {
        List list = new ArrayList();
        for (Class clz : classList) {
            if (isSubClass(clz, clazz)) {
                T beanByType = (T) getBeanByType(clz);
                list.add(beanByType);
            }
        }
        return list;
    }

    public  Set getBeanSet(String type) {
        Class typeClazz = null;
        try {
            typeClazz = Class.forName(type);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return getBeanSet(typeClazz);
    }

    public  Set getBeanSet(Class clazz) {
        Set set = new HashSet();
        for (Class clz : classList) {
            if (isSubClass(clz, clazz)) {
                T beanByType = (T) getBeanByType(clz);
                set.add(beanByType);
            }
        }
        return set;
    }

    public  Collection getBeanCollection(String type) {
        return getBeanList(type);
    }

    public  Collection getBeanCollection(Class clazz) {
        return getBeanList(clazz);
    }

    public boolean isExistBeanByName(String name) {
        return nameMap.containsKey(name);
    }

    public boolean isExistBeanByType(String type) {
        try {
            return isExistBeanByType(Class.forName(type));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isExistBeanByType(Class clazz) {
        return typeConverterMap.containsKey(clazz);
    }

    public void addTypeConverter(TypeConverter typeConverter) {
        typeConverterMap.put(typeConverter.getType(), typeConverter);
    }

    public void addAop(AopDefine aopDefine) {
        proxy.addAop(aopDefine);
    }

    public void setParent(BeanContainer beanContainer) {
        this.parent = beanContainer;
    }

    public void addBeanContainer(BeanContainer beanContainer) {
        if (!beanContainerList.contains(beanContainer)) {
            beanContainerList.add(beanContainer);
            beanContainer.setParent(this);
        }
    }

    public void removeBeanContainer(BeanContainer beanContainer) {
        if (beanContainerList.contains(beanContainer)) {
            beanContainerList.remove(beanContainer);
            beanContainer.setParent(null);
        }
    }

    public void setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public ClassLoader getClassLoader() {
        if (classLoader == null) {
            return this.getClass().getClassLoader();
        }
        return classLoader;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy