技术这个东西真的需要沉淀,你想1天2天把一本书吃透是很难的,都是一点一点的知识点累积起来形成自己的知识体系。
在这个浮躁的时代,心急导致很多问题不能静下心来思考,解决不了问题就开始沮丧,开始对自己产生怀疑,最后选择放弃。
每个人成长进步的背后固然是要付出辛苦的汗水,但成长后的喜悦是不是也别有一番滋味呢。
spring这个框架用了很多年,记得2011年的时候就开始接触,期间做项目的时候就在网上copy配置文件,那时也不知道spring是干啥的,只知道看网上说IOC,AOP,
后来心血来潮的时候也看了下源码,了解web项目启动到加载配置文件最后实例化bean的过程。源码太多,绕来绕去人都晕,知识点也没有总结。
现在闲在家就好好把spring总结下。
开始前先想好思路,先按第一部分划分成3个 (容器基础,IOC,AOP) 其中 把本书的默认标签和自定义标签的解析和bean的加载归纳到IOC里面。
容器基础
先用XmlBeanFactory操作bean
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("application.xml")); MyTestBean bean = (MyTestBean) bf.getBean("myTestBean");
可以去XmlBeanFactory这个类去看看,他继承了DefaultListableBeanFactory这个类。
可以看下这个类,很简单有个XmlBeanDefinitionReader类去读配置文件
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); /** * Create a new XmlBeanFactory with the given resource, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } /** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @param parentBeanFactory parent bean factory * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); }}
其实可以用下面代码代替XmlBeanFactory,其实XmlBeanFactory构造器也就做了下面的事情
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();// 构造工厂 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);// 新增Xml阅读器 reader.loadBeanDefinitions(new ClassPathResource("application.xml"));// 规则注册入容
书上说了DefaultListableBeanFactory和XmlBeanDefinitionReader是spring中最核心的2个类,那下面就好好研究这2个类。
- DefaultListableBeanFactory
先画下这个类的继承关系(画的累啊加起来一起15个类,接口)
1.BeanFactory 定义获取bean的接口
2.ListableBeanFactory 定义了获取bean集合的接口
3.AutowireCapableBeanFactory 该接口定义了创建bean,属性自动注入
(可以使用这个接口集成其它框架,捆绑并填充并不由Spring管理生命周期并已存在的实例,
因为spring容器外的bean是没有被spring管理的,如果想要bean的属性自动注入,可以用这个接口)
4.BeanDefinitionRegistry 定义注册bean,移除bean。。接口
5.AbstractBeanFactory 实现获取bean
6.AbstractAutowireCapableBeanFactory 实现了创建bean
9.DefaultListableBeanFactory 实现了注册bean
- XmlBeanDefinitionReader
先画下这个类的关系图
DefaultDocumentLoader 负责把资源文件就是配置文件转换成Document
DefaultBeanDefinitionDocumentReader 负责读取Document并注册bean
上面看到了程序员注册bean的代码
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();// 构造工厂
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);// 新增Xml阅读器reader.loadBeanDefinitions(new ClassPathResource("application.xml"));// 规则注册入容先从 ClassPathResource入手
ClassPathResource从类名我们就知道这个是classpath路径下的资源,这个类也很简单,继承了其他类外,自己就封装了ClassLoader加载器
看源码这个加载器就是Thread.currentThread().getContextClassLoader();
打印为sun.misc.Launcher$AppClassLoader就是 系统加载器。
这里可以复习下JVM定义的3个加载器,
1.启动(Bootstrap)类加载器 它负责将 <Java_Runtime_Home>/lib 下面的类库加载到内存中
2.标准扩展(Extension)类加载器sun.misc.Launcher$ExtClassLoader 它负责将 < Java_Runtime_Home >/lib/ext下面的类库加载到内存中
3.系统(System)类加载器 sun.misc.Launcher$AppClassLoader 它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中.
再看看XmlBeanDefinitionReader.loadBeanDefinitions 做了什么事情
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); }
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception { return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, getValidationModeForResource(resource), isNamespaceAware()); }
看黄色部分做了3件事
1.getValidationModeForResource获取对XML文件的验证模式
2.loadDocument加载XML把内容封装到Document类里面
3.registerBeanDefinitions 根据document注册bean