写自己的框架,让别人笑掉大牙吧(IOC1)
?????? IOC在java框架中到处可见,我们只需要创建类,而不需要自己来创建实例,以及实例及实例之间的组织关系,而是通过配置文件或者注解来表明对象与对象之间的关系,最终有第三方根据配置文件及注解将需要的组件对象进行实例化的过程就是IOC。不知道这个理解是否正确,就将就着这么理解吧。通常我们使用别的框架来完成这个步骤。spring 大概大家都知道,典型的IOC ,实现也很强大。不过,spring 还是java写的,自己也来搞一个吧,虽然简单,但也能说明问题;即使很烂,也是一种实现。对吧?如果你是大牛,注意:别笑掉大牙!
?
???? 接下来就自己完成这么一个小框架吧!首先声明,所有的IOC 在本人看来必须要使用java 的反射技术,如果没有反射技术,那么这一切都是空话。 废话不说 开始吧!
?
首先我们定义一个类似spring配置文件的xml,用来定义需要框架组织的对象及组织关系。
<?xml version="1.0" encoding="UTF-8"?><beans><bean id="dao" single="true"/><bean id="service" refer="dao"/></bean><bean id="service1" refer="dao"/></bean></beans>
?
看看这2个配置的类
package com.sample.spring.egclasses;public class EgDao{public void callMe(){System.out.println("Dao is called");}}
?
package com.sample.spring.egclasses;public class EgSevice{private EgDao egDao;public void callMe(){egDao.callMe();}public EgDao getEgDao(){return egDao;}}
?
接下来编写一个了一个classloader? 本来想在这个里面干点什么,但是现在还没有想到。
package com.sample.spring;public class SampleClassLoader extends ClassLoader{private SampleClassLoader(){super();}private static final SampleClassLoader thisInstance;static{thisInstance=new SampleClassLoader();}public static SampleClassLoader getClassLoader(){return thisInstance;}}
?
接下来就是我们这雷人的框架核心了。
package com.sample.spring;import java.io.IOException;import java.lang.reflect.Field;import java.util.HashMap;import java.util.List;import java.util.Map;import org.jdom2.Document;import org.jdom2.Element;import org.jdom2.JDOMException;import org.jdom2.input.SAXBuilder;public class SampleSpringContainer{private static final Map<String,Bean> beans=new HashMap<String, Bean>();static final Map<String,Object> singles=new HashMap<String, Object>();static{ SAXBuilder sb = new SAXBuilder(); try{Document doc =sb.build(SampleSpringContainer.class.getClassLoader().getResourceAsStream("com/sample/spring/springSample.xml"));Element rootElement = doc.getRootElement();List<Element> beans = rootElement.getChildren("bean");buidBeans(beans);initBeans();}catch (JDOMException e){e.printStackTrace();}catch (IOException e){e.printStackTrace();}}private static void buidBeans(List<Element> beans){for(Element bean :beans){String id = bean.getAttributeValue("id");if(SampleSpringContainer.beans.containsKey(id))continue;String clas = bean.getAttributeValue("class");boolean single =Boolean.valueOf(bean.getAttributeValue("single"));Bean mbean=new Bean(clas, single);SampleSpringContainer.beans.put(id, mbean);List<Element> dependences = bean.getChildren("setProperty");for(Element dependence :dependences){String name = dependence.getAttributeValue("name");String agr = dependence.getAttributeValue("refer");Bean dbean2 = SampleSpringContainer.beans.get(agr);if(dbean2==null){buidDependenceBeans(beans,agr);dbean2=SampleSpringContainer.beans.get(agr);}if(dbean2==null){throw new IllegalArgumentException(id+"property "+name+"is not found");}mbean.getDependence().put(name, dbean2);}}}private static void initBeans(){for(Map.Entry<String, Bean> bean:beans.entrySet()){if(!bean.getValue().getDependence().isEmpty()){for(Map.Entry<String, Bean> dep:bean.getValue().getDependence().entrySet()){deepBuildDependence(dep.getValue().getDependence());}}singles.put(bean.getValue().getClassName(), bean.getValue().newInstance());}}private static void deepBuildDependence(Map<String, Bean> dependence){for(Map.Entry<String, Bean> dep:dependence.entrySet()){Bean bean = dep.getValue();if(!bean.getDependence().isEmpty()){deepBuildDependence(bean.getDependence());}singles.put(bean.getClassName(), bean.newInstance());}}private static void buidDependenceBeans(List<Element> beans,final String rid){for(Element bean :beans){String id = bean.getAttributeValue("id");if(!rid.equals(id))continue;String clas = bean.getAttributeValue("class");boolean single =Boolean.valueOf(bean.getAttributeValue("single"));Bean mbean=new Bean(clas, single);SampleSpringContainer.beans.put(id, mbean);List<Element> dependences = bean.getChildren("setProperty");for(Element dependence :dependences){String name = dependence.getAttributeValue("name");String agr = dependence.getAttributeValue("refer");Bean dbean2 = SampleSpringContainer.beans.get(agr);if(dbean2==null){buidDependenceBeans(beans,agr);dbean2=SampleSpringContainer.beans.get(agr);}if(dbean2==null){throw new IllegalArgumentException("");}mbean.getDependence().put(name, dbean2);}}}public static Object getBean(final String beanId){Bean bean = beans.get(beanId);if(bean!=null){if(bean.isSingle()){return singles.get(beanId);}else{return bean.newInstance();}}return null;}}class Bean{private String className;private boolean isSingle;public Bean(String className, boolean isSingle){super();this.className = className;this.isSingle = isSingle;}private Map<String,Bean> dependence=new HashMap<String, Bean>();public String getClassName(){return className;}public void setClassName(String className){this.className = className;}public boolean isSingle(){return isSingle;}public Map<String, Bean> getDependence(){return dependence;}public Object newInstance(){SampleClassLoader classLoader = SampleClassLoader.getClassLoader();Object newInstance=null;try{Class<?> loadClass = classLoader.loadClass(className);newInstance= loadClass.newInstance();for(Map.Entry<String, Bean> entity:dependence.entrySet()){Field field = loadClass.getDeclaredField(entity.getKey());field.setAccessible(true);if(entity.getValue().isSingle()){field.set(newInstance,SampleSpringContainer.singles.get(entity.getValue().getClassName()));}else{field.set(newInstance, entity.getValue().newInstance());}}}catch (ClassNotFoundException e){e.printStackTrace();}catch (InstantiationException e){e.printStackTrace();}catch (IllegalAccessException e){e.printStackTrace();}catch (SecurityException e){e.printStackTrace();}catch (NoSuchFieldException e){e.printStackTrace();}return newInstance;}}
?这个类有点长,此处并没有太多的考虑,最靠谱的首先是能够实现,对吧?
呵呵 在编写一个带main函数的类测试一下,总的有图有真相吧?
package com.sample.spring;import com.sample.spring.egclasses.EgSevice;public class TestSpring{/** * @param args */public static void main(String[] args){EgSevice bean = (EgSevice) SampleSpringContainer.getBean("service");bean.callMe();EgSevice bean1 = (EgSevice) SampleSpringContainer.getBean("service1");bean1.callMe();System.out.println(bean.getEgDao()==bean1.getEgDao());}}
?
执行结果如图:
没有骗你吧?不管咋地 首先是完成了功能。 呵呵 注解篇,请看续集!