一提到工厂,我们先来回忆前面学习过的工厂方法和抽象工厂模式:
工厂方法:针对产品维度,可以产生新的产品,也可以产生新的产品工厂,既可以扩展产品维度。但是如果我们想在普通工厂上生产产品系列,就会特别麻烦如果产生Apple你就得产生AppleFactory,如果产生Mushroom,就得产生MushroomFactory.这样就会照成工厂泛滥。
抽象工厂:针对产品系列,可以在谋一系列的产品上进行扩展。缺点是如果产生产品新种,改动就会很多。
Spring工厂:可以在产品系列方面既能扩展,又能确定产品品种。下面是Spring的实例:
1.首先定义一个接口两个类:
public class Car implements Moveable { public void run(){ System.out.println("O(∩_∩)O哈哈~,开着敞篷车回家咯~~~~~"); } }
public class Train implements Moveable { @Override public void run() { System.out.println("呜呜呜~~,只能挤火车 ~~~"); } }
public interface Moveable { void run(); }
2.添加引用Spring的Jar包 ,添加XML文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="v" class="com.tgbstd.spring.factory.Car"></bean> </beans>
public static void main(String[] args) throws Exception { BeanFactory f = new ClassPathXmlApplicationContext("applicationContext.xml"); Object o =f.getBean("v"); //传入id Moveable m =(Moveable)o; m.run(); } }
Spring模拟:定义一个BeanFactory,在这个里面有自己的实现,最常见的实现ClassPathXML ,从这里面读XML,把读到的信息都装在一个MAP里面,当你要的时候再拿出来。
A.定义BeanFactory接口和getBean方法
public interface BeanFactory { Object getBean(String id); }
public class ClassPathXmlApplicationContext implements BeanFactory { //把所有配置文件里的东西读出来保存在map里面 private Map<String,Object> container = new HashMap<String,Object>(); //定义构造函数 public ClassPathXmlApplicationContext(String fileName) throws Exception { SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(this.getClass().getClassLoader() .getResourceAsStream(fileName)); //拿到配置文件 Element root = doc.getRootElement(); List list = XPath.selectNodes(root, "/beans/bean"); // 循环遍历节点 for (int i = 0; i < list.size(); i++) { Element bean = (Element) list.get(i); String id = bean.getAttributeValue("id"); String clazz = bean.getAttributeValue("class"); Object o =Class.forName(clazz).newInstance(); container.put(id, o); //存放对象 //相关过程输出 System.out.println("id=" + id); System.out.println("通过id拿到具体的class信息:" +"class"); } } @Override //调用getBean将拿到的信息返回给客户 public Object getBean(String id) { return container.get(id); } }
public class Test { public static void main(String[] args) throws Exception { //父类引用指向子类对象,找到配置文件 BeanFactory f = new ClassPathXmlApplicationContext("com/tgbstd/spring/factory/applicationContext.xml"); //传入id Object o = f.getBean("v"); Moveable m =(Moveable)o; m.run(); } }
D.结果:
上面简单的介绍了Spring创建Bean工厂的原理。其实Bean主要是通过自己定义一个BeanFactory工厂的实现,通过构造函数传入初始值,读取XML配置文件信息。并且将读取到的id作为key值,读取到的对象作为Value值,存入到Map容器中。当客户端需要获取时,只要传入id,就能从容器中读取出来。
百度百科定义:Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架。而Bean工厂的概念是Spring作为IOC(面向接口或面向抽象类编程,将具体的东西写在配置文件里。当我们需求改变时,只需要去修改配置文件,例如,将Car修改为Train。我们得到的结果就是做火车回家的方式。)容器的基础。可想而知,理解Bean工厂的原理是非常有必要的。