Spring IOC初始化1--定位

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定位

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值