前言
本文是基于XML配置的方式去理解Spring的源码,这篇文章是大体说了一下IOC的内容,但是内容还是很多,初学者可能还是需要花1个多小时才能看完,后续我会出比较细致的IOC源码分析,从讲Bean的前身开始,直到讲到IOC的结束,看这篇文章之前,至少要保证你已经使用过Spring。
学习源码,我们要学习的是它们的设计思想,以及出了问题之后知道如何排查错误,以及我认为学习源码之后最大的优势就是可以做到自定义框架!
引言
废话不多说,直接上代码,首先使用maven加入如下依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
最基本的使用XML配置文件去启动Spring 容器的例子如下所示:
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
}
通过ClassPathXmlApplicationContext这个类,也能猜出来,它肯定是在ClassPath中寻找我们传入的配置文件,根据xml配置文件的内容,去初始化Spring 容器。
注意:这里的xml配置文件中的每一行都是有意义的,每一行都能帮助Spring去初始化容器,下面给出一个最基本的Spring XML配置文件的结构体:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <!-- 默认bean命名空间 -->
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- xml约束命名空间定义 -->
xmlns:aop="http://www.springframework.org/schema/aop"<!-- AOP命名空间的scheme约束 -->
xmlns:context="http://www.springframework.org/schema/context" <!-- context命名空间的scheme约束 -->
xsi:schemaLocation=" <!-- 上面各个scheme的location信息(网络地址) -->
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd ">
</beans>
这里的代码都是能够帮助Spring 初始化容器的,后面我们能看到这些xsd文件究竟是干嘛用的。
我们也可以不使用xml文件去初始化容器,所以我们先来看看ApplicationContext一个大体的继承结构是什么样子的:
可以看到上图中绿色的部分,它们就是可以使用其他的方式去初始化Spring容器的类了。
- AnnotationConfigApplicationContext:基于注解去初始化Spring 容器,使用配置类和注解去帮助Spring
- FileSystemXmlApplicationContext:和ClassPathXmlApplicationContext差不多,只不过它是传入系统中的路径
本文分析IOC,使用的是ClassPathXmlApplicationContext去构建Spring容器,首先我们先简单写一个Spring的例子,看看如何使用Spring,同时去分析Spring如何将我们的bean注入到容器中去。
定义一个接口:
public interface HelloWordService {
String sayHelloWord();
}
定义实现类:
public class HelloWorldServiceImpl implements HelloWorldService {
@Override
public String sayHelloWorld() {
return "hello word";
}
}
在resource目录下新建一个application.xml文件,文件内容如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloWorld" class="com.ming.spring.service.impl.HelloWorldServiceImpl"/>
</beans>
接下来新建一个启动类:
public class SpringApplication {
public static void main(String[] args) {
// 使用 XML 的形式去初始化 Spring 容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");
System.out.println("Spring 容器初始化成功");
// 从容器中去拿HelloWorldService的实现类 注意这一步不是使用new的方式去获取相关类
HelloWorldService helloWorld = applicationContext.getBean(HelloWorldService.class);
// 调用其方法
System.out.println(helloWorld.sayHelloWorld());
}
}
上面就是一个使用XML去配置Spring容器,并且从容器中拿我们想要的类的一个简单例子了,接下来就会依靠这个例子去讲解IOC容器,上面都是引言部分了,下面开始正式分析Spring的IOC功能了。
BeanFactory
BeanFactory,看到这个名字就知道,它是一个工厂类,主要用于生产和管理Bean实例,前面我们说的ApplicationContext就是一个BeanFactory,只不过加了很多功能而已,关于它的一个继承结构如下所示:
这里只是需要暂时记住,我们的ApplicationContext就是一个BeanFactory就好了,其他的我会在后续详细讲讲。
启动过程分析
我们从上面的这段代码开始分析:
public class SpringApplication {
public static void main(String[] args) {
// 使用 XML 的形式去初始化 Spring 容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");
System.out.println("Spring 容器初始化成功");
// 从容器中去拿HelloWorldService的实现类 注意这一步不是使用new的方式去获取相关类
HelloWorldService helloWorld = applicationContext.getBean(HelloWorldService.class);
// 调用其方法
System.out.println(helloWorld.sayHelloWorld());
}
}
首先我们点进ClassPathXmlApplicationContext:
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private Resource[] configResources;
...
//点进来的时候是这个构造方法 依次往下点
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
...
// 最终会流转到这个构造方法中
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
// 根据提供的路径 先去除空白 再处理成配置文件数组(以分号 逗号 空格 tab 换行符分割)
setConfigLocations(configLocations);
if (refresh) {
// 核心方法 这个方法看着很短 实际长的很
refresh();
}
}
...
}
接下来就是refresh();方法,之所以叫做refresh方法,是因为ApplicationContext创建之后,可能涉及到重新构建,那就得需要使用refresh方法了,它会将原来的ApplicationContext销毁,然后重新进行初始化操作。
接下来看到refresh的源码:
@Override
public void refresh() throws BeansException, IllegalStateException {
// 加锁 否则线程A初始化容器 线程B又销毁容器
synchronized (this.startupShutdownMonitor) {
// 准备工作 记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 将BeanDefinition注册到BeanFactory中 但是Bean却没有初始化
// 如果很难理解 就理解为将Class文件注入到了JVM中 什么时候需要类 就问JVM拿
// 这里也是一个意思 将Bean的定义文件加入到BeanFactory中 后续就依靠这个Bean定义文件去构建Bean
// 同时这里也有一个注册中心的概念 就是将Bean定义注册到BeanFactory中 其实就是放入了一个Map里
// beanName-BeanDefinition 的 一个map
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器 添加几个 BeanPostProcessor 手动注册几个特殊的 bean 忽略给定的自动装配依赖接口
prepareBeanFactory(beanFactory);
try {
// 这一步是留给子类进行拓展的 相当于钩子函数
// 所有的BeanDefinition都加载、注册完成之后 还没有初始化Bean之前
// 我们可以添加一些特殊的BeanFactoryPostProcessor的实现类进去做点事情
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注意 这里是注册BeanPostProcessor的实现类 通过名字也能猜出来 它是在扩展初始化Bean的方法
// 这个接口有两个方法:
// 1 在Bean初始化之前执行
// 2 在Bean初始化之后执行
// 它和BeanFactoryPostProcessor是不一样的 但是性质可以说是差不多的
// 注意:在这一步的Bean还没有进行初始化!!!
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource
// 其实就是国际化
// 这一步我们不会展开说 会直接跳过 重点也不在这里
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器
// 这边也跳过
initApplicationEventMulticaster();
// 同样的 也是钩子方法
// 在初始化单例Bean之前 还可以在这一步初始化一些特殊的Bean
onRefresh();
// 注册事件监听器 监听器需要实现 ApplicationListener 接口
// 这边跳过
registerListeners();
// 最重要的一步在这里
// 这一步开始初始化所有的单例Bean
// 但是不包括懒加载的Bean
finishBeanFactoryInitialization(beanFactory);
// 广播事件 告诉大家 ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
// 销毁已经初始化的 singleton 的 Beans 以免有些 bean 会一直占用资源
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
上述就是refresh方法的总体了,我们必须明确目标,对于一些事件广播器、事件监听器等,这些东西我们暂时不管,重点关注在整个IOC容器以及最重要的Bean的初始化,下面要带着一些问题去看下面的内容:
- Bean的定义——BeanDefinition(也叫做Bean的前身)是什么?
- Bean的定义被放入注册中心去了,注册中心是什么?
- 在通过Bean的定义去加载Bean的时候,如果遇到循环依赖,Spring是如何做的?
下面开始一步一步分解整个refresh方法了。
创建Bean容器的准备工作
这一步还是十分简单的,同时相对也不是那么重要,看看源码,知道有这么回事就可以了,源码如下所示:
protected void prepareRefresh() {
// 记录当前时间
this.startupDate = System.currentTimeMillis();
// 设置当前的容器状态
// 这里的closed和active都是原子类
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
// 初始化占位符资源 这一步默认什么都不做 留给子类拓展
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
// 开始校验xml配置文件
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
开始初始化BeanFactory并且注册BeanDefinition
接下来就走到了obtainFreshBeanFactory这个方法中,这个方法是最重要的方法之一,在这一步,我们会初始化Bean容器并且加载、注册BeanDefinition到容器中去。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 开始创建Bean容器 如果已经有Bean容器了 那么先销毁旧的Bean容器 再创建一个新的
// 同时加载并注册BeanDefinition到容器中
refreshBeanFactory();
// 获取刚刚创建好的Bean容器 也就是获取上一步创建好的
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
// 返回Bean容器
return beanFactory;
}
先看refreshBeanFactory方法(从现在开始要仔细看了,因为会涉及到很多个loadBeanDefinitions重载方法):
// AbstractRefreshableApplicationContext.java 第120行
protected final void refreshBeanFactory() throws BeansException {
// 判断是否已有Bean容器
if (hasBeanFactory()) {
// 如果有
// 销毁所有Bean
destroyBeans();
// 关闭BeanFactory
closeBeanFactory();
}
try {
// 创建一个DefaultListableBeanFactory的Bean容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化Id
beanFactory.setSerializationId(getId());
// 这个方法十分重要
// 设置BeanFactory的两个属性 1 是否允许Bean覆盖 2 是否允许循环引用
customizeBeanFactory(beanFactory);
// 加载BeanDefinition到BeanFactory中
// 这个方法要多看几遍 后面有着很多个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);
}
}
看到这里,我们看看下面的createBeanFactory这个方法的源码:
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// 跳转到这个方法
public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
// 跳转到这里
public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
this();
setParentBeanFactory(parentBeanFactory);
}
看到这里,就必须要明确一点,ApplicationContext虽然继承BeanFactory,但是它不仅仅是BeanFactory的实现类,通过上面的方法,可以看出ApplicationContext是内部持有一个BeanFactory(DefaultListableBeanFactory),所有的BeanFactory的操作都是委托给这个类进行操作的。
继续往下之前,我们必须要先来了解一下这个Bean定义——BeanDefinition到底是什么(个人理解:我把它想象为Class类)?
BeanDefinition——Bean定义(就是Bean的设计图,告诉Spring如何去创建Bean)
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// Bean的类型 默认就这两种 1 singleton 2 prototype
// request, session、globalSession、application、websocket 这几种都是web的扩展
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// 继承父类Bean的配置信息(不是Java中继承的概念 是bean继承)
void setParentName(String parentName);
// 获取父 Bean
String getParentName();
// 设置 Bean 的类名称 将来是要通过反射来生成实例的
void setBeanClassName(String beanClassName);
// 获取 Bean 的类名称
String getBeanClassName();
// 设置 bean 的 scope
void setScope(String scope);
String getScope();
// 设置是否懒加载
void setLazyInit(boolean lazyInit);
// 判断是否为懒加载
boolean isLazyInit();
// 设置该Bean依赖的所有Bean 也就是xml配置文件中depends-on="" 属性设置的值
// @Autowire 标记的不是哦
void setDependsOn(String... dependsOn);
// 返回该 Bean 的所有依赖
String[] getDependsOn();
// 设置该 Bean 是否可以注入到其他 Bean 中(针对根据类型注入)
// 这里是不管根据名称注入的
void setAutowireCandidate(boolean autowireCandidate);
// 该 Bean 是否可以注入到其他 Bean 中
boolean isAutowireCandidate();
// 指定大哥 就是说这个接口有多个实现类 这个时候Spring不知道找谁了 就会优先找primary为true的bean
void setPrimary(boolean primary);
// 是否是 primary 的
boolean isPrimary();
// 如果该 Bean 采用工厂方法生成 指定工厂名称
void setFactoryBeanName(String factoryBeanName);
// 获取工厂名称
String getFactoryBeanName();
// 指定工厂类中的 工厂方法名称
void setFactoryMethodName(String factoryMethodName);
// 获取工厂类中的 工厂方法名称
String getFactoryMethodName();
// 构造器参数
ConstructorArgumentValues getConstructorArgumentValues();
// Bean 中的属性值
MutablePropertyValues getPropertyValues();
// 是否 singleton
boolean isSingleton();
// 是否 prototype
boolean isPrototype();
// 如果这个 Bean 是被设置为 abstract 那么不能实例化
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
这里所有的属性和方法记住也是不大可能的,但是要知道有这么一个东西,里面的属性和方法看一看,有点印象就行,继续分析IOC源码。
customizeBeanFactory方法
这个方法很简单,就是设置两个属性,是否允许BeanDefinition覆盖和是否允许循环依赖。
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
// 是否允许 Bean 定义覆盖
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
// 是否允许 Bean 间的循环依赖
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
Bean覆盖
Bean覆盖就是在配置文件中配置了相同的id和name的,默认情况下,如果在同一个配置文件中会报错,在不同的配置文件中会覆盖。
循环依赖
循环依赖也很容易理解,比如A依赖B,B依赖C,C依赖A,默认情况下Spring是允许循环依赖的,但是Spring不能解决在构造方法中的循环依赖,这一点在后面的源码就能体现出来。
loadBeanDefinitions 重点方法
接下来就是十分重要的loadBeanDefinitions方法了,它有着很多个的重载方法,它就是加载各个BeanDefinition并且放入容器中。
// AbstractXmlApplicationContext类 80行
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 实例化XmlBeanDefinitionReader去加载各个BeanDefinition
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
// 下面就是对这个XmlBeanDefinitionReader进行一些配置
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
// 初始化XmlBeanDefinitionReader 这个方法也是给子类去覆写的
initBeanDefinitionReader(beanDefinitionReader);
// 再次回到loadBeanDefinitions方法 注意 这里的传参是XmlBeanDefinitionReader 看名字也很好记住它
// 继续往下
loadBeanDefinitions(beanDefinitionReader);
}
// AbstractXmlApplicationContext.java 120
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 重点在这里
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 这个分支最终会把路径解析成Resource进入第一个分支
reader.loadBeanDefinitions(configLocations);
}
}
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
// 这里每一个文件都被解析成了resource 循环去进行加载BeanDefinition
for (Resource resource : resources) {
// 又来到了这个方法loadBeanDefinitions 继续往下看
counter += loadBeanDefinitions(resource);
}
// 返回总共加载了多少个 BeanDefinition
return counter;
}
// XmlBeanDefinitionReader 303
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 这一步看名字也知道要干嘛 不重要 继续往下走
return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader 314
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<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 核心方法 所有带doXxxx的方法都是核心方法 真正干活的方法
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
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();
}
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 将XML文件解析成Document对象进行解析
Document doc = doLoadDocument(inputSource, resource);
// 继续往下走
return registerBeanDefinitions(doc, resource);
}
catch (...
}
// 返回值:返回从当前配置文件加载了多少数量的 BeanDefinition
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 重点在这里 看方法名字就知道这个是注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// DefaultBeanDefinitionDocumentReader 90
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
// 这一步开始解析xml文件了 也就是这一步才刚刚开始读取文件 加载BeanDefinition
// 从根节点开始解析
doRegisterBeanDefinitions(root);
}
到了这一步,终于是开始读取配置文件了,这里读取配置文件只是读取了其中一个,将配置文件转为DOM数去进行解析,继续往下走:
// DefaultBeanDefinitionDocumentReader 116
protected void doRegisterBeanDefinitions(Element root) {
// 我们看名字就知道 BeanDefinitionParserDelegate 必定是一个重要的类 它负责解析 Bean 定义
// 这里的parent 是递归问题
// 因为 <beans /> 内部是可以定义 <beans /> 的
//所以这个方法的 root 其实不一定就是 xml 的根节点 也可以是嵌套在里面的 <beans /> 节点
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
// 这里说的是根节点 <beans ... profile="dev" /> 中的 profile 是否是当前启动环境
// 比如现在是生产环境 那自然是不用加载开发环境的Bean了
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root); // 钩子方法
// 开始解析了 继续往下
parseBeanDefinitions(root, this.delegate);
postProcessXml(root); // 钩子方法
this.delegate = parent;
}
// 这里明确一点 default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />
// 说白了这一步就是开始解析相应的标签和标签里的内容
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
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;
if (delegate.isDefaultNamespace(ele)) {
// 解析 default namespace 下面的几个元素
parseDefaultElement(ele, delegate);
}
else {
// 解析其他 namespace 的元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
从上面的代码可以看出来了,最终会流入两个分支:
- parseDefaultElement(ele, delegate);
- delegate.parseCustomElement(ele);
这里的namespace初学者估计是不知道是啥的,下面进行解释一下:
http://www.springframework.org/schema/beans
上面这玩意,熟悉吧,就是在配置文件中引入的东西,它所代表的就是namespace了,对于其他的标签,那么就需要在xml文件的头部引入对应的namespace以及对应的.xsd文件路径,如下所示:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">
同时代码需要对应的parser来解析,比如MvcNamespaceHandler、TaskNamespaceHandler、ContextNamespaceHandler、AopNamespaceHandler 等。
也就是说比如遇到了一个标签,那么要分析Spring是如何加载并解析它的,就应该去找对应的XxxNameSpaceHandler这个处理类去分析它的流程。
现在开始分析处理default标签的方法:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
// 处理 <import /> 标签
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
// 处理 <alias /> 标签定义
// <alias name="fromName" alias="toName"/>
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 处理 <bean /> 标签定义 重点 因为最常用了
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 如果碰到的是嵌套的 <beans /> 标签 需要递归
doRegisterBeanDefinitions(ele);
}
}
这里就挑解析 标签来说吧,其他的方法都是大同小异的。
processBeanDefinition(ele, delegate);
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 将 <bean /> 节点中的信息提取出来 然后封装到一个 BeanDefinitionHolder 中
// 这个BeanDefinitionHolder就是对BeanDefinition再次进行了封装
// BeanDefinitionHolder的属性有
// 1 beanDefinition 2 beanName 3 aliases 所以也没什么
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// 下面几行后面说 先看看Bean标签里面可以定义些什么 再继续往下走
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
下面是Bean标签内可以定义的属性:
| Property | |
|---|---|
| class | 类的全限定名 |
| name | 可指定 id、name(用逗号、分号、空格分隔) |
| scope | 作用域 |
| constructor arguments | 指定构造参数 |
| properties | 设置属性的值 |
| autowiring mode | no(默认值)、byName、byType、 constructor |
| lazy-initialization mode | 是否懒加载(如果被非懒加载的bean依赖了那么其实也就不能懒加载了) |
| initialization method | bean 属性设置完成后,会调用这个方法 |
| destruction method | bean 销毁后的回调方法 |
那就继续往下:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
// 将 name 属性的定义按照 “逗号、分号、空格” 切分 形成一个 别名列表数组
// 也可以不进行设置name
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
// 如果没有指定id 就用别名列表的第一个名字作为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");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 根据 <bean ...>...</bean> 中的配置创建 BeanDefinition 然后把配置中的信息都设置到实例中
// 也就是说这方法走完 就出来一个 beanDefinition
// 核心方法就是这个方法
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
// 到这里 一个 <bean /> 标签就算解析结束了
if (beanDefinition != null) {
// 如果都没有设置 id 和 name 那么此时的 beanName 就会为 null 进入下面这块代码产生对应的beanName
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {// 按照我们的思路 这里 containingBean 是 null 的
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 如果我们不定义 id 和 name 那么我们引言里的那个例子:
// 1. beanName 为:com.ming.spring.demo.HelloWorldServiceImpl#0
// 2. beanClassName 为:com.ming.spring.demo.HelloWorldServiceImpl
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
// 把 beanClassName 设置为 Bean 的别名
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);
// 返回 BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
// 继续往下走 看看是怎么创建一个BeanDefinition的
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 创建 BeanDefinition 然后设置类信息
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 设置 BeanDefinition 的一些属性 这些属性定义在 AbstractBeanDefinition 中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 下面就是解析Bean标签内部的子元素 解析出来的元素全部放在AbstractBeanDefinition中
// 解析 <meta />
parseMetaElements(ele, bd);
// 解析 <lookup-method />
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 <replaced-method />
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 <constructor-arg />
parseConstructorArgElements(ele, bd);
// 解析 <property />
parsePropertyElements(ele, bd);
// 解析 <qualifier />
parseQualifierElements(ele, bd);
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();
}
return null;
}
到这里我们已经根据bean标签解析出来了一个BeanDefinitionHolder实例,回到解析bean标签方法:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 将 <bean /> 节点转换为 BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 如果有自定义属性的话 进行相应的解析 先忽略
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 注册完成后 发送事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
下面我们开始进行注册Bean:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
// 注册 BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
// 这个不是很重要 重点是上面的注册BeanDefinition
// 使用map保存别名信息 alias -> beanName
// 获取的时候 会先将 alias 转换为 beanName 然后再查找
registry.registerAlias(beanName, alias);
}
}
}
// 继续往下
@Override
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");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(...);
}
}
// 这里的oldBeanDefinition就是对应着允许覆盖这个设置
BeanDefinition oldBeanDefinition;
// 之后会看到,所有的 Bean 注册后会放入这个 beanDefinitionMap 中
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 处理重复名称的 Bean 定义的情况
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
// 如果不允许覆盖的话 抛异常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription()...
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// log...用框架定义的 Bean 覆盖用户自定义的 Bean
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
// log...用新的 Bean 覆盖旧的 Bean
}
else {
// log...用同等的 Bean 覆盖旧的 Bean,这里指的是 equals 方法返回 true 的 Bean
}
// 覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 判断是否已经有其他的 BeanDefinition 开始初始化了
// 这里是注册BeanDefinition并不是注册Bean哦
// 容器初始化的最后才会初始化所有的单例bean
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 正常流入这个分支中
// 将 BeanDefinition 放到这个 map 中 这个 map 保存了所有的 BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 这是 ArrayList 所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字
this.beanDefinitionNames.add(beanName);
// 这是个 LinkedHashSet 代表的是手动注册的 singleton bean
// 注意这里是 remove 方法 到这里的 Bean 当然不是手动注册的
// 手动指的是通过调用以下方法注册的 bean :
// registerSingleton(String beanName, Object singletonObject)
// 这不是重点 解释只是为了不让大家疑惑 Spring 会在后面"手动"注册一些 Bean
// 如 "environment"、"systemProperties" 等 bean 我们自己也可以在运行时注册 Bean 到容器中的
this.manualSingletonNames.remove(beanName);
}
// 这个不重要 在预初始化的时候会用到 跳过
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
到这里,就是把一个个bean标签解析成了BeanDefinition,但是还没有对Bean进行初始化,然后在容器中注册了各个BeanDefinition到注册中心(其实就是一个map),并且注册完成后发送注册完成事件。
前面的内容可以说是比较简单的,稍微整理一下思路就能知道发生了些什么,就是很繁琐而已。
下面才陆陆续续开始正式的使用BeanDefinition去初始化Bean出来。
开始初始化所有的单例Bean
首先让我们回到refresh方法,要记住刚刚代码走到了哪里,刚刚我们只是将配置文件读取,将所有的BeanDefinition在容器中注册。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
// 刚刚上面主要就是说完了这一步 下面的几个步骤将会简单带过 只看核心步骤
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器 添加几个 BeanPostProcessor 手动注册几个特殊的 bean
prepareBeanFactory(beanFactory);
try {
......
// 核心方法 初始化所有的单例bean 懒加载的除外
finishBeanFactoryInitialization(beanFactory);
// 广播初始化完成事件 ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经初始化的 singleton 的 Beans 以免有些 bean 会一直占用资源
destroyBeans();
cancelRefresh(ex);
// 把异常往外抛
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
准备Bean容器:prepareBeanFactory(注册特殊bean)
在上面我们可以看到,容器在初始化完成之后,且所有的BeanDefinition都注册在容器中时,Spring会手动注册几个特殊的bean,看到prepareBeanFactory方法:
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 的类加载器
// 这里设置为加载当前 ApplicationContext 类的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置 BeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加一个 BeanPostProcessor 这个 processor 比较简单
// 实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调
// 这个我们很常用 如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
// 注意:它不仅仅回调 ApplicationContextAware 还会负责回调 EnvironmentAware、ResourceLoaderAware 等
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面的方法看名字就能知道是干嘛的 ignore 忽略
// 也就是如果bean依赖于以下几个接口的实现类 那么在自动装配的时候忽略它们 后续Spring会再处理
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 下面就是为特殊的几个bean赋值
// 通过下面几行代码就能知道 ApplicationContext 是内部持有一个beanFactory
// 并且通过下面这几行的 this 就能知道 ApplicationContext 继承了下面的各个类
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 这个 BeanPostProcessor 也很简单 在 bean 实例化后 如果是 ApplicationListener 的子类
// 那么将其添加到 listener 列表中 也就是注册事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 这里涉及到特殊的 bean 名为:loadTimeWeaver 这不是我们的重点 忽略它
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 下面就是Spring为我们默认注册的几个bean
// 如果没有定义 "environment" 这个 bean 那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 如果没有定义 "systemProperties" 这个 bean 那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 如果没有定义 "systemEnvironment" 这个 bean 那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
上面代码可以看出来其实就是Spring对一些特殊的bean进行了处理,比如注册等操作,上面的如果理解不了可以暂时先放着,重点也不在这里。
初始化所有的单例bean
从上面的代码就可以看出来,重点方法是finishBeanFactoryInitialization(beanFactory);这个方法了,它会负责初始化所有的单例bean。
那么现在Spring都做了哪些事情呢?
- BeanFactory已经创建完成了
- 所有实现了BeanFactoryPostProcessor接口的bean都已经初始化了,并且postProcessBeanFactory方法也回调执行了
- spring注册了一些特殊的bean
所以下一步,只要不是懒加载的bean,spring都会开始初始化单例bean了。
// 初始化剩余的 singleton beans
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 首先 初始化名字为 conversionService 的 Bean
// 注意 初始化的动作包装在 beanFactory.getBean(...) 中 继续往下看
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// 先初始化 LoadTimeWeaverAware 类型的 Bean 这里先跳过 因为这里主要是 AspectJ 的内容
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// 没什么别的目的 因为到这一步的时候 Spring 已经开始预初始化 singleton beans 了
// 肯定不希望这个时候还出现 bean 定义解析、加载、注册。
beanFactory.freezeConfiguration();
// 开始初始化
beanFactory.preInstantiateSingletons();
}
preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// this.beanDefinitionNames 保存了所有的 beanNames
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 下面这个循环,触发所有的非懒加载的 singleton beans 的初始化操作
for (String beanName : beanNames) {
// 合并父 Bean 中的配置 也就是 <bean id="" class="" parent="" /> 中的 parent
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象、非懒加载的 singletons 如果 xml 中配置了 'abstract = true' 那是不需要初始化的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 处理 FactoryBean
if (isFactoryBean(beanName)) {
// FactoryBean 的话 在 beanName 前面加上 ‘&’ 符号 再调用 getBean getBean方法是重点
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
// 对于普通的 Bean 调用 getBean(beanName) 进行初始化
getBean(beanName);
}
}
}
// 到这里说明所有的非懒加载的 singleton beans 已经完成了初始化
// 如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的 那么在这里得到回调 忽略
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
getBean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 注意 这里依然是在解析初始化bean的过程
// 如果bean没有初始化 那么这个方法就先初始化bean之后返回
// 如果bean初始化了 那么这个方法就直接返回
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 获取真正的beanName 处理两种情况 一个是前面说的 FactoryBean(前面带 ‘&’),
// 一个是别名问题 因为这个方法是 getBean 获取 Bean 用的
final String beanName = transformedBeanName(name);
// 注意 这个是返回值
Object bean;
// 检查下是不是已经创建过了
Object sharedInstance = getSingleton(beanName);
// 这里说下 args 呗 虽然看上去一点不重要 前面我们一路进来的时候都是 getBean(beanName),
// 所以 args 传参其实是 null 的 但是如果 args 不为空的时候 那么意味着调用方不是希望获取 Bean 而是创建 Bean
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("...");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 下面这个方法:如果是普通 Bean 的话 直接返回 sharedInstance
// 如果是 FactoryBean 的话 返回它创建的那个实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 创建过了此 beanName 的 prototype 类型的 bean 那么抛异常
// 往往是因为陷入了循环引用
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查一下这个 BeanDefinition 在容器中是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果当前容器不存在这个 BeanDefinition 则去父容器找找看有没有
String nameToLookup = originalBeanName(name);
if (args != null) {
// 返回父容器的查询结果
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
markBeanAsCreated(beanName);
}
// 这里开始就是要创建bean了 对于单例bean来说 容器中没有创建过这个bean
// 对于原型模式来说 每次请求都要创建一个新的bean
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 先初始化依赖的所有 Bean 这里也就是准备工作 先准备好需要的依赖Bean
// 注意 这里的依赖指的是 depends-on 中定义的依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 检查是不是有循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册一下依赖关系
registerDependentBean(dep, beanName);
// 先初始化被依赖项
getBean(dep);
}
}
// 如果是 singleton scope 的 创建 singleton 的实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 执行创建 Bean 后面会详细说
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是 prototype scope 的 创建 prototype 的实例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 执行创建 Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 如果不是 singleton 和 prototype 的话 需要委托给相应的实现类来处理
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
// 执行创建 Bean
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
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;
}
}
// 最后 检查一下类型对不对 不对的话就抛异常 对的话就返回了
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
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;
}
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 确保 BeanDefinition 中的 Class 被加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 准备方法覆写 这里又涉及到一个概念:MethodOverrides 它来自于 bean 定义中的 <lookup-method />
// 和 <replaced-method />
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 重点 开始创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
创建bean(重点)
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 说明不是 FactoryBean 这里实例化 Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 这个就是 Bean 里面的 我们定义的类 的实例
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
// 类型
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// 直接忽略 涉及接口:MergedBeanDefinitionPostProcessor
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 下面这块代码是为了解决循环依赖的问题
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");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 这一步负责属性装配 因为前面的实例只是实例化了 并没有设值 这里就是设值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 还记得 init-method、InitializingBean 接口、 BeanPostProcessor 接口
// 这里就是处理 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) {
//
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
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.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
到这里,我们就可以说是有一个大概的初始化的流程框架了,接下来我们通过这三个细节来分析代码:
- 创建Bean实例
- 依赖注入
- 回调方法
创建Bean实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 确保已经加载了此 class
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());
}
if (mbd.getFactoryMethodName() != null) {
// 采用工厂方法实例化 注意这里不是 FactoryBean
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 如果不是第一次创建 比如第二次创建 prototype bean
// 这种情况下 我们可以从第一次创建知道 采用无参构造函数 还是构造函数依赖注入 来完成实例化
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) {
// 构造函数依赖注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 无参构造函数
return instantiateBean(beanName, mbd);
}
}
// 判断是否采用有参构造函数
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);
}
这里就看一个最简单的无参构造函数的构造实例:
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
// 实例化 关键的一步
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
// 包装成 BeanWrapper 然后返回
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
// 下面看beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);这一步
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// 如果不存在方法覆写 那就使用 java 反射进行实例化 否则使用 CGLIB
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 利用构造方法进行实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 存在方法覆写 利用 CGLIB 来完成实例化 需要依赖于 CGLIB 生成子类
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
bean属性注入
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// bean 实例的所有属性都在这里了
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// 到这步的时候 bean 实例化完成(通过工厂方法或构造方法)但是还没开始属性设值
// InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 通过名字找到所有属性值 如果是 bean 依赖 先初始化依赖的 bean 记录依赖关系
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 通过类型装配
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
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 进到这里: AutowiredAnnotationBeanPostProcessor
// 对采用 @Autowired、@Value 注解的依赖进行设值,这里的内容也是非常丰富的,不过本文不会展开说了,感兴趣的读者请自行研究
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 设置 bean 实例的属性值
applyPropertyValues(beanName, mbd, bw, pvs);
}
回调方法
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 接口 回调
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回调
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 处理 bean 中定义的 init-method
// 或者如果 bean 实现了 InitializingBean 接口 调用 afterPropertiesSet() 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回调
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}