spring源码阅读(一) Bean加载解析准备
作为一名java工程师,没有阅读过spring源码,总有一种要被鄙视的感觉,另外也想通过阅读源码提升自己的能力,没有比spring更合适的了。
那么开始这个源码阅读的系列吧,参考书籍《Spring源码深度解析》
2019-06-26 Spring加载的解析
首先我们构建的spring例子工程
我们主要代码:
public static void main(String args[]){ BeanFactory context = new XmlBeanFactory(new ClassPathResource("ioc.xml")); Zaojiaoshu zaojiaoshu = (Zaojiaoshu) context.getBean("zaojiaoshu"); System.out.println(zaojiaoshu.getAge() + "岁" + zaojiaoshu.getHigh() + "米"); }
核心是这个XmlBeanFactory我们来看下它的代码,打开发现比较简单:
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader; public XmlBeanFactory(Resource resource) throws BeansException { this(resource, (BeanFactory)null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader = new XmlBeanDefinitionReader(this); this.reader.loadBeanDefinitions(resource); } }
那么,构造函数里又调用了另一个构造函数。才是真正的核心。那么BeanFactory本身的结构是什么样的?通过代码可以看到主要是继承了DefaultListableBeanFactory。来看:
牵扯的内容很多,有些现在不能一一说明用意,只能粗略的了解下先。
比如:
BeanDefinitionRegistry 提供对BeanDefinition的各种增删改查操作。后续了解清楚各个组建的作用后,再来添加详细。To do ...
返回之前Main方法中继续。创建完XmlBeanFactoryBean对象时,主要参数是Resource对象。分析下:
Resource接口是spring提供的统一的资源封装接口,用来封装各种底层资源。
public interface Resource extends InputStreamSource { boolean exists(); boolean isReadable(); boolean isOpen(); URL getURL() throws IOException; URI getURI() throws IOException; File getFile() throws IOException; long contentLength() throws IOException; long lastModified() throws IOException; Resource createRelative(String var1) throws IOException; String getFilename(); String getDescription(); }
InputStream就更简单了。
public interface InputStreamSource { InputStream getInputStream() throws IOException; }
获取InputStream的返回对象。
可以看到Resource接口里,提供了文件是否存在/是否可读/是否打开的方法,来判断资源状态。另外还提供了不同资源向URL/URI/File类型资源的转换方法。
看下Resource的类图结构:
为了便于显示,删除了部分AbstractResource的实现类,主要用来看下类结构图。
相关实现,就比较简单了,查看源码就能看到,比如ClassPathResource
public InputStream getInputStream() throws IOException { InputStream is; if (this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); } else if (this.classLoader != null) { is = this.classLoader.getResourceAsStream(this.path); } else { is = ClassLoader.getSystemResourceAsStream(this.path); } if (is == null) { throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist"); } else { return is; } }
借助ClassLoader或者class提供了底层方法进行调用。其他的具体查看下代码即可。核心就是能够获取资源的InputStream流。
讲了Resource,那继续之前方法中的代码:加载Bean。
Todo 把当时写在word上的内容,挪过来。