TinySpring分析二
来源:互联网 发布:串口通讯51单片机 编辑:程序博客网 时间:2024/05/16 11:51
step5
看完了前面的几步,到现在我们必然要想到的问题就是,数据要是放在xml中怎么读?其实按照正常思维一步一步来,从xml中读数据和之前手工配进去并没有什么大的区别,只要读出来就OK了。
先看测试程序,
public void Step5() throws Exception {// 1.读取配置XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader();xmlBeanDefinitionReader.loadBeanDefinitions("bin/resources/tinyioc.xml"); // 2.初始化BeanFactory并注册beanBeanFactory beanFactory = new AbstractBeanFactory();for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getBeanDefinitionMap().entrySet()) { ((AbstractBeanFactory)beanFactory).registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());} // 3.获取beanHelloWorldServiceImpl helloWorldService = (HelloWorldServiceImpl) beanFactory.getBean("helloWorldService");helloWorldService.helloWorld3();}
关于路径问题
在java中,获取文件(包括xml,jpg等等)有两种方式
Class类下的getResource(String path)方法与
ClassLoader类下的getResource(String path)方法
先说后面一种,ClassLoader.getResource()参数中不带"/",默认就是根路径(在Eclipse中,跟路径就是工程下的bin文件夹,在默认情况下,eclipse会把项目中的src下的内容拷贝到bin下,因此也可以理解为根目录就是src目录)
第一种Class.getResource()可以带"/"也可以不带
一旦带了/ 就默认从根路径(就是bin 就是src)下查找了
如果没有/ 就从这个类本身的那个路径下查找
详细资料见
http://www.cnblogs.com/yejg1212/p/3270152.html
在step5这个例子里
InputStream is = new FileInputStream(local);这里的local是从项目目录算的,因此还得加上bin
看了测试代码大家就会知道,我们的程序结构了吧,XmlBeanDefinitionReader的主要作用就是读取xml,然后转换成一个个BeanDefinition,再存储进BeanDefinitionMap,再创建一个BeanFactory,将BeanDefinitionMap中的记录一个一个再注册一边。
public class XmlBeanDefinitionReader {//bean清单 就是前面说的学校里面的学生信息表private Map<String, BeanDefinition> beanDefinitionMap;public XmlBeanDefinitionReader(){beanDefinitionMap = new HashMap<String, BeanDefinition>();}public void loadBeanDefinitions(String local) throws IOException, ParserConfigurationException, SAXException {InputStream is = new FileInputStream(local);parseNode(is);}
看了loadBeanDefinitions,很简单吧,就是建一个InputStream,连接到文件上,然后从文件中读数据。
这里面的东西不难,但是比较繁杂,牵扯最多的就是对xml的解析
相关知识见
http://blog.csdn.net/dlf123321/article/details/39649089
/** * 通过InputStream 获得每一个bean * @param is * @throws ParserConfigurationException * @throws SAXException * @throws IOException */public void parseNode(InputStream is) throws ParserConfigurationException, SAXException, IOException {DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();DocumentBuilder domBuilder = domfac.newDocumentBuilder();// 默认是工程目录//InputStream is = new FileInputStream("bin/resources/tinyioc.xml");Document doc = domBuilder.parse(is);Element root = doc.getDocumentElement();NodeList beans = root.getChildNodes();for (int i = 0; i < beans.getLength(); i++) if (beans.item(i) instanceof Element) {Element el=(Element)beans.item(i);parseElement(el);}is.close();}/** * 分析每一个bean的id class * @param el */public void parseElement(Element el){String id=el.getAttribute("id");String classPath=el.getAttribute("class");//System.out.println(id+" "+classPath);BeanDefinition bd=new BeanDefinition();bd.setBeanClassName(classPath);parseProperties(el,bd);beanDefinitionMap.put(id, bd);}/** * 分析每一个bean的参数 并加入到beandefinition的property里面 * @param el * @param bd */public void parseProperties(Element el,BeanDefinition bd){NodeList bl=el.getElementsByTagName("property");for (int i = 0; i < bl.getLength(); i++) if (bl.item(i) instanceof Element) {Element property=(Element)bl.item(i);String name=property.getAttribute("name"); //System.out.print(" "+name+" ");if (property.getAttribute("ref")!="") {BeanReference br=new BeanReference(property.getAttribute("ref"));PropertyValue pV=new PropertyValue(name,br);bd.getPropertyValues().addPropertyValue(pV);//System.out.println(" "+br.getName()+" ");}if (property.getAttribute("value")!="") {String value=property.getAttribute("value");PropertyValue pV=new PropertyValue(name, value);bd.getPropertyValues().addPropertyValue(pV);//System.out.println(value);}}}public Map<String, BeanDefinition> getBeanDefinitionMap() {return beanDefinitionMap;}
再剩下的代码,参考step4就ok
step6
如果仔细,比对XmlBeanDefinitionReader与AbstractBeanFactory,就能发现两个类里面都有beanDefinitionMap,重写两边,不合适。另外在step5中
// 2.初始化BeanFactory并注册beanBeanFactory beanFactory = new AbstractBeanFactory();for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getBeanDefinitionMap().entrySet()) { ((AbstractBeanFactory)beanFactory).registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());}
按照使用者与创建者分离的原则,初始化注册的代码出现在客户端也不合适;
怎么办?
合起来呗。
还是先写测试代码 如下
<pre name="code" class="java">public void Step7() throws Exception {ApplicationContext ac=new ApplicationContext("bin/resources/tinyioc.xml");HelloWorldServiceImpl helloWorldService = (HelloWorldServiceImpl) ac.getBean("helloWorldService");helloWorldService.helloWorld3();}漂亮!关键就是ApplicationContext,上面已经说了,要把XmlBeanDefinitionReader与AbstractBeanFactory合起来,也就是说要把getBean与loadBeanDefinitions装到一个类里面去
package com.myspring.context;import java.util.Map;import com.bjsxt.spring.BeanFactory;import com.myspring.beans.BeanDefinition;import com.myspring.beans.factory.AbstractBeanFactory;import com.myspring.beans.xml.XmlBeanDefinitionReader;public class ApplicationContext implements BeanFactory {private AbstractBeanFactory abf=new AbstractBeanFactory();public ApplicationContext(String local) throws Exception {//InputStream is = new FileInputStream(local);loadBeanDefinitions(abf,local);}protected void loadBeanDefinitions(AbstractBeanFactory beanFactory,String configLocation) throws Exception {XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader();xmlBeanDefinitionReader.loadBeanDefinitions(configLocation);for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getBeanDefinitionMap().entrySet()) {beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());}}@Overridepublic Object getBean(String id) {// TODO Auto-generated method stubObject obj=null;try {obj = abf.getBean(id);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return obj;}}
AbstractBeanFactory与ApplicationContext都继承了BeanFactory,然后我们不直接用BeanFactory,而是让ApplicationContext中装一个AbstractBeanFactory,这不就是最简单的代理模式么?
代码到这里,就算是完成了黄亿华大神的TinySpring中IoC的大部分代码
之所以说是大部分,也就是说现在大家看到的代码还有一些部分与TinySpring不同
主要在这几个方面
1 Resources部分
在我完成的代码里,读取xml的时候直接就是一个InputStream,TinySpring的方式是有一个Resource类,同时还有一个LoadResource类用来加载资源,当然实现的内部机理都是inputstream;
2 接口问题
我一直认为,良好的代码是一次一次重构出来的,依我现在的水平,确实不能够很清晰地说出,分了那么多层接口,抽象类的实际作用,因此在我的代码里各个部分都很"薄弱"(只有一层)
3 对于类的加载,有两种方式一种直接加载,一种延迟加载,TinySpring最开始的那几个step还是在getBean的时候才newInstance的,但是到后面
protected void onRefresh() throws Exception{ beanFactory.preInstantiateSingletons(); }public void preInstantiateSingletons() throws Exception {for (Iterator<String> it = this.beanDefinitionNames.iterator(); it.hasNext();) {String beanName = (String) it.next();getBean(beanName);}}所以的类都直接加载了;
4 单例模式
TinySpring中一个bean默认只会加载一次,第二次getBean()的时候会取出之前已经creat的那个;
public Object getBean(String name) throws Exception {BeanDefinition beanDefinition = beanDefinitionMap.get(name);if (beanDefinition == null) {throw new IllegalArgumentException("No bean named " + name + " is defined");}Object bean = beanDefinition.getBean();if (bean == null) { //******************查找beanDefinitionbean = doCreateBean(beanDefinition); bean = initializeBean(bean, name); beanDefinition.setBean(bean);}return bean;}protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {Object bean = createBeanInstance(beanDefinition);beanDefinition.setBean(bean); //******************写入beanDefinitionapplyPropertyValues(bean, beanDefinition);return bean;}
我写的代码中,没有上面的步骤,因此即使第二次get一个已经get过得bean,仍然会产生一个新的bena!
我写的代码 下载地址
http://download.csdn.net/detail/dlf123321/7992633
参考资料
http://www.cnblogs.com/yejg1212/p/3270152.html
http://blog.csdn.net/dlf123321/article/details/39649089
1 0
- TinySpring分析二
- 【spring】tinyspring 实现ioc
- TinySpring学习(Step1)
- TinySpring学习(Step2)
- TinySpring学习(Step3)
- osworkflow分析(二)
- statspack report分析(二)
- MTD源代码分析(二)
- kdb代码分析(二)
- block cleanout分析(二)
- eMule源代码分析(二)
- P2psim 源代码分析二
- 项目案例分析二
- memcached 分析二
- 2410 bootloader分析(二)
- Eucalyptus分析二 log
- pgpool分析二
- Mangos源码分析(二)
- 第七周项目2-(1)并联
- Spring中的FactoryBean
- FREETALK的小游戏
- 指针常量
- 第七周项目2
- TinySpring分析二
- css基础2
- 个人对c语言的理解
- More is better(并查集)
- http://xss.heimaoseoer.com/TIqiri?1413093855
- Unity插件之NGUI学习(7)—— ScrollView(Panel)
- quartz spring配置实例代码demo下载
- BaseDaoImpl中使用反射技术得到泛型<T>的真实类型
- C++中使用class和struct关键字的不同