- Spring IOC源码是什么
- 为什么学习Spring IOC源码
- SpringIOC源码该怎么理解
Spring IOC源码是什么
根据Spring IOC原理理解文章中了解了IOC以及DI的原理,以及最基本的Spring例子。接下来我们来思考一下,Spring IOC源码究竟是什么?
我们来看看控制台输出的I am kitty背后spring究竟做了哪些事情。作为开发人员一般很熟悉applicationContext.xml,关于测试类TestAnimal有使用了FileSystemXmlApplicationContext,那么我们就从这里入手,源码调用类步骤如下:
(1)FileSystemXmlApplicationContext继承自AbstractXmlApplicationContext;
(2)继承AbstractRefreshableConfigApplicationContext;
(3)继承AbstractRefreshableApplicationContext;
(4)继承AbstractApplicationContext;
(5)实现接口ConfigurableApplicationContext;
(6)继承接口ApplicationContext;
(7)继承接口ListableBeanFactory,HierarchicalBeanFactory;
(8)继承接口BeanFactory。
由此可以看出,接口BeanFactory就是Spring源码的入口。
接下来关注FileSystemXmlApplicationContext类构造方法
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
然后调用带有多个参数的构造方法
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
//S1.调用父类容器的构造方法为容器设置好Bean资源加载器
super(parent);
//S2.告诉读取器Bean定义资源文件的定位路径
setConfigLocations(configLocations);
//S3.刷新
if (refresh) {
refresh();
}
}
S1.调用父类容器的构造方法为容器设置好Bean资源加载器
super(parent);
S1-1最终调用AbstractApplicationContext类构造方法AbstractApplicationContext,代码如下:
public AbstractApplicationContext(ApplicationContext parent) {
this.parent = parent;
this.resourcePatternResolver = getResourcePatternResolver();
this.environment = createEnvironment();
}
this.parent = parent;复制对象
this.resourcePatternResolver = getResourcePatternResolver();解析资源模式
this.environment = createEnvironment();创建环境参数
S1-1-1其实getResourcePatternResolver()方法就是保存了resourceLoader对象,后续解析资源路径会用到的
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
S1-1-1-1实现类PathMatchingResourcePatternResolver的构造方法代码如下:
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
this.resourceLoader = resourceLoader;
}
S1-1-2加载环境配置createEnvironment()方法
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
类StandardEnvironment 继承了AbstractEnvironment 类,代码如下:
public class StandardEnvironment extends AbstractEnvironment {
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
}
AbstractEnvironment类的构造方法加载了log信息设置,代码如下:
public AbstractEnvironment() {
String name = getClass().getSimpleName();
if (this.logger.isDebugEnabled()) {
this.logger.debug(format("Initializing new %s", name));
}
customizePropertySources(this.propertySources);
if (this.logger.isDebugEnabled()) {
this.logger.debug(format(
"Initialized %s with PropertySources %s", name, this.propertySources));
}
}
在这里整个S1流程走完了,整理一下步骤:
(1)调用父类构造方法;
(2)保存了一个ApplicationContext容器对象
(3)保存了一个ResourceLoader对象
(4)加载配置参数
S2.告诉读取器Bean定义资源文件的定位路径
setConfigLocations(configLocations);
调用了父类AbstractRefreshableConfigApplicationContext的setConfigLocations方法,代码如下:
public void setConfigLocations(String[] locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
//将字符串解析为路径
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
然后调用了resolvePath方法,代码如下:
/**
* 解决给定的路径,用相应的替换占位符系统属性值,如有必要。应用于配置位置。
*/
protected String resolvePath(String path) {
return this.getEnvironment().resolveRequiredPlaceholders(path);
}
接下来调用了接口PropertyResolver的resolveRequiredPlaceholders方法,
实现类AbstractPropertyResolver实现了该方法,代码如下:
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
if (strictHelper == null) {
strictHelper = createPlaceholderHelper(false);
}
return doResolvePlaceholders(text, strictHelper);
}
创建了占位符帮助对象createPlaceholderHelper,然后执行了解析占位符方法doResolvePlaceholders,代码如下:
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
return helper.replacePlaceholders(text, new PlaceholderResolver() {
public String resolvePlaceholder(String placeholderName) {
return getProperty(placeholderName);
}
});
}
具体的解析代码就不展开了。
S3.刷新
refresh();
调用了父类AbstractApplicationContext的refresh()方法,代码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备这个上下文刷新。
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 告诉子类刷新内部的bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 准备在这种情况下使用的bean工厂。
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 允许在上下文子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 在上下文中调用注册为bean的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册拦截bean创建的bean处理器。
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化此上下文的消息源。
initMessageSource();
// Initialize event multicaster for this context.
// 初始化此上下文的事件多播器。
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 在特定的上下文子类中初始化其他特殊的bean。
onRefresh();
// Check for listener beans and register them.
// 检查监听器bean并注册它们。
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩下的(非惰性初始化)单例。
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 最后一步:发布相应的事件。
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.
// 销毁已经创建的单例资源。
destroyBeans();
// Reset 'active' flag.
// 重置“active”标志为false。
cancelRefresh(ex);
// Propagate exception to caller.
// 传播异常给调用者。
throw ex;
}
}
}
S3-1准备这个上下文刷新。
prepareRefresh();
调用了
/**
* 准备这个上下文进行刷新,设置其启动日期和活动标志以及执行任何财产来源的初始化。
*/
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 在上下文环境中初始化任何占位符属性源
initPropertySources();
// 验证标记为必需的所有属性是可解析的
// 请参阅ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
}
/**
* 用实际实例替换任何存根属性源。
* @请参阅 org.springframework.core.env.PropertySource.StubPropertySource
* @请参阅 org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
*/
protected void initPropertySources() {
// For subclasses: do nothing by default.
// 对于子类:默认情况下不做任何事情。
}