传统Java SE程序设计,直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象,现在是由容器来创建及注入依赖对象,依赖对象的获取被反转了。
ApplicationContext接口是BeanFactory的子接口,与BeanFactory一样,可以加载配置文件中定义的bean并进行管理。
ApplicationContext接口主要的5个作用
将配置文件中的bean信息解析成对应的BeanDefinition对象。
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
xml文件解析使用BeanDefinitionReader实现类XmlBeanDefinitionReader。
BeanFactory是所有Bean容器的根接口,定义了spring容器基本方法。如使用 getBean(beanName,Class) 获取对象等。
解析配置文件类FileSystemXmlApplicationContext
/**
* 下面这 4 个构造方法都调用了第 5 个构造方法
* @param configLocation
* @throws BeansException
*/
// configLocation 包含了 BeanDefinition 所在的文件路径
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
// 可以定义多个 BeanDefinition 所在的文件路径
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
// 在定义多个 BeanDefinition 所在的文件路径 的同时,还能指定自己的双亲 IoC 容器
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
/**
* 如果应用直接使用 FileSystemXmlApplicationContext 进行实例化,则都会进到这个构造方法中来
*/
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 动态地确定用哪个加载器去加载我们的配置文件
super(parent);
// 告诉读取器 配置文件放在哪里,该方法继承于爷类 AbstractRefreshableConfigApplicationContext
setConfigLocations(configLocations);
if (refresh) {
// 容器初始化
refresh();
}
}
/**
* 实例化一个 FileSystemResource 并返回,以便后续对资源的 IO 操作
* 本方法是在其父类 DefaultResourceLoader 的 getResource 方法中被调用的,
*/
@Override
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
其父类AbstractApplicationContext实现的refresh()方法,是IoC容器初始化核心方法
/**
* 容器初始化的过程:BeanDefinition 的 Resource 定位、BeanDefinition 的载入、BeanDefinition 的注册。
* BeanDefinition 的载入和 bean 的依赖注入是两个独立的过程,依赖注入一般发生在 应用第一次通过
* getBean() 方法从容器获取 bean 时。
*
* 另外需要注意的是,IoC 容器有一个预实例化的配置(即,将 AbstractBeanDefinition 中的 lazyInit 属性
* 设为 true),使用户可以对容器的初始化过程做一个微小的调控,lazyInit 设为 false 的 bean
* 将在容器初始化时进行依赖注入,而不会等到 getBean() 方法调用时才进行
*/
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新,获取容器的当前时间,同时给容器设置同步标识
prepareRefresh();
// 告诉子类启动 refreshBeanFactory() 方法,BeanDefinition 资源文件的载入从子类的 refreshBeanFactory() 方法启动开始
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// 为容器的某些子类指定特殊的 BeanPost 事件处理器
postProcessBeanFactory(beanFactory);
// 调用所有注册的 BeanFactoryPostProcessor 的 Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 为 BeanFactory 注册 BeanPost 事件处理器.
// BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
// 初始化信息源,和国际化相关.
initMessageSource();
// 初始化容器事件传播器
initApplicationEventMulticaster();
// 调用子类的某些特殊 Bean 初始化方法
onRefresh();
// 为事件传播器注册事件监听器.
registerListeners();
// 初始化 Bean,并对 lazy-init 属性进行处理
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
// 销毁以创建的单态 Bean
destroyBeans();
// 取消 refresh 操作,重置容器的同步标识.
cancelRefresh(ex);
throw ex;
}
}
}
obtainFreshBeanFactory()方法告诉子类去刷新内部的beanFactory
/**
* Tell the subclass to refresh the internal bean factory.
* 告诉子类去刷新内部的 beanFactory
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 自己定义了抽象的 refreshBeanFactory() 方法,具体实现交给了自己的子类
refreshBeanFactory();
// getBeanFactory() 也是一个抽象方法,交由子类实现
// 看到这里是不是很容易想起 “模板方法模式”,父类在模板方法中定义好流程,定义好抽象方法
// 具体实现交由子类完成
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractRefreshableApplicationContext中对refreshBeanFactory()方法的实现。FileSystemXmlApplicationContext 从上层体系的各抽象类中继承了大量的方法实现,抽象类中抽取大量公共行为进行具体实现,留下 abstract 的个性化方法交给具体的子类实现,这是一个很好的 OOP 编程设计,我们在自己编码时也可以尝试这样设计自己的类图
/**
* 在这里完成了容器的初始化,并赋值给自己私有的 beanFactory 属性,为下一步调用做准备
* 从父类 AbstractApplicationContext 继承的抽象方法,自己做了实现
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果已经建立了 IoC 容器,则销毁并关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建 IoC 容器,DefaultListableBeanFactory 类实现了 ConfigurableListableBeanFactory 接口
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 对 IoC 容器进行定制化,如设置启动参数,开启注解的自动装配等
customizeBeanFactory(beanFactory);
// 载入 BeanDefinition,在当前类中只定义了抽象的 loadBeanDefinitions() 方法,具体实现 调用子类容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 给自己的属性赋值
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
AbstractXmlApplicationContext 中对 loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 的实现。
/*
* 实现了基类 AbstractRefreshableApplicationContext 的抽象方法
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口,在初始化 XmlBeanDefinitionReader 时
// 将 BeanDefinition 注册器注入该 BeanDefinition 读取器
// 创建用于从 Xml 中读取 BeanDefinition 的读取器,并通过回调设置到 IoC 容器中去,容器使用该读取器读取 BeanDefinition 资源
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 为 beanDefinition 读取器设置 资源加载器,由于本类的基类 AbstractApplicationContext
// 继承了 DefaultResourceLoader,因此,本容器自身也是一个资源加载器
beanDefinitionReader.setResourceLoader(this);
// 设置 SAX 解析器,SAX(simple API for XML)是另一种 XML 解析方法。相比于 DOM,SAX 速度更快,占用内存更小。
// 它逐行扫描文档,一边扫描一边解析。相比于先将整个 XML 文件扫描近内存,再进行解析的 DOM,SAX 可以在解析文档的
// 任意时刻停止解析,但操作也比 DOM 复杂。
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 初始化 beanDefinition 读取器,该方法同时启用了 Xml 的校验机制
initBeanDefinitionReader(beanDefinitionReader);
// Bean 读取器真正实现加载的方法
loadBeanDefinitions(beanDefinitionReader);
}
继续看 AbstractXmlApplicationContext 中 loadBeanDefinitions() 的重载方法。
/**
* 用传进来的 XmlBeanDefinitionReader 读取器加载 Xml 文件中的 BeanDefinition
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
/**
* ClassPathXmlApplicationContext 与 FileSystemXmlApplicationContext 在这里的调用出现分歧,
* 各自按不同的方式加载解析 Resource 资源,最后在具体的解析和 BeanDefinition 定位上又会殊途同归。
*/
// 获取存放了 BeanDefinition 的所有 Resource,FileSystemXmlApplicationContext 类未对
// getConfigResources() 进行重写,所以调用父类的,return null。
// 而 ClassPathXmlApplicationContext 对该方法进行了重写,返回设置的值
Resource[] configResources = getConfigResources();
if (configResources != null) {
// XmlBeanDefinitionReader 调用其父类 AbstractBeanDefinitionReader 的方法加载 BeanDefinition
reader.loadBeanDefinitions(configResources);
}
// 调用父类 AbstractRefreshableConfigApplicationContext 的实现,
// 优先返回 FileSystemXmlApplicationContext 构造方法中调用 setConfigLocations() 方法设置的资源
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// XmlBeanDefinitionReader 调用其父类 AbstractBeanDefinitionReader 的方法从配置位置加载 BeanDefinition
reader.loadBeanDefinitions(configLocations);
}
}
AbstractBeanDefinitionReader 中对 loadBeanDefinitions 方法的各种重载及调用。
/**
* loadBeanDefinitions() 方法的重载方法之一,调用了另一个重载方法 loadBeanDefinitions(String)
*/
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
// 计数器,统计加载了多少个BeanDefinition
int counter = 0;
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
/**
* 重载方法之一,调用了下面的 loadBeanDefinitions(String, Set) 方法
*/
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
/**
* 获取在 IoC 容器初始化过程中设置的资源加载器
*/
public int loadBeanDefinitions(String location, Set actualResources) throws BeanDefinitionStoreException {
// 在实例化 XmlBeanDefinitionReader 后 IoC 容器将自己注入进该读取器作为 resourceLoader 属性
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
try {
// 将指定位置的 BeanDefinition 资源文件解析为 IoC 容器封装的资源
// 加载多个指定位置的 BeanDefinition 资源文件
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 委派调用其子类 XmlBeanDefinitionReader 的方法,实现加载功能
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* AbstractApplicationContext 继承了 DefaultResourceLoader,所以 AbstractApplicationContext
* 及其子类都会调用 DefaultResourceLoader 中的实现,将指定位置的资源文件解析为 Resource,
* 至此完成了对 BeanDefinition 的资源定位
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
Resource resource = resourceLoader.getResource(location);
// 从 resource 中加载 BeanDefinition,loadCount 为加载的 BeanDefinition 个数
// 该 loadBeanDefinitions() 方法来自其实现的 BeanDefinitionReader 接口,
// 且本类是一个抽象类,并未对该方法进行实现。而是交由子类进行实现,如果是用 xml 文件进行
// IoC 容器的初始化,则调用 XmlBeanDefinitionReader 中的实现
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
resourceLoader 的 getResource() 方法有多种实现,看清 FileSystemXmlApplicationContext 的继承体系就可以明确,其走的是 DefaultResourceLoader 中的实现。
/**
* 获取 Resource 的具体实现方法
*/
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
// 如果 location 是类路径的方式,返回 ClassPathResource 类型的文件资源对象
if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// 如果是 URL 方式,返回 UrlResource 类型的文件资源对象,
// 否则将抛出的异常进入 catch 代码块,返回另一种资源对象
URL url = new URL(location);
return new UrlResource(url);
}
catch (MalformedURLException ex) {
// 如果既不是 classpath 标识,又不是 URL 标识的 Resource 定位,则调用容器本身的
// getResourceByPath() 方法获取 Resource。根据实例化的子类对象,调用其子类对象中
// 重写的此方法,如 FileSystemXmlApplicationContext 子类中对此方法的重写
return getResourceByPath(location);
}
}
}
其中的 getResourceByPath(location) 方法的实现则是在 FileSystemXmlApplicationContext 中完成的。
/**
* 实例化一个 FileSystemResource 并返回,以便后续对资源的 IO 操作
* 本方法是在 DefaultResourceLoader 的 getResource() 方法中被调用的,
*/
@Override
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
FileSystemXmlApplicationContext 的 getResourceByPath() 方法返回了一个 FileSystemResource 对象,接下来 spring 就可以对这个对象进行相关的 I/O 操作,进行 BeanDefinition 的读取和载入了。
Spring IoC 容器 BeanDefinition 解析过程就是把用户在配置文件中配置的 bean,解析并封装成 IoC 容器可以装载的 BeanDefinition 对象,BeanDefinition 是 Spring 定义的基本数据结构,其中的属性与配置文件中 bean 的属性相对应.
AbstractRefreshableApplicationContext 的 refreshBeanFactory() 方法,这是一个模板方法,其中调用的 loadBeanDefinitions() 方法是一个抽象方法,交由子类实现。
/**
* 在这里完成了容器的初始化,并赋值给自己私有的 beanFactory 属性,为下一步调用做准备
* 从父类 AbstractApplicationContext 继承的抽象方法,自己做了实现
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果已经建立了 IoC 容器,则销毁并关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建 IoC 容器,DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 接口
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 对 IoC 容器进行定制化,如设置启动参数,开启注解的自动装配等
customizeBeanFactory(beanFactory);
// 载入 BeanDefinition,当前类中只定义了抽象的 loadBeanDefinitions() 方法,具体的实现调用子类容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 给自己的属性赋值
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
AbstractRefreshableApplicationContext 的子类 AbstractXmlApplicationContext 对 loadBeanDefinitions() 方法的实现
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口,所以在初始化 XmlBeanDefinitionReader 时
// 将该 beanFactory 传入 XmlBeanDefinitionReader 的构造方法中。
// 从名字也能看出来它的功能,这是一个用于从 .xml文件 中读取 BeanDefinition 的读取器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 为 beanDefinition 读取器设置 资源加载器,由于本类的基类 AbstractApplicationContext
// 继承了 DefaultResourceLoader,因此,本容器自身也是一个资源加载器
beanDefinitionReader.setResourceLoader(this);
// 为 beanDefinitionReader 设置用于解析的 SAX 实例解析器,SAX(simple API for XML)是另一种XML解析方法。
// 相比于DOM,SAX速度更快,占用内存更小。它逐行扫描文档,一边扫描一边解析。相比于先将整个XML文件扫描进内存,
// 再进行解析的DOM,SAX可以在解析文档的任意时刻停止解析,但操作也比DOM复杂。
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 初始化 beanDefinition 读取器,该方法同时启用了 XML 的校验机制
initBeanDefinitionReader(beanDefinitionReader);
// 用传进来的 XmlBeanDefinitionReader 读取器读取 .xml 文件中配置的 bean
loadBeanDefinitions(beanDefinitionReader);
}
loadBeanDefinitions(XmlBeanDefinitionReader reader)
/**
* 读取并解析 .xml 文件中配置的 bean,然后封装成 BeanDefinition 对象
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
/**
* ClassPathXmlApplicationContext 与 FileSystemXmlApplicationContext
* 在这里的调用出现分歧,各自按不同的方式加载解析 Resource 资源
* 最后在具体的解析和 BeanDefinition 定位上又会殊途同归
*/
// 获取存放了 BeanDefinition 的所有 Resource,FileSystemXmlApplicationContext 中未对
// getConfigResources() 进行重写,所以调用父类的,return null。
// 而 ClassPathXmlApplicationContext 对该方法进行了重写,返回设置的值
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 这里调用的是其父类 AbstractBeanDefinitionReader 中的方法,解析加载 BeanDefinition对象
reader.loadBeanDefinitions(configResources);
}
// 调用其父类 AbstractRefreshableConfigApplicationContext 中的实现,优先返回
// FileSystemXmlApplicationContext 构造方法中调用 setConfigLocations() 方法设置的资源路径
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 这里调用其父类 AbstractBeanDefinitionReader 的方法从配置位置加载 BeanDefinition
reader.loadBeanDefinitions(configLocations);
}
}
AbstractBeanDefinitionReader 对 loadBeanDefinitions() 方法的三重重载
/**
* loadBeanDefinitions() 方法的重载方法之一,调用了另一个重载方法 loadBeanDefinitions(String location)
*/
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
// 计数器,统计加载了多少个配置文件
int counter = 0;
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
/**
* 重载方法之一,调用了下面的 loadBeanDefinitions(String location, Set actualResources) 方法
*/
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
/**
* 获取在 IoC 容器初始化过程中设置的资源加载器
*/
public int loadBeanDefinitions(String location, Set actualResources) throws BeanDefinitionStoreException {
// 在实例化 XmlBeanDefinitionReader 时 曾将 IoC 容器注入该对象,作为 resourceLoader 属性
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
try {
// 将指定位置的 bean 配置文件解析为 BeanDefinition 对象
// 加载多个指定位置的 BeanDefinition 资源
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 调用其子类 XmlBeanDefinitionReader 的方法,实现加载功能
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* AbstractApplicationContext 继承了 DefaultResourceLoader,所以 AbstractApplicationContext
* 及其子类都可以调用 DefaultResourceLoader 中的方法,将指定位置的资源文件解析为 Resource,
* 至此完成了对 BeanDefinition 的资源定位
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
Resource resource = resourceLoader.getResource(location);
// 从 resource 中加载 BeanDefinition,loadCount 为加载的 BeanDefinition 个数
// 该 loadBeanDefinitions() 方法来自其 implements 的 BeanDefinitionReader 接口,
// 且本类是一个抽象类,并未对该方法进行实现。而是交由子类进行实现,如果是用 xml 文件进行
// IoC 容器初始化的,则调用 XmlBeanDefinitionReader 中的实现
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
XmlBeanDefinitionReader 读取器中的方法执行流,按代码的先后顺序。
/**
* XmlBeanDefinitionReader 加载资源的入口方法
*/
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 调用本类的重载方法,通过 new EncodedResource(resource) 获得的 EncodedResource 对象
// 能够将资源与读取资源所需的编码组合在一起
return loadBeanDefinitions(new EncodedResource(resource));
}
/**
* 通过 encodedResource 进行资源解析,encodedResource 对象持有 resource 对象和 encoding 编码格式
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 从 resource 中获取输入流,对 resource 中的内容进行读取
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 实例化一个"XML 实体的单个输入源",将 inputStream 作为自己的属性
InputSource inputSource = new InputSource(inputStream);
// 如果 encodedResource 中的 encoding 属性不为空,就为 inputSource 设置读取 XML 的编码格式
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 这里是具体的读取过程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
// 关闭 IO 流
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
/**
* 从指定 XML 文件中解析 bean,封装成 BeanDefinition 对象的具体实现
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
// 通过 documentLoader 获取 XML 文件的 Document 对象
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
// 启动对 BeanDefinition 的详细解析过程,该解析过程会用到 Spring 的 Bean 配置规则
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
/**
* 按照 Spring 对配置文件中 bean 元素的语义定义,将 bean 元素 解析成 BeanDefinition 对象
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 得到 BeanDefinitionDocumentReader,将 xml 中配置的 bean 解析成 BeanDefinition 对象
// BeanDefinitionDocumentReader 只是个接口,这里实际上是一个 DefaultBeanDefinitionDocumentReader 对象
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
// 获得容器中注册的 bean 数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 解析过程入口
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 统计解析的 Bean 数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
文档解析器 DefaultBeanDefinitionDocumentReader 对配置文件中元素的解析。
// 根据 Spring 对 Bean 的定义规则进行解析
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
// 获得 XML 描述符
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
// 获得 Document 的根元素
Element root = doc.getDocumentElement();
// 解析的具体实现
doRegisterBeanDefinitions(root);
}
/**
* 依次注册 BeanDefinition,使用给定的根元素
*/
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
}
// 具体的解析过程由 BeanDefinitionParserDelegate 实现,
// BeanDefinitionParserDelegate中定义了用于解析 bean 的各种属性及方法
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(this.readerContext, root, parent);
// 前置解析处理,可以在解析 bean 之前进行自定义的解析,增强解析的可扩展性
preProcessXml(root);
// 从 Document 的根元素开始进行 Bean 定义的 Document 对象
parseBeanDefinitions(root, this.delegate);
// 后置解析处理,可以在解析 bean 之后进行自定义的解析,增加解析的可扩展性
postProcessXml(root);
this.delegate = parent;
}
/**
* 根据 Spring 的 bean解析规则,从 Document 的根元素开始进行解析
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 根节点 root 是否使用了 Spring 默认的 XML 命名空间
if (delegate.isDefaultNamespace(root)) {
// 获取根元素的所有子节点
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
// 如果 ele 定义的 Document 的元素节点使用的是 Spring 默认的 XML 命名空间
if (delegate.isDefaultNamespace(ele)) {
// 使用 Spring 的 bean解析规则 解析元素节点
parseDefaultElement(ele, delegate);
}
else {
// 若没有使用 Spring 默认的 XML 命名空间,则使用用户自定义的解析规则解析元素节点
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 若 Document 的根节点没有使用 Spring 默认的命名空间,则使用用户自定义的解析规则
// 解析 Document 根节点
delegate.parseCustomElement(root);
}
}
/**
* 使用 Spring 的 bean解析规则 解析 Spring元素节点
*/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析 元素
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// 解析 元素
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 若元素节点既不是 也不是 ,即普通的 元素,
// 则按照 Spring 的 bean解析规则 解析元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 如果被解析的元素是 beans,则递归调用 doRegisterBeanDefinitions(Element root) 方法进行解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
doRegisterBeanDefinitions(ele);
}
}
/**
* 解析 元素
*/
protected void importBeanDefinitionResource(Element ele) {
// 获取给定的导入元素的 location 属性
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
// 如果导入元素的 location 属性值为空,则没有导入任何资源,直接返回
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// 使用系统变量值解析 location 属性值
location = environment.resolveRequiredPlaceholders(location);
Set actualResources = new LinkedHashSet(4);
// 标识给定的 元素的 location 是否是绝对路径
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
}
if (absoluteLocation) {
try {
// 使用资源读取器加载给定路径的 bean
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {
// 给定的 元素的 location 是相对路径
try {
int importCount;
// 将给定 元素的 location 封装为相对路径资源
Resource relativeResource = getReaderContext().getResource().createRelative(location);
// 封装的相对路径资源存在
if (relativeResource.exists()) {
// 使用资源读取器加载 bean
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
// 封装的相对路径资源不存在
else {
// 获取 Spring IOC 容器资源读取器的基本路径
String baseLocation = getReaderContext().getResource().getURL().toString();
// 根据 Spring IoC 容器资源读取器的基本路径加载给定导入路径的资源
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
// 在解析完 元素之后,发送容器导入其他资源处理完成事件
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
/**
* 解析 元素
*/
protected void processAliasRegistration(Element ele) {
// 获取 元素中的 name 属性值
String name = ele.getAttribute(NAME_ATTRIBUTE);
// 获取 元素中的 alias 属性值
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
boolean valid = true;
// 若 元素的 name 属性值为空
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
// 若 元素的 alias 属性值为空
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
// 向容器的资源读取器 注册别名
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias +
"' for bean with name '" + name + "'", ele, ex);
}
// 在解析完 元素之后,向容器发送别名处理完成事件
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
/**
* 解析 bean 元素
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder 是对 BeanDefinition 的进一步封装,持有一个 BeanDefinition 对象 及其对应
// 的 beanName、aliases别名。对 元素的解析由 BeanDefinitionParserDelegate 实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 对 bdHolder 进行包装处理
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* 向 Spring IoC 容器注册解析完成的 BeanDefinition对象,这是 BeanDefinition 向 IoC 容器注册的入口
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 在完成向 Spring IOC 容器注册 BeanDefinition对象 之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinitionParserDelegate 中对 bean 元素的详细解析过程。
/**
* 解析 元素的入口
*/
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
/**
* 解析 元素,这个方法中主要处理 元素的 id、name 和 alias 属性
*/
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 获取 元素中的 id 属性值
String id = ele.getAttribute(ID_ATTRIBUTE);
// 获取 元素中的 name 属性值
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// 获取 元素中的 alias 属性值
List aliases = new ArrayList();
// 将 元素中的所有 name 属性值存放到别名中
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
// 如果 元素中没有配置 id 属性,则将 别名alias 中的第一个值赋值给 beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
// 检查 元素所配置的 id 或者 name 的唯一性
// 元素中是否包含子 元素
if (containingBean == null) {
// 检查 元素所配置的 id、name 或者 别名alias 是否重复
checkNameUniqueness(beanName, aliases, ele);
}
// 将 元素解析成 BeanDefinition对象
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
// 如果 元素中没有配置 id、name 或者 alias,且没有包含子元素
if (containingBean != null) {
// 为解析的 BeanDefinition 生成一个唯一的 beanName
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// 在别名集合 aliases 中添加 bean 的类名
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
// 当解析出错时,返回 null
return null;
}
/**
* 详细对 元素中的其他属性进行解析,上面的方法中已经对 bean 的 id、name 及 alias 属性进行了处理
*/
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
// 记录解析的
this.parseState.push(new BeanEntry(beanName));
// 这里只读取 元素中配置的 class 名字,然后载入到 BeanDefinition 中去
// 只是记录配置的 class 名字,不做实例化,对象的实例化在 getBean() 时发生
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
// 如果 元素中配置了 parent 属性,则获取 parent 属性的值
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 根据 元素配置的 class 名称和 parent 属性值创建 BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 对当前的 元素中配置的一些属性进行解析和设置,如配置的单例 (singleton) 属性等
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 为 BeanDefinition对象 注入 description属性值
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 解析 元素中的 meta 属性
parseMetaElements(ele, bd);
// 解析 元素中的 lookup-method 属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 元素中的 replaced-method 属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 元素的构造方法
parseConstructorArgElements(ele, bd);
// 解析 元素中的所有 元素
parsePropertyElements(ele, bd);
// 解析 元素的 qualifier 属性
parseQualifierElements(ele, bd);
// 为当前BeanDefinition对象 设置所需的资源和依赖对象
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
// 解析 元素出错时,返回 null
return null;
}
对 bean 的部分子元素进行解析的具体实现。
/**
* 解析 元素中所有的 子元素
*/
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
// 获取对应 元素中所有的 子元素,逐一解析
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 对 子元素进行详细解析
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
/**
* 详细解析 元素
*/
public void parsePropertyElement(Element ele, BeanDefinition bd) {
// 获取 元素的名字
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
// 如果一个 Bean 中已经有同名的 property 存在,则不进行解析,直接返回。
// 即如果在同一个 Bean 中配置同名的 property,则只有第一个起作用
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
// 解析获取 propertyName 对应的 value值,propertyName 及其 value值会被封装到
// PropertyValue 对象中,然后 set 到 BeanDefinition对象中去
Object val = parsePropertyValue(ele, bd, propertyName);
// 根据 property 的 名字propertyName 和 值val 创建 PropertyValue实例
PropertyValue pv = new PropertyValue(propertyName, val);
// 解析 元素
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
// 为当前的 BeanDefinition对象设置 propertyValues 属性值
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
/**
* 解析获取 元素的属性值 value
*/
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = (propertyName != null) ?
" element for property '" + propertyName + "'" :
" element";
// 获取 的所有子元素,只能是其中一种类型:ref,value,list 等
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 如果子元素不是 description 和 meta 属性
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!nodeNameEquals(node, META_ELEMENT)) {
// Child element is what we're looking for.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {// 当前 元素包含有子元素
subElement = (Element) node;
}
}
}
// 判断 property 的属性值是 ref 还是 value,不允许既是 ref 又是 value
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
// 如果属性是 ref,创建一个 ref 的数据对象 RuntimeBeanReference
// 这个对象封装了 ref 信息
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
// 一个指向运行时所依赖对象的引用
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
// 设置这个 ref 的数据对象是被当前的 property 对象所引用
ref.setSource(extractSource(ele));
return ref;
}
// 如果属性是 value,创建一个 value 的数据对象 TypedStringValue
// 这个对象封装了 value 信息
else if (hasValueAttribute) {
// 一个持有 String 类型值的对象
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
// 设置这个 value 数据对象是被当前的 property 对象所引用
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
// 如果当前 元素还有子元素
else if (subElement != null) {
// 解析 的子元素
return parsePropertySubElement(subElement, bd);
}
else {
// propery 属性中既不是 ref,也不是 value 属性,解析出错返回 null
error(elementName + " must specify a ref or value", ele);
return null;
}
}
/**
* 解析 元素中 ref,value 或者集合等子元素
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
return parsePropertySubElement(ele, bd, null);
}
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
// 如果 没有使用 Spring 默认的命名空间,则使用用户自定义的规则解析
// 内嵌元素
if (!isDefaultNamespace(ele)) {
return parseNestedCustomElement(ele, bd);
}
// 如果子元素是 bean,则使用解析 元素的方法解析
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
}
// 如果子元素是 ref,ref 中只能有以下 3 个属性:bean、local、parent
else if (nodeNameEquals(ele, REF_ELEMENT)) {
// 获取 元素中的 bean 属性值,引用其他解析的 Bean 的名称
// 可以不再同一个 Spring 配置文件中,具体请参考 Spring 对 ref 的配置规则
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
// 获取 元素中的 local 属性值,引用同一个 Xml 文件中配置
// 的 Bean 的 id,local 和 ref 不同,local 只能引用同一个配置文件中的 Bean
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
if (!StringUtils.hasLength(refName)) {
// 获取 元素中 parent 属性值,引用父级容器中的 Bean
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean', 'local' or 'parent' is required for element", ele);
return null;
}
}
}
// 没有配置 ref 的目标属性值
if (!StringUtils.hasText(refName)) {
error(" element contains empty target attribute", ele);
return null;
}
// 创建 ref 类型数据,指向被引用的对象
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
// 设置引用类型值是被当前子元素所引用
ref.setSource(extractSource(ele));
return ref;
}
// 如果子元素是 ,使用解析 ref 元素的方法解析
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
return parseIdRefElement(ele);
}
// 如果子元素是 ,使用解析 value 元素的方法解析
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
//如果子元素是 null,为 设置一个封装 null 值的字符串数据
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
// 如果子元素是 ,使用解析 array 集合子元素的方法解析
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
// 如果子元素是 ,使用解析 list 集合子元素的方法解析
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
// 如果子元素是 ,使用解析 set 集合子元素的方法解析
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
// 如果子元素是
配置文件中定义的 bean 就被解析成了 IoC 容器能够装载和使用的 BeanDefinition 对象,这种数据结构可以让 IoC 容器执行索引、查询等操作。然后就可以将得到的 BeanDefinition 对象 注册到 IoC 容器中。
将前面解析出来的 BeanDefinition 对象 注册进 IoC 容器,其实就是存入一个 ConcurrentHashMap
看一下前面在 DefaultBeanDefinitionDocumentReader 中实现的 processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) 方法。
/**
* 将 .xml 文件中的元素解析成 BeanDefinition对象,并注册到 IoC容器 中
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder 是对 BeanDefinition 的进一步封装,它持有一个 BeanDefinition 对象 及其对应
// 的 beanName、aliases别名。
// 对 Document 对象中 元素的解析由 BeanDefinitionParserDelegate 实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 对 bdHolder 进行包装处理
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* 向 IoC 容器注册解析完成的 BeanDefinition对象,这是 BeanDefinition 向 IoC 容器注册的入口
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 在完成向 IOC容器 注册 BeanDefinition对象 之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinitionReaderUtils 的 registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) 方法
/**
* 将解析到的 BeanDefinition对象 注册到 IoC容器
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 获取解析的 元素 的名称 beanName
String beanName = definitionHolder.getBeanName();
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* 开始向 IoC容器 注册 BeanDefinition对象
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果解析的 元素 有别名alias,向容器中注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}
BeanDefinitionRegistry 中的 registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 方法在 DefaultListableBeanFactory 实现类中的具体实现。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** 按注册顺序排列的 beanDefinition名称列表(即 beanName) */
private final List beanDefinitionNames = new ArrayList();
/** IoC容器 的实际体现,key --> beanName,value --> BeanDefinition对象 */
private final Map beanDefinitionMap = new ConcurrentHashMap(64);
/**
* 向 IoC容器 注册解析的 beanName 和 BeanDefinition对象
*/
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 校验解析的 BeanDefiniton对象
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 注册的过程中需要线程同步,以保证数据的一致性
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 检查是否有同名(beanName)的 BeanDefinition 存在于 IoC容器 中,如果已经存在,且不允许覆盖
// 已注册的 BeanDefinition,则抛出注册异常,allowBeanDefinitionOverriding 默认为 true
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
// 如果允许覆盖同名的 bean,后注册的会覆盖先注册的
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
// 若该 beanName 在 IoC容器 中尚未注册,将其注册到 IoC容器中,
else {
// 将 beanName 注册到 beanDefinitionNames列表
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
// beanDefinitionMap 是 IoC容器 的最主要体现,他是一个 ConcurrentHashMap,
// 直接存储了 bean的唯一标识 beanName,及其对应的 BeanDefinition对象
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 重置所有已经注册过的 BeanDefinition 的缓存
resetBeanDefinition(beanName);
}
}
前面我们主要分析了 FileSystemXmlApplicationContext 这个具体的 IoC 容器实现类 的初始化源码,在 IoC 容器 中建立了 beanName 到 BeanDefinition 的数据映射,通过一个 ConcurrentHashMap。
Spring 是如何将 IoC 容器中存在依赖关系的 bean 根据配置联系在一起的。Spring 中触发 IoC 容器“依赖注入” 的方式有两种,一个是应用程序通过 getBean()方法 向容器索要 bean 实例 时触发依赖注入;另一个是提前给 bean 配置了 lazy-init 属性为 false,Spring 在 IoC 容器 初始化会自动调用此 bean 的 getBean() 方法,提前完成依赖注入。总的来说,想提高运行时获取 bean 的效率,可以考虑配置此属性。
首先看一下 AbstractBeanFactory 中的 getBean() 系列方法及 doGetBean() 具体实现。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
//---------------------------------------------------------------------
// BeanFactory 接口的实现,下列的 getBean() 方法不论是哪种重载,最后都会走
// doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) 的具体实现
//---------------------------------------------------------------------
// 获取 IoC容器 中指定名称的 bean
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 获取 IoC容器 中指定名称和类型的 bean
public T getBean(String name, Class requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
// 获取 IoC容器 中指定名称和参数的 bean
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
// 获取 IoC容器 中指定名称、类型和参数的 bean
public T getBean(String name, Class requiredType, Object... args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
// 真正实现向 IoC容器 获取 bean 的功能,也是触发 依赖注入(DI) 的地方
@SuppressWarnings("unchecked")
protected T doGetBean(final String name, final Class requiredType, final Object[] args,
boolean typeCheckOnly) throws BeansException {
// 根据用户给定的名称(也可能是别名alias) 获取 IoC容器 中与 BeanDefinition 唯一对应的 beanName
final String beanName = transformedBeanName(name);
Object bean;
// 根据 beanName 查看缓存中是否有已实例化的 单例bean,对于 单例bean,整个 IoC容器 只创建一次
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 获取给定 bean 的实例对象,主要是完成 FactoryBean 的相关处理
// 注意:BeanFactory 是一个 IoC容器,它保存了 bean 的基本配置信息。
// 而 FactoryBean 是 IoC容器 中一种特殊的 bean,它能够实例化 bean对象,注意两者之间的区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 如果应用程序要获取的 bean 还未创建
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 获取当前容器的父容器
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果当前容器中没有指定的 bean,且当前容器的父容器不为空
// 则从父容器中去找,如果父容器也没有,则沿着当前容器的继承体系一直向上查找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 根据用户传入的 name(有可能是别名alias),获取唯一标识的 beanName
String nameToLookup = originalBeanName(name);
if (args != null) {
// 委派父级容器根据指定名称和显式的参数查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 委派父容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 创建的 bean 是否需要进行类型验证,一般不需要
if (!typeCheckOnly) {
// 向容器标记指定的 bean 已经被创建
markBeanAsCreated(beanName);
}
try {
// 根据 beanName 获取对应的 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取当前 bean 所依赖bean 的 beanName,下面的 getBean(dependsOnBean) 方法会触发
// getBean() 的递归调用,直到取到一个不依赖任何其它 bean 的 bean 为止。
// 比如:beanA 依赖了 beanB,而 beanB 依赖了 beanC,那么在实例化 beanA 时会先实例化
// beanC,然后实例化 beanB 并将 beanC 注入进去,最后实例化 beanA 时将 beanB 注入
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
// 递归调用 getBean() 方法,从末级节点依次实例化 依赖的bean
getBean(dependsOnBean);
// 把 当前bean 直接依赖的bean 进行注册
//(也就是通过 setter 或构造方法将依赖的 bean 赋值给当前 bean 对应的属性)
registerDependentBean(dependsOnBean, beanName);
}
}
// 如果当前 bean 是单例的
if (mbd.isSingleton()) {
// 这里使用了一个匿名内部类,创建 bean实例对象
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
// 根据给定的 beanName 及 RootBeanDefinition对象,创建 bean 实例对象
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
// 获取给定 bean 的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建原型模式的 bean 实例对象
else if (mbd.isPrototype()) {
// 原型模式 (Prototype) 每次都会创建一个新的对象
Object prototypeInstance = null;
try {
// 回调 beforePrototypeCreation() 方法,默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
// 创建指定 bean 对象实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 回调 afterPrototypeCreation() 方法,默认的功能是告诉 IoC容器
// 指定 bean 的原型对象不再创建了
afterPrototypeCreation(beanName);
}
// 获取给定 bean 的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 要创建的 bean 既不是单例模式,也不是原型模式,则根据该 bean元素 在配置文件中
// 配置的生命周期范围,选择实例化 bean 的合适方法,这种在 Web 应用程序中
// 比较常用,如:request、session、application 等的生命周期
else {
// 获取此 bean 生命周期的范围
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
// bean 定义资源中没有配置生命周期范围,则该 bean 的配置不合法
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
// 这里又使用了一个 ObjectFactory 的匿名内部类,获取一个指定生命周期范围的实例
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
// 获取给定 bean 的实例对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 对要返回的 bean实例对象 进行非空验证和类型检查,如果没问题就返回这个已经完成 依赖注入的bean
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
}
getBean() 方法是依赖注入的起点,之后会调用 createBean(),根据之前解析生成的 BeanDefinition 对象 生成 bean 对象,下面看看 AbstractBeanFactory 的子类 AbstractAutowireCapableBeanFactory 中对 createBean() 的具体实现。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
* 创建指定的 bean 实例对象
*/
@Override
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
// 判断需要创建的 bean 是否可实例化,是否可以通过当前的类加载器加载
resolveBeanClass(mbd, beanName);
try {
// 校验和准备 bean 中的方法覆盖
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 如果 bean 配置了后置处理器 PostProcessor,则这里返回一个 proxy 代理对象
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 创建 bean 实例对象的具体实现
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
/**
* 创建 bean 实例对象的具体实现,Spring 中以 do 开头的都是方法的具体实现
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
BeanWrapper instanceWrapper = null;
// 如果这个 bean 是单例的,则从缓存中获取这个 beanName 对应的 BeanWrapper实例,并清除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/**
* !!!!!!!!!!!!!
* 创建实例对象
* !!!!!!!!!!!!!
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取实例化对象和其类型
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// 调用 PostProcessor 后置处理器
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// 向容器中缓存单例模式的 bean 对象,以防循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 这里是一个 ObjectFactory 的匿名内部类,为了防止循环引用,尽早持有对象的引用
addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// bean 对象的初始化,依赖注入在此触发
// 这个 exposedObject 在初始化完成之后,将返回作为依赖注入完成后的 bean
Object exposedObject = bean;
try {
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!
* 把生成的 bean对象 的依赖关系设置好,完成整个依赖注入过程
* !!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
// 获取指定名称的已注册的 单例bean对象
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 如果根据名称获取的已注册的 bean 和正在实例化的 bean 是同一个
if (exposedObject == bean) {
// 当前实例化的 bean 初始化完成
exposedObject = earlySingletonReference;
}
// 如果当前 bean 依赖其他 bean,并且当发生循环引用时不允许新创建实例对象
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
// 获取当前 bean 所依赖的其他 bean
for (String dependentBean : dependentBeans) {
// 对 依赖bean 进行类型检查
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
// 注册 成完依赖注入的bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 为应用返回所需要的实例对象
return exposedObject;
}
}
源码中可以看到 createBeanInstance() 和 populateBean() 这两个方法与依赖注入的实现非常密切,createBeanInstance() 方法中生成了 bean 所包含的 Java 对象,populateBean() 方法对这些生成的 bean 对象之间的依赖关系进行了处理。下面我们先看一下 createBeanInstance() 方法的实现。
/**
* 创建 bean 的实例对象
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 检查确认 bean 是可实例化的
Class> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 使用 RootBeanDefinition对象 中的 factoryMethodName 对 bean 进行实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 使用容器的自动装配方法进行实例化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 配置了自动装配属性,使用容器的自动装配实例化,即,根据参数类型匹配 bean 的构造方法
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认的无参构造方法进行实例化
return instantiateBean(beanName, mbd);
}
}
// 使用 bean 的构造方法进行实例化
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 使用容器的自动装配特性,调用匹配的构造方法实例化
return autowireConstructor(beanName, mbd, ctors, args);
}
return instantiateBean(beanName, mbd);
}
// 使用默认的无参构造方法实例化 bean对象
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
// 获取系统的安全管理接口,JDK 标准的安全管理 API
if (System.getSecurityManager() != null) {
// 这里使用了一个 PrivilegedAction 的匿名内部类,根据实例化策略创建实例对象
beanInstance = AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
/**
* !!!!!!!!!!!!!!
* 使用初始化策略实例化 bean 对象
* !!!!!!!!!!!!!!
*/
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
源码中调用了 SimpleInstantiationStrategy 实现类来生成 bean 对象,这个类是 Spring 用来生成 bean 对象 的默认类,它提供了两种策略来实例化 bean 对象,一种是利用 Java 的反射机制,另一种是直接使用 CGLIB。
public class SimpleInstantiationStrategy implements InstantiationStrategy {
// 使用初始化策略实例化 bean对象
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// 如果 配置的bean 中没有方法覆盖,则使用 Java 的反射机制实例化对象,否则使用 CGLIB
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
// 获取对象的构造方法对 bean 进行实例化
constructorToUse = (Constructor>) beanDefinition.resolvedConstructorOrFactoryMethod;
// 如果前面没有获取到构造方法,则通过反射获取
if (constructorToUse == null) {
// 使用 JDK 的反射机制,判断要实例化的 bean 是否是接口
final Class clazz = beanDefinition.getBeanClass();
// 如果 clazz 是一个接口,直接抛出异常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
// 这里使用了一个 PrivilegedExceptionAction 的匿名内部类,使用反射机制获取 bean 的构造方法
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Constructor run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 根据传入的 Constructor,在 BeanUtils 中调用该 Constructor 的
// newInstance(Object...) 方法,实例化指定对象
return BeanUtils.instantiateClass(constructorToUse);
}
else {
/**
* !!!!!!!!!!!!!!
* 使用 CGLIB 来实例化对象
* 调用了 CglibSubclassingInstantiationStrategy 中的实现
* !!!!!!!!!!!!!!
*/
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
}
在 SimpleInstantiationStrategy 的子类 CglibSubclassingInstantiationStrategy 中可以看到使用 CGLIB 进行实例化的源码实现。
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
/**
* 下面两个方法都通过实例化自己的私有静态内部类 CglibSubclassCreator,
* 然后调用该内部类对象的实例化方法 instantiate() 完成实例化
*/
protected Object instantiateWithMethodInjection(
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null);
}
@Override
protected Object instantiateWithMethodInjection(
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
Constructor ctor, Object[] args) {
return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args);
}
/**
* 为避免 3.2 之前的 Spring 版本中的外部 cglib 依赖而创建的内部类。
*/
private static class CglibSubclassCreator {
private static final Log logger = LogFactory.getLog(CglibSubclassCreator.class);
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
public CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}
// 使用 CGLIB 进行 bean对象 实例化
public Object instantiate(Constructor ctor, Object[] args) {
// 实例化 Enhancer对象,并为 Enhancer对象 设置父类,生成 Java 对象的参数,比如:基类、回调方法等
Enhancer enhancer = new Enhancer();
// 将 bean 本身作为其父类
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
enhancer.setCallbackFilter(new CallbackFilterImpl());
enhancer.setCallbacks(new Callback[] {
NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(),
new ReplaceOverrideMethodInterceptor()
});
// 使用 CGLIB 的 create() 方法生成实例对象
return (ctor == null) ? enhancer.create() : enhancer.create(ctor.getParameterTypes(), args);
}
}
}
至此,完成了 bean 对象 的实例化,然后就可以根据解析得到的 BeanDefinition 对象 完成对各个属性的赋值处理,也就是依赖注入。这个实现方法就是前面 AbstractAutowireCapableBeanFactory 类中的 populateBean() 方法。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
* 为属性赋值,完成依赖注入
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// 获取 RootBeanDefinition 中设置的 属性值PropertyValues,这些属性值来自对
// .xml 文件中 bean元素 的解析
PropertyValues pvs = mbd.getPropertyValues();
// 如果 BeanWrapper对象 为 null,而要注入的属性值不为空,则抛出下述异常
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// BeanWrapper对象 为 null,属性值也为空,不需要设置属性值,直接返回
return;
}
}
// 在设置属性之前调用 bean 的 PostProcessor 后置处理器
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
// 依赖注入开始,首先处理 autowire 自动装配的注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 对 autowire 自动装配的处理,根据 bean 名称自动装配注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据 bean 类型自动装配注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 检查容器是否持有用于处理单例模式 bean 关闭时的后置处理器
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// bean实例对象 没有依赖,即没有继承基类
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
// 从实例对象中提取属性描述符
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 使用 BeanPostProcessor 处理器处理属性值
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
// 为要设置的属性进行依赖检查
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
/**
* !!!!!!!!!!!
* 对属性进行依赖注入
* !!!!!!!!!!!
*/
applyPropertyValues(beanName, mbd, bw, pvs);
}
/**
* 解析并注入依赖属性的过程
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
// 封装属性值
MutablePropertyValues mpvs = null;
List original;
if (System.getSecurityManager()!= null) {
if (bw instanceof BeanWrapperImpl) {
// 设置安全上下文,JDK 安全机制
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
// 如果属性值已经转换
if (mpvs.isConverted()) {
try {
// 为实例化对象设置属性值
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
// 获取属性值对象的原始类型值
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
// 获取用户自定义的类型转换
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 创建一个 BeanDefinition 属性值解析器,将 BeanDefinition 中的属性值解析为 bean 实例对象的实际值
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// 为属性的解析值创建一个副本,最后将属性值注入到实例对象中
List deepCopy = new ArrayList(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
// 如果属性值已经转换,直接添加到 deepCopy 列表中
if (pv.isConverted()) {
deepCopy.add(pv);
}
// 如果属性值需要转换
else {
String propertyName = pv.getName();
// 原始的属性值,即转换之前的属性值
Object originalValue = pv.getValue();
/**
* !!!!!!!!!!!!!!!!!!!
* 解析属性值,对注入类型进行转换
* !!!!!!!!!!!!!!!!!!!
*/
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// 转换之后的属性值
Object convertedValue = resolvedValue;
// 属性值是否可以转换
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
// 使用用户自定义的类型转换器转换属性值
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// 存储转换后的属性值,避免每次属性注入时的转换工作
if (resolvedValue == originalValue) {
if (convertible) {
// 设置属性转换之后的值
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
// 如果:属性是可转换的,且属性原始值是字符串类型,且属性的原始类型值不是
// 动态生成的字符串,且属性的原始值不是集合或者数组类型
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
// 重新封装属性的值
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
// 标记属性值已经转换过
mpvs.setConverted();
}
// 进行属性依赖注入
try {
/**
* !!!!!!!!!!!!!!!!!!!!!
* 完成 bean 的属性值注入的入口
* 走 AbstractPropertyAccessor 中的实现方法
* !!!!!!!!!!!!!!!!!!!!!
*/
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
}
BeanDefinitionValueResolver 中解析属性值,对注入类型进行转换的具体实现。
class BeanDefinitionValueResolver {
/**
* 解析属性值,对注入类型进行转换
*/
public Object resolveValueIfNecessary(Object argName, Object value) {
// 对引用类型的属性进行解析,RuntimeBeanReference 是在对 BeanDefinition 进行解析时生成的数据对象
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
/**
* !!!!!!!!!!!!!!!!
* 解析引用类型的属性值
* !!!!!!!!!!!!!!!!
*/
return resolveReference(argName, ref);
}
// 对属性值是引用容器中另一个 bean 名称的解析
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(evaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
// 对 BeanDefinitionHolder 类型属性的解析,主要是 bean 中的内部类
else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd);
}
// 对集合数组类型的属性解析
else if (value instanceof ManagedArray) {
ManagedArray array = (ManagedArray) value;
// 获取数组的类型
Class> elementType = array.resolvedElementType;
if (elementType == null) {
// 获取数组元素的类型
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
// 使用反射机制创建指定类型的对象
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
// 没有获取到数组的类型,也没有获取到数组元素的类型
// 则直接设置数组的类型为 Object
else {
elementType = Object.class;
}
}
// 创建指定类型的数组
return resolveManagedArray(argName, (List>) value, elementType);
}
// 解析 list 类型的属性值
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(argName, (List>) value);
}
// 解析 set 类型的属性值
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
return resolveManagedSet(argName, (Set>) value);
}
// 解析 map 类型的属性值
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
return resolveManagedMap(argName, (Map, ?>) value);
}
// 解析 Properties 类型的属性值,Properties 其实就是 key 和 value 均为字符串的 map
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
// 创建一个拷贝,用于作为解析后的返回值
Properties copy = new Properties();
for (Map.Entry propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
copy.put(propKey, propValue);
}
return copy;
}
// 解析字符串类型的属性值
else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
// 获取属性的目标类型
Class> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
// 对目标类型的属性进行解析,递归调用
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
// 没有获取到属性的目标对象,则按 Object 类型返回
else {
return valueObject;
}
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else {
return evaluate(value);
}
}
/**
* 解析引用类型的属性值
*/
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
// 获取 所引用bean 的 beanName
String refName = ref.getBeanName();
refName = String.valueOf(evaluate(refName));
// 如果引用的对象在父容器中,则从父容器中获取指定的引用对象
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
// 从当前的容器中获取指定的引用 bean对象,如果指定的 bean 没有被实例化
// 则会递归触发引用 bean 的初始化和依赖注入
else {
Object bean = this.beanFactory.getBean(refName);
// 为 refName对应的bean 注入 它所依赖的bean
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
/**
* 解析 array 类型的属性
*/
private Object resolveManagedArray(Object argName, List> ml, Class> elementType) {
// 创建一个指定类型的数组,用于存放和返回解析后的数组
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
// 递归解析 array 的每一个元素,并将解析后的值设置到 resolved 数组中,索引为 i
Array.set(resolved, i,
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
/**
* 解析 list 类型的属性
*/
private List resolveManagedList(Object argName, List> ml) {
List resolved = new ArrayList(ml.size());
for (int i = 0; i < ml.size(); i++) {
// 递归解析 list 的每一个元素
resolved.add(
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
/**
* 解析 set 类型的属性
*/
private Set resolveManagedSet(Object argName, Set> ms) {
Set resolved = new LinkedHashSet(ms.size());
int i = 0;
// 递归解析 set 的每一个元素
for (Object m : ms) {
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));
i++;
}
return resolved;
}
/**
* 解析 map 类型的属性
*/
private Map resolveManagedMap(Object argName, Map, ?> mm) {
Map resolved = new LinkedHashMap(mm.size());
// 递归解析 map 中每一个元素的 key 和 value
for (Map.Entry entry : mm.entrySet()) {
Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
Object resolvedValue = resolveValueIfNecessary(
new KeyedArgName(argName, entry.getKey()), entry.getValue());
resolved.put(resolvedKey, resolvedValue);
}
return resolved;
}
}
至此,已经为依赖注入做好了准备,下面就该将 bean 对象 设置到它所依赖的另一个 bean 的属性中去。AbstractPropertyAccessor 和其子类 BeanWrapperImpl 完成了依赖注入的详细过程。先看一下 AbstractPropertyAccessor 中的实现。
public abstract class AbstractPropertyAccessor extends TypeConverterSupport implements ConfigurablePropertyAccessor {
/**
* setPropertyValues() 方法有多种重载,但最终都走的是
* setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)重载方法
*/
public void setPropertyValues(Map, ?> map) throws BeansException {
setPropertyValues(new MutablePropertyValues(map));
}
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws BeansException {
setPropertyValues(pvs, ignoreUnknown, false);
}
public void setPropertyValues(PropertyValues pvs) throws BeansException {
setPropertyValues(pvs, false, false);
}
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException {
List propertyAccessExceptions = null;
List propertyValues = (pvs instanceof MutablePropertyValues ?
((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
for (PropertyValue pv : propertyValues) {
try {
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* 该方法走 BeanWrapperImpl 中的实现,这是 bean属性值注入 具体实现的入口
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
setPropertyValue(pv);
}
catch (NotWritablePropertyException ex) {
if (!ignoreUnknown) {
throw ex;
}
}
catch (NullValueInNestedPathException ex) {
if (!ignoreInvalid) {
throw ex;
}
}
catch (PropertyAccessException ex) {
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new LinkedList();
}
propertyAccessExceptions.add(ex);
}
}
// 如果出现 PropertyAccessException 异常,则将这些异常积累起来放到一个集合中,然后一次性抛出!!!
// 这种抛异常的方式 在实际的开发中也时常使用,可以好好看一下,对比一下
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray =
propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
throw new PropertyBatchUpdateException(paeArray);
}
}
}
最后看一下 BeanWrapperImpl 中的实现。
public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWrapper {
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
// PropertyTokenHolder 是一个用于内部使用的内部类
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
if (tokens == null) {
String propertyName = pv.getName();
BeanWrapperImpl nestedBw;
try {
nestedBw = getBeanWrapperForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
if (nestedBw == this) {
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
/**
* !!!!!!!!!!!!!!!
* 进入 bean 属性值注入的具体实现
* !!!!!!!!!!!!!!!
*/
nestedBw.setPropertyValue(tokens, pv);
}
else {
setPropertyValue(tokens, pv);
}
}
/**
* !!!!!!!!!!!!!!!!
* 依赖注入(将某个bean所依赖的值 注入到这个bean中) 的具体实现
* !!!!!!!!!!!!!!!!
*/
@SuppressWarnings("unchecked")
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
// PropertyTokenHolder 是定义在 BeanWrapperImpl 中的内部类,主要保存属性的名称、路径、
// 以及集合的 size 等信息
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
// 对集合类型的属性注入,PropertyTokenHolder 的 keys 是用来保存集合类型属性的 size
if (tokens.keys != null) {
// 将属性信息从 tokens 拷贝到 getterTokens
PropertyTokenHolder getterTokens = new PropertyTokenHolder();
getterTokens.canonicalName = tokens.canonicalName;
getterTokens.actualName = tokens.actualName;
getterTokens.keys = new String[tokens.keys.length - 1];
System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);
Object propValue;
try {
// 通过反射机制,调用属性的 getter 方法获取属性值
propValue = getPropertyValue(getterTokens);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "'", ex);
}
// 获取集合类型属性的长度
String key = tokens.keys[tokens.keys.length - 1];
if (propValue == null) {
if (this.autoGrowNestedPaths) {
int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
propValue = setDefaultValue(getterTokens);
}
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
}
}
// 如果属性值是 Array 数组类型的,则注入 array 类型的属性值
if (propValue.getClass().isArray()) {
// 获取属性的描述符
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
// 获取数组的类型
Class requiredType = propValue.getClass().getComponentType();
// 获取数组的长度
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
// 获取数组以前初始化的值
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
// 将属性的值赋值给数组中的元素
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid array index in property path '" + propertyName + "'", ex);
}
}
// 如果属性值是 List 类型的,则注入 list 类型的属性值
else if (propValue instanceof List) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
// 获取 list 集合中元素的类型
Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
pd.getReadMethod(), tokens.keys.length);
List list = (List) propValue;
int index = Integer.parseInt(key);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
// 获取 list 解析后的属性值
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
// 获取 list 集合的 size
int size = list.size();
// 如果 list 的长度大于属性值的长度,则多余的元素赋值为 null
if (index >= size && index < this.autoGrowCollectionLimit) {
for (int i = size; i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
// 为 list 属性赋值
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid list index in property path '" + propertyName + "'", ex);
}
}
}
// 如果属性值是 Map 类型的,则注入 Map 类型的属性值
else if (propValue instanceof Map) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
// 获取 map 集合 key 的类型
Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(
pd.getReadMethod(), tokens.keys.length);
// 获取 map 集合 value 的类型
Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
pd.getReadMethod(), tokens.keys.length);
Map map = (Map) propValue;
TypeDescriptor typeDescriptor = (mapKeyType != null ?
TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class));
// 解析 map 类型属性 key 值
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor);
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
// 解析 map 类型属性 value 值
Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
mapValueType, TypeDescriptor.nested(property(pd), tokens.keys.length));
// 将解析后的 key 和 value 值赋值给 map 集合属性
map.put(convertedMapKey, convertedMapValue);
}
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");
}
}
// 对非集合类型的属性注入
else {
PropertyDescriptor pd = pv.resolvedDescriptor;
if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {
pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
// 如果无法获取到属性名或者属性没有提供 setter 赋值方法
if (pd == null || pd.getWriteMethod() == null) {
// 如果属性值是可选的,即不是必须的,则忽略该属性值
if (pv.isOptional()) {
logger.debug("Ignoring optional value for property '" + actualName +
"' - property not found on bean class [" + getRootClass().getName() + "]");
return;
}
// 如果属性值是必须的,则抛出无法给属性赋值,因为没提供 setter 方法的异常
else {
PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());
throw new NotWritablePropertyException(
getRootClass(), this.nestedPath + propertyName,
matches.buildErrorMessage(), matches.getPossibleMatches());
}
}
pv.getOriginalPropertyValue().resolvedDescriptor = pd;
}
Object oldValue = null;
try {
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
if (pv.isConverted()) {
valueToApply = pv.getConvertedValue();
}
else {
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
// 获取属性的 getter 方法
final Method readMethod = pd.getReadMethod();
// 如果属性的 getter 方法无法访问,则使用 Java 的反射机制强行访问 (暴力读取属性值)
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
!readMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
// 匿名内部类,根据权限修改属性的读取控制限制
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
}
else {
readMethod.setAccessible(true);
}
}
try {
// 属性没有提供 getter 方法时,调用潜在的读取属性值的方法,获取属性值
if (System.getSecurityManager() != null) {
oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
return readMethod.invoke(object);
}
}, acc);
}
else {
oldValue = readMethod.invoke(object);
}
}
catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" +
this.nestedPath + propertyName + "'", ex);
}
}
}
// 设置属性的注入值
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
// 根据 Java 的内省机制,获取属性的 setter方法
final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
pd.getWriteMethod());
// 如果属性的 setter方法 无法访问,则强行设置 setter方法 可访问 (暴力为属性赋值)
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
writeMethod.setAccessible(true);
return null;
}
});
}
else {
writeMethod.setAccessible(true);
}
}
final Object value = valueToApply;
// 如果使用了 Java 的安全机制,则需要权限验证
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
// 将属性值设置到属性上去
writeMethod.invoke(object, value);
return null;
}
}, acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
// 将属性值设置到属性上去
writeMethod.invoke(this.object, value);
}
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
}
else {
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
}
}
catch (Exception ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
}
}
至此,完成了对 bean 的各种属性的依赖注入,在 bean 的实例化和依赖注入的过程中,需要依据 BeanDefinition 中的信息来递归地完成依赖注入。另外,在此过程中存在许多递归调用,一个递归是在上下文体系中查找 当前 bean 依赖的 bean 和创建 当前 bean 依赖的 bean 的递归调用;另一个是在依赖注入时,通过递归调用容器的 getBean() 方法,得到当前 bean 的依赖 bean,同时也触发对依赖 bean 的创建和注入;在对 bean 的属性进行依赖注入时,解析的过程也是递归的。这样,根据依赖关系,从最末层的依赖 bean 开始,一层一层地完成 bean 的创建和注入,直到最后完成当前 bean 的创建。
lazy-init 触发的预实例化和依赖注入,发生在 IoC 容器完成对 BeanDefinition 的定位、载入、解析和注册之后。通过牺牲 IoC 容器初始化的性能,来有效提升应用第一次获取该 bean 的效率。 lazy-init 实现的入口方法在我们前面解读过的 AbstractApplicationContext 的 refresh() 中,它是 IoC 容器正式启动的标志。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
/**
* 容器初始化的过程:
* 1、根据指定规则扫描指定目录,获取所有 用于配置bean的配置文件;
* 2、根据 Spring定义的规则,解析配置文件中的各个元素,将其封装成 IoC容器 可以装载的 BeanDefinition对象;
* 3、将封装好的 BeanDefinition 注册进 IoC容器。
*
* IoC容器的初始化 和 bean的依赖注入 是两个独立的过程,依赖注入一般发生在应用第一次通过 getBean()方法
* 从容器获取 bean 时。
* 另外需要注意的是,IoC容器 有一个预实例化的配置(即,将 元素 的 lazyInit属性 设为 false),
* 使该 元素对应的 bean可以提前实例化,而不用等到调用 getBean()方法 时才开始实例化。
*/
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识
prepareRefresh();
// 告诉子类启动 refreshBeanFactory() 方法,BeanDefinition 资源文件的载入从子类的
// refreshBeanFactory() 方法启动开始
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// 为容器的某些子类指定特殊的 BeanPost 事件处理器
postProcessBeanFactory(beanFactory);
// 调用所有注册的 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 为 BeanFactory 注册 BeanPost 事件处理器.
// BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
// 初始化信息源,和国际化相关.
initMessageSource();
// 初始化容器事件传播器
initApplicationEventMulticaster();
// 调用子类的某些特殊 Bean 初始化方法
onRefresh();
// 为事件传播器注册事件监听器.
registerListeners();
/**
* !!!!!!!!!!!!!!!!!!!!!
* 对配置了 lazy-init属性 为 false 的 bean 进行预实例化
* !!!!!!!!!!!!!!!!!!!!!
*/
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
// 销毁以创建的单态 Bean
destroyBeans();
// 取消 refresh 操作,重置容器的同步标识.
cancelRefresh(ex);
throw ex;
}
}
}
/**
* 对配置了 lazy-init属性 为 false 的 bean 进行预实例化
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 这是 Spring3 以后新加的代码,为容器指定一个转换服务 (ConversionService)
// 在对某些 bean 属性进行转换时使用
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
/**
* !!!!!!!!!!!!!!!!!!!!
* 在这里 通过调用 getBean()方法,触发依赖注入
* !!!!!!!!!!!!!!!!!!!!
*/
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 为了类型匹配,停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
// 缓存容器中所有注册的 BeanDefinition 元数据,以防被修改
beanFactory.freezeConfiguration();
// 对配置了 lazy-init属性 为 false 的 单例bean 进行预实例化处理
beanFactory.preInstantiateSingletons();
}
}
BeanPostProcessor 接口 也叫 Bean 后置处理器,作用是在 Bean 对象实例化和依赖注入完成后,在显示调用 bean 的 init-method(初始化方法)的前后添加我们自己的处理逻辑。注意是 Bean 实例化完毕后及依赖注入完成后触发的,接口的源码如下
public interface BeanPostProcessor {
/**
* 实例化、依赖注入完毕,
* 在调用显示的初始化之前完成一些定制的初始化任务
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* 实例化、依赖注入、初始化完毕时执行
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
使用方法也很简单,实现 BeanPostProcessor 接口,然后将实现类注入 IoC 容器即可。