Spring IOC 源码分析有三篇
Spring IOC 初始化1–定位
Spring IOC 初始化2–加载BeanDefinition
Spring IOC 初始化3–注册BeanDefinition
本次源码分析,基于spring 5.2.6.RELEASE 版本
Spring容器使用
public static void main( String[] args )
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
源码分析
通过构造器启动Spring容器
//构造器,传入一个配置文件
public ClassPathXmlApplicationContext(String configLocation) throws BeansException{
this(new String[] {configLocation}, true, null);
}
//实际上是调用了这个构造器 配置文件可以传多个进来
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);//调用父类构造器,生成资源加载器
setConfigLocations(configLocations);//设置配置文件
if (refresh) {
refresh();//启动Spring容器
}
}
1、ClassPathXmlApplicationContext的父构造器
public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
继续调用父构造器
public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
继续 调用父构造器
public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
继续 调用父构造器
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();//调用自身构造器,设置一个资源解析器,以后可以加载资源
setParent(parent);//设置父上下文 一路传入的parent是null
}
1.1、设置资源解析器
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
生成资源解析器
//org.springframework.context.support.AbstractApplicationContext#getResourcePatternResolver
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
PathMatchingResourcePatternResolver
private final ResourceLoader resourceLoader;
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
//设置Spring的资源加载器
this.resourceLoader = resourceLoader;
}
因为AbstractApplicationContext 继承了 DefaultResourceLoader,因此也是一个资源加载器
1.2、设置parent
//org.springframework.context.support.AbstractApplicationContext#setParent
@Override
public void setParent(@Nullable ApplicationContext parent) {
this.parent = parent;
//上面ClassPathXmlApplicationContext 调用的时候,传进来的是null
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
结合来看,ClassPathXmlApplicationContext 构造器的第一步就是生成了一个资源加载器
2、设置资源加载路径
这里调用了父类的方法
//org.springframework.context.support.AbstractRefreshableConfigApplicationContext#setConfigLocations
//传入配置文件路径,可能为多个
public void setConfigLocations(@Nullable 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;
}
}
解析配置文件路径
//org.springframework.context.support.AbstractRefreshableConfigApplicationContext#resolvePath
private String[] configLocations;
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
2.1、调用父类 的方法,获取Environment
//org.springframework.context.support.AbstractApplicationContext#getEnvironment
//上面可以看到,如果第一步传入的参数不为null,也会调用这个方法
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
//创建Environment
this.environment = createEnvironment();
}
return this.environment;
}
创建Environment
//org.springframework.context.support.AbstractApplicationContext#createEnvironment
protected ConfigurableEnvironment createEnvironment() {
//这里创建了一个标准的Environment
return new StandardEnvironment();
}
2.2、解析配置文件路径
private final MutablePropertySources propertySources = new MutablePropertySources();
private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources);
//org.springframework.core.env.AbstractEnvironment#resolveRequiredPlaceholders
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
return this.propertyResolver.resolveRequiredPlaceholders(text);
}
2.2.1、创建MutablePropertySources
public MutablePropertySources() {
}
2.2.2、创建PropertySourcesPropertyResolver
private final PropertySources propertySources;
//这里传入了一个MutablePropertySources
public PropertySourcesPropertyResolver(@Nullable PropertySources propertySources) {
this.propertySources = propertySources;
}
2.2.3、解析占位符
private PropertyPlaceholderHelper strictHelper;
//org.springframework.core.env.AbstractPropertyResolver#resolveRequiredPlaceholders
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
if (this.strictHelper == null) {
this.strictHelper = createPlaceholderHelper(false);
}
return doResolvePlaceholders(text, this.strictHelper);
}
创建占位符处理器
//PLACEHOLDER_PREFIX = "${"
private String placeholderPrefix = SystemPropertyUtils.PLACEHOLDER_PREFIX;
//PLACEHOLDER_SUFFIX = "}"
private String placeholderSuffix = SystemPropertyUtils.PLACEHOLDER_SUFFIX;
//VALUE_SEPARATOR = ":"
private String valueSeparator = SystemPropertyUtils.VALUE_SEPARATOR;
//org.springframework.core.env.AbstractPropertyResolver#createPlaceholderHelper
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix,this.valueSeparator, ignoreUnresolvablePlaceholders);
}
创建PropertyPlaceholderHelper入参分别是占位符前缀${,占位符后缀},值分隔符:,是否忽略解析占位符
private static final Map<String, String> wellKnownSimplePrefixes = new HashMap<>(4);
static {
wellKnownSimplePrefixes.put("}", "{");
wellKnownSimplePrefixes.put("]", "[");
wellKnownSimplePrefixes.put(")", "(");
}
private final String placeholderPrefix;
private final String placeholderSuffix;
private final String simplePrefix;
@Nullable
private final String valueSeparator;
private final boolean ignoreUnresolvablePlaceholders;
public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix, @Nullable String valueSeparator, boolean ignoreUnresolvablePlaceholders) {
Assert.notNull(placeholderPrefix, "'placeholderPrefix' must not be null");
Assert.notNull(placeholderSuffix, "'placeholderSuffix' must not be null");
this.placeholderPrefix = placeholderPrefix;
this.placeholderSuffix = placeholderSuffix;
//根据后缀获取前缀
String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix);
if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {
//赋值 {
this.simplePrefix = simplePrefixForSuffix;
}
else {
this.simplePrefix = this.placeholderPrefix;
}
this.valueSeparator = valueSeparator;
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
}
2.2.4、解析占位符
//org.springframework.core.env.AbstractPropertyResolver#doResolvePlaceholders
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper){
return helper.replacePlaceholders(text, this::getPropertyAsRawString);
}
调用子类方法获取属性值
//org.springframework.core.env.PropertySourcesPropertyResolver#getPropertyAsRawString
protected String getPropertyAsRawString(String key) {
return getProperty(key, String.class, false);
}
private final PropertySources propertySources;
//org.springframework.core.env.PropertySourcesPropertyResolver#getProperty
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
for (PropertySource<?> propertySource : this.propertySources) {
if (logger.isTraceEnabled()) {
logger.trace("Searching for key '" + key + "' in PropertySource '" +
propertySource.getName() + "'");
}
Object value = propertySource.getProperty(key);
if (value != null) {
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
logKeyFound(key, propertySource, value);
return convertValueIfNecessary(value, targetValueType);
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("Could not find key '" + key + "' in any property source");
}
return null;
}
转换值,将value转换成对应的类型
protected <T> T convertValueIfNecessary(Object value, @Nullable Class<T> targetType) {
if (targetType == null) {
return (T) value;
}
ConversionService conversionServiceToUse = this.conversionService;
if (conversionServiceToUse == null) {
// Avoid initialization of shared DefaultConversionService if
// no standard type conversion is needed in the first place...
if (ClassUtils.isAssignableValue(targetType, value)) {
return (T) value;
}
conversionServiceToUse = DefaultConversionService.getSharedInstance();
}
return conversionServiceToUse.convert(value, targetType);
}
3、刷新
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {//加锁
//准备刷新
prepareRefresh();
//ioc的初始化在这里
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//准备BeanFactory
prepareBeanFactory(beanFactory);
try {
//调用子类的方法
postProcessBeanFactory(beanFactory);
//BeanFactory后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
//bean后置处理器
registerBeanPostProcessors(beanFactory);
//初始化信息源
initMessageSource();
//初始化容器事件传播器.
initApplicationEventMulticaster();
//调用子类的某些特殊Bean初始化方法 比如web容器的初始化
onRefresh();
//注册事件监听器.
registerListeners();
//初始化非lazy的bean 预先实例化bean
finishBeanFactoryInitialization(beanFactory);
//发布容器事件,结束refresh
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
//销毁已创建的Bean
destroyBeans();
//取消refresh操作
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
}
ioc容器在AbstractApplicationContext#obtainFreshBeanFactory方法中初始化
//org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
3.1、刷新BeanFactory
//org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
//如果已经有容器,销毁容器中的bean,关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建IOC容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//对IOC容器进行定制化
customizeBeanFactory(beanFactory);
//加载BeanDefinition ioc初始化第二步
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
3.1.1、创建IOC容器
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
3.1.1.1、获取父Beanfactory
//AbstractApplicationContext#getInternalParentBeanFactory 这里会返回null
protected BeanFactory getInternalParentBeanFactory() {
return (getParent() instanceof ConfigurableApplicationContext) ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent();
}
ClasspathXmlApplicationContext传入的parent是null
private ApplicationContext parent;
public ApplicationContext getParent() {
return this.parent;
}
3.1.1.1.2、创建DefaultListableBeanFactory
public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
调用父类 AbstractAutowireCapableBeanFactory
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
this();
setParentBeanFactory(parentBeanFactory);
}
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
调用父类
public AbstractBeanFactory() {
}
设置父Beanfactory
public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
}
this.parentBeanFactory = parentBeanFactory;
}
这一步构造了ioc容器,DefaultListableBeanFactory
3.2、定制化ioc容器
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//是否允许beanDefinition重写
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//是否允许循环依赖
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
上面是ioc初始化的第一步,初始化资源,Beanfactory,获取Bean定位