一、封装配置文件
spring的配置文件读取是通过ClassPathResource进行封装的。ClassPathResource类是简介实现了接口Resource,而Resource的作用是为了封装所有spring内部使用到的底层资源:File,URL,ClassPath等。Resource接口的定义如下:
spring的配置文件读取是通过ClassPathResource进行封装的。ClassPathResource类是简介实现了接口Resource,而Resource的作用是为了封装所有spring内部使用到的底层资源:File,URL,ClassPath等。Resource接口的定义如下:
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
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 relativePath) throws IOException;
String getFilename();
String getDescription();
}
不同来源的资源文件都有相对应的Resource实现:文件(FileSystemResource)、ClassPath资源(ClassPathResource)等,通过getInputStream()获得inputStream之后就可以正常开发了。
二、加载bean
加载单例bean时首先尝试从singleObjects中加载,如果获取不到再从earlySingletonObjects里面获取,如果还获取不到,再尝试从singletonFactories中获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingletonObjects里面去,并且从singletonFactories里面remove掉这个ObjectFactory。这里涉及到的用于存储不同bean的map:
- singletonObjects:用于保存BeanName和创建bean实例之间的关系。
- singletonFactories:用于保存BeanName和创建bean的工厂之间的关系。
- earlySingletonObjects:也是用于保存BeanName和创建bean实例之间的关系。与singletonObjects不同的是,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用
- registerSingletons:用来保存当前所有已经注册的bean。
如果没有获取到单例,则开始准备创建单例,其流程如下: