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();
}
}