设计模式之_工厂系列_04

package com.learn.spring;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	
	public static void main(String[] args) throws Exception {
		
//		Properties props = new Properties();
		
		/**
		 * 我们原来是从配置文件里面读,现在我们可以从Spring他自己的配置文件里面读
		 * 
		 */
//		props.load(Test.class.getClassLoader().getResourceAsStream("com/learn/spring/spring.properties"));
//		
//		String vehicleTypeName = props.getProperty("VehicleType");
//		
//		System.out.println(vehicleTypeName);
//		
//		Object o = Class.forName(vehicleTypeName).newInstance();
		
		/**
		 * 对于Spring来说,applicationContext这个配置文件就是记录一系列的对象
		 * 具体对象的Class类型,而这些类型都有一个v,这个是不是很类似于v=com.learn.spring.Car
		 * 换了个马甲你就不认识了,他无非就是换了中形式而已,里的内容换汤不换药,原来都是让你去那个配置文件里面读
		 * 现在让Spring帮我们来读就行了,Spring有一个类叫BeanFactory,就是Bean工厂
		 * 产生JavaBean的工厂,产生JAVA对象的工厂,对于BeanFactory来说他又一个子类,
		 * BeanFactory是一个interface,其中有一个ClassPathXmmApplicationContext,
		 * 你别管他名字有多长,他名字再长也是BeanFactory,因为他实现了BeanFactory接口,
		 * 所以既然他实现了BeanFactory接口,ClassPathXmlApplicationContext类路径下的XML的应用上下文
		 * 这个子类有一个方法,从哪个文件读取配置信息,里面指定要从什么样的配置文件去读,这个配置文件叫applicationContext.xml
		 * 
		 */
		BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		/**
		 * 这个接口有一个方法getBean
		 * 这个v是什么,v就是我写在这个配置文件里面的id,
		 * 你根据id就能找到对应的class,找到class就可以通过newInstance产生一个对象
		 * 然后把bean反馈回来就好了
		 */
		Object o = factory.getBean("v");
		
		Moveable m = (Moveable)o;
		
		/**
		 * 输出的红字不用管,那是Spring跟踪输出的信息
		 * 冒着烟奔跑中car...... 因为我们配置的是Car,
		 * 假如我们配置文件里面配置的是Train,
		 * 小火车.... 就变成这个了
		 */
		m.run();				
		
		// Moveable m = new Car();
		// m.run();
		
	}	
}
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee.xsd
		http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!-- beans是最根上的那个节点,不用管 -->
    <!-- id等于v代表它是Vehicle -->
    <bean id="v" class="com.learn.spring.Train"></bean>
       
</beans>  
package com.learn.spring;

public interface BeanFactory {

	Object getBean(String id);
}
package com.learn.spring;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 刚才我们看到了ClassPathXmlApplicationContext里面有一个构造方法,
 * 里面有一个文件名fileName
 * 
 * 我们从配置文件读取信息之后,我们读出v等于什么,接下来我们new个对象出来,
 * 然后把v作为key,把后面的对象作为value存在Map里,当别人想找我里面的东西的时候,
 * 你把id传过来比如叫v,我们容器里面把id等于v的丢出来就行了,就这么简单,
 * 这就是最简单bean容器的概念,所以Spring为什么叫做容器
 * @author Leon.Sun
 *
 */
public class ClassPathXmlApplicationContext implements BeanFactory {
	
	/**
	 * 所谓的bean的容器是这么来的,
	 * 在我们的BeanFactory里面有一个什么东西呢,叫Map<String,Object>
	 * Map里面装的是key和value,所以我们说Spring是一个bean的容器
	 * 原因就来自这个地方,因为它会把配置文件读出来的所有的信息全都保存在一个Map里面,
	 * 这就是他的那个容器,所以你别把他想的太复杂了,
	 */
	private Map<String,Object> container = new HashMap<String,Object>();	
	
	
	/**
	 * 我们通过fileName指向配置文件,他就能从配置文件读取配置信心来
	 * 通过getBean来生成具体的bean,下面的问题变成了当我拿到文件之后,
	 * 我该怎么样去把里面的东西拿出来之后产生一个bean的信息,当你调用getBean的时候,
	 * 再反馈给我们的客户,这个问题就稍微有点复杂了,
	 * xml文件我该怎么去读呢,简单起见我先把namespace的内容先给他去掉
	 * 就这样的一个xml我该怎么去读呢,假如你已经把XML文件给读出来了,你已经得到v了,
	 * 得到这个class了,大家能不能产生自己的bean,假如你已经得到class的名字了,
	 * 能不能自己产生那个bean,Java四种解析XML技术,首先出场的是DOM,
	 * 你随便用一个就行了,什么叫做应用驱动学习,你用JDOM一定可以把东西拿出来,
	 * @param fileName
	 */
	@SuppressWarnings("unchecked")
	public ClassPathXmlApplicationContext(String fileName) {
        try {
			SAXReader reader = new SAXReader();
			File file = new File(fileName);
			Document document = reader.read(file);
			Element root = document.getRootElement();
			List<Element> list = root.selectNodes("bean");  
			// System.out.println(list);
			/**
			 * 因为我们在beans的根目录下只有一个bean
			 */
			System.out.println(list.size());
			for (Element bean : list) {
				/**
				 * 拿属性可以这么拿
				 * 已知属性名情况下
				 * 这两句话的意思是当我们拿到bean节点的时候,我们根据里面的方法拿到id属性的值
				 * 拿到class属性对应的值,分别把它装到id和clazz里面
				 */
				String id = bean.attributeValue("id");
			    String clazz  = bean.attributeValue("class");
			    /**
			     * 生成一个对象
			     */
			    Object o = Class.forName(clazz).newInstance();
			    
			    /**
			     * 然后在把这个东西放在容器里
			     */
			    container.put(id, o);
			    
			    
			    /**
			     * 如果你不信你可以打印一下
			     * 你可以发现可以拿到v的信息和class的信息
			     * 拿到具体class的信息了,
			     */
			    System.out.println("id: " + id);    
			    System.out.println("clazz" + clazz);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * getBean的时候怎么拿呢?主要是去配置文件里把信息读出来
	 * 找到id为他的东西,读出来之后就return出来就行了
	 * 如果这个配置文件是spring.properties,我相信大家应该都能够读的出来
	 * 可是现在这个配置文件是applicationContext.xml
	 */
	@Override
	public Object getBean(String id) {
		return container.get(id);
	}	

}
package com.learn.spring;

import java.io.File;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Sample2 {
	
    public static void main(String[] args) throws Exception {
        SAXReader reader = new SAXReader();
        /**
         * 我建议所有的配置文件都放在classpath里
         */
        File file = new File("C:\\Users\\Leon.sun\\eclipse-workspace\\Aztech_Test\\src\\com\\learn\\spring\\applicationContext.xml");
        /**
         * 它是把整个文档当成Document对象
         */
        Document document = reader.read(file);
        /**
         * root是拿到document的根对象
         */
        Element root = document.getRootElement();
        /**
         * 拿到它的节点,我是可以拿到他的element的,
         */
        List<Element> childElements = root.selectNodes("bean");  
        // System.out.println(childElements);
        System.out.println(childElements.size());
        for (Element child : childElements) {
            //已知属性名情况下
            System.out.println("id: " + child.attributeValue("id"));              
            //已知子元素名的情况下
            System.out.println("class" + child.attributeValue("class"));
            //这行是为了格式化美观而存在
            System.out.println();
        }
    }

}
package com.learn.spring;

/**
 * 这就是一个最简单的Spring的模拟
 * Spring他定义了一个BeanFactory没错
 * BeanFactory他有一些自己的实现,常见的实现有ClassPathXmlApplicationContext
 * 里面找XML的配置,它会把bean的信息全部装在map里,当你要的时候它会从map里给你拿出来,仅此而已
 * 当然这是Spring最入门的内容,Spring还有一个更难的内容,叫AOP,那个有点难
 * 
 * 我们通过司机一辆车讲了单例和多例,
 * 任意的定制交通工具的类型和生产过程讲了普通工厂方法
 * 我们讲了怎么进行系列产品的替换,讲了抽象工厂
 * 同时我们引出来Spring的bean的工厂
 * bean工厂有自己的好处,第一个是基于接口的类型任意定制,类型你任意写,没有那么多Factory,Factory只有一个
 * 就是bean工厂,同时我可以进行生产过程的定制,当然你要生产系列产生也没有问题,只要你换成系列产品的具体实现就行了
 * 关于一定生产过程的定制,这个等讲AOP的时候再说,自己取阅读观察者模式,把抽象工厂运用到坦克项目中去,
 * 产生坦克的子弹爆炸全都是圆的,如果你有一个方的工厂,那么产生坦克的子弹爆炸全都是方的,看他能不能应用到进去,
 * 
 * @author Leon.Sun
 *
 */
public class Test {
	
	public static void main(String[] args) throws Exception {
		
		BeanFactory factory = new ClassPathXmlApplicationContext("C:\\Users\\Leon.sun\\eclipse-workspace\\Aztech_Test\\src\\com\\learn\\spring\\applicationContext.xml");
		
		/**
		 * 我们把key等于v的对象拿出来
		 */
		Object o = factory.getBean("v");
		
		/**
		 * 拿出来之后转化为Moveable
		 */
		Moveable m = (Moveable)o;
		
		m.run();
		
	}

}

猜你喜欢

转载自blog.csdn.net/Leon_Jinhai_Sun/article/details/89513542