container
defaultcontainer
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.apache.log4j.Logger;import com.easyjf.minicontainer.Container;import com.easyjf.minicontainer.annotation.Inject;public class DefaultContainer implements Container { private static final Logger logger = Logger.getLogger(DefaultContainer.class); private final Map objMap = new HashMap(); public Object getBean(String name) { return objMap.get(name); } public Object getBean(Class type) { Iterator it = this.objMap.values().iterator(); while(it.hasNext()){ Object obj = it.next(); if(type.isAssignableFrom(obj.getClass())){ return obj; } } return null; } public Collection getBeanName() { return null; } public List getBeans(String name) { return null; } public List getBeans(Class type) { return null; } public boolean hasBean(Class clz) { if(this.getBean(clz)!=null){ return true; } return false; } public boolean hasBean(String name){ if(this.getBean(name)!=null){ return true; } return false; } public void init() { Config config = new Config(); config.init(this); refresh(); } public void registBean(Class clz){ String name = clz.getCanonicalName(); try { if(!Modifier.isAbstract(clz.getModifiers())&&!Modifier.isInterface(clz.getModifiers())){ logger.debug("加载了类:"+name); Object obj = clz.newInstance(); objMap.put(name, obj); }else{ Inject inject = (Inject)clz.getAnnotation(Inject.class); String taget = inject.target(); if("".equals(taget)){ throw new RuntimeException( "接口必须指定目标类!"); } Class tagetClz = Class.forName(taget); Object tagetObj = tagetClz.newInstance(); logger.debug("加载了类:"+name); objMap.put(name, tagetObj); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public void refresh(){ Iterator it = this.objMap.values().iterator(); while(it.hasNext()){ try { Object obj = it.next(); String name = obj.getClass().getCanonicalName(); Field[] fields = obj.getClass().getDeclaredFields(); for(Field field : fields){ Annotation inject = field.getAnnotation(Inject.class); if(inject!=null){ Object arg = this.getBean(field.getType()); if(arg==null){ throw new RuntimeException( "无法加载"+field.getType().getCanonicalName()+"!"); } String fieldName = field.getName(); String methodName = "set" +fieldName.substring(0, 1).toUpperCase() +fieldName.substring(1, fieldName.length()); Method method; method = obj.getClass() .getDeclaredMethod(methodName, arg.getClass()); if(method != null){ method.invoke(obj, arg); }else{ throw new RuntimeException("无法加载" +obj.getClass().getCanonicalName() +"."+field.getName() +",找不到该字段的set方法!"); } } } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }}
这里主要说说registBean(Class clz)和refresh()这两个方法。registBean(Class clz)是由另外一个类来调用的,这里主要说说这个方法的功能。这个方法接受一个Class类型的参数,然后判断这个Class是不是接口或者抽象类,如果是就根据其@Inject注解中的target值来找到一个类,并初始化这个类。如果不是就直接实例化并且放入容器中。
refresh()方法则是在加载完需要加载的类之后开始执行注入操作。通过迭代容器中的所有bean,来扫描每一个bean,看看是否有需要注入的字段(即使用了@Inject注解的字段),然后执行这个字段的setter方法,实现注入(未实现构造子注入)。
接下来是Config类,这个类的功能主要是扫面classes目录下的文件,找到所有class文件并尝试交给DefaultContainer来加载。
代码如下:
}
这个类有三个重要方法:getPackagePath()、loadClassFromDir(String path)、loadClassFromFile(String path)。
getPackagePath()功能是获取当前应用的classes目录所处的绝对路径。loadClassFromDir(String path)方法是从一个目录中加载类,这里有一个递归调用,从而遍历所有子目录。loadClassFromFile(String path)的功能就是从一个文件中加载类。