前言
最近我在读Spring源码,还是有不少收获,打算近期把阅读的心得体会总结一下分享给大家,让大家也能够快速入手,希望对你会有所帮助。
我尽量用一些自己认为更好理解的方式,带大家一起感受一下Spring的魅力。
我们先从最最最基础的Spring IOC开始。
需要注意的是,Spring系列文章源码的版本是:5.3.23。
1. 什么是Spring IOC?
IOC是InversionofControl的缩写,即控制反转。
我们之前是怎么创建对象的,大概是这样的吧:
Useruser=newUser();
user.setName("苏三");
Rolerole=newRole();
role.setId(123);
role.setName("角色");
user.setRole(role);在我们的业务代码中,通过new关键字主动创建对象,然后就可以调用该对象的方法了。
这种创建对象的方式,是开发者控制的。
如果user和role都是单例对象,创建和初始化对象,在整个生命周期中只有一次。
既然如此,对象的创建和初始化,有没有办法让框架代码自动实现呢?
将创建对象的方式,反转给框架控制,不由开发者控制,这样更智能化一些。
这其实是Spring IOC的控制反转。
其实Spring IOC不只是包含控制反转的功能,它的功能更强大,还能帮大家完成各个对象依赖关系的字段注入。
这就是大家经常说的DI(Dependency Injection),即依赖注入。
上面的那个例子中user对象的初始化,需要依赖于role对象,需要它先初始化。
这里用的:
user.setRole(role);手动设置的依赖,其实Spring可以帮我们自动完成依赖的注入。
问题来了,Spring是如何管理对象的呢?
2. BeanFactory
如果你经常使用Spring,肯定听过BeanFactory,它是一个顶层的接口,用来创建Spring容器的。
在Spring中的对象,有个非常特别的名字,叫做:Bean。
在Java中万事万物皆是对象,而在Spring中万事万物皆是Bean。
BeanFactory见名之意,是Bean的工厂,用来创建和管理Bean对象的。
publicinterfaceBeanFactory{
StringFACTORY_BEAN_PREFIX="&";
ObjectgetBean(Stringname)throwsBeansException;
<T>TgetBean(Stringname,Class<T>requiredType)throwsBeansException;
ObjectgetBean(Stringname,Object...args)throwsBeansException;
<T>TgetBean(Class<T>requiredType)throwsBeansException;
<T>TgetBean(Class<T>requiredType,Object...args)throwsBeansException;
<T>ObjectProvider<T>getBeanProvider(Class<T>requiredType);
<T>ObjectProvider<T>getBeanProvider(ResolvableTyperequiredType);
booleancontainsBean(Stringname);
booleanisSingleton(Stringname)throwsNoSuchBeanDefinitionException;
booleanisPrototype(Stringname)throwsNoSuchBeanDefinitionException;
booleanisTypeMatch(Stringname,ResolvableTypetypeToMatch)throwsNoSuchBeanDefinitionException;
booleanisTypeMatch(Stringname,Class<?>typeToMatch)throwsNoSuchBeanDefinitionException;
@Nullable
Class<?>getType(Stringname)throwsNoSuchBeanDefinitionException;
@Nullable
Class<?>getType(Stringname,booleanallowFactoryBeanInit)throwsNoSuchBeanDefinitionException;
String[]getAliases(Stringname);
}BeanFactory接口中定义了我们耳熟能详的方法,这些想法我们经常会用到。
但这些只是Spring IOC最基础的功能,ApplicationContext接口的出现极大的丰富了BeanFactory接口的功能。

ApplicationContext接口继承了BeanFactory接口功能,并且增加了:资源文件的处理、事件处理、国际化等功能。
目前Spring容器,更多的是通过ApplicationContext接口的实现类取创建和初始化的。
我们见得比较多的实现类有:
- FileSystemXmlApplicationContext
- ClassPathXmlApplicationContext
- AnnotationConfigWebApplicationContext
其实这些类都殊途同归,最终都会调用refresh方法,我们以ClassPathXmlApplicationContext类为例:
publicClassPathXmlApplicationContext(
String[]configLocations,booleanrefresh,@NullableApplicationContextparent)
throwsBeansException{
super(parent);
setConfigLocations(configLocations);
if(refresh){
refresh();
}
}它的构造方法最终会调用refresh方法,该方法是Spring容器的关键方法。
顺便说一下,上面的setConfigLocations方法主要是解析配置文件的路径的。
3. refresh方法
refresh方法会去解析配置文件中的各种标签,已经解析各种Spring的注解,创建Spring容器,创建和初始化各种bean。
refresh方法是Spring IOC的入口方法,后面大家想阅读Spring的源码,可以直接从该方法开始。
该方法是AbstractApplicationContext类的方法。
主要代码如下:
publicvoidrefresh()throwsBeansException,IllegalStateException{
synchronized(this.startupShutdownMonitor){
StartupStepcontextRefresh=this.applicationStartup.start("spring.context.refresh");
//准备环境,初始化placeholder
prepareRefresh();
//解析xml,生成并注册BeanDefinition
ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();
//准备BeanFactory容器参数
prepareBeanFactory(beanFactory);
try{
//钩子方法,添加BeanFactoryPostProcessor
postProcessBeanFactory(beanFactory);
StartupStepbeanPostProcess=this.applicationStartup.start("spring.context.beans.post-process");
//调用BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
//支持国际化
initMessageSource();
//初始化广播事件
initApplicationEventMulticaster();
//钩子方法,启动web容器
onRefresh();
//注册事件监听器
registerListeners();
//初始化单例bean
finishBeanFactoryInitialization(beanFactory);
//广播消息
finishRefresh();
}
catch(BeansExceptionex){
//销毁Spring容器
destroyBeans();
//重置状态
cancelRefresh(ex);
throwex;
}
finally{
//重置常用缓存
resetCommonCaches();
contextRefresh.end();
}
}
}下面用一张图,以便于大家更好的理解。

好了,今天就聊到这里,后面会将refresh方法中的关键代码都跟大家分享一下,我们下期再见。