spring

##1. ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) {
    //null
    super(parent);
    setConfigLocations(configLocations);
    //默认true
    if (refresh) {
        refresh();
    }
复制代码

###1.1 super()一路向上调用,直到AbstractApplicationContext

public AbstractApplicationContext(ApplicationContext parent) {
        this();
        this.setParent(parent);
    }
复制代码
public AbstractApplicationContext() {
        this.logger = LogFactory.getLog(this.getClass());
        this.id = ObjectUtils.identityToString(this);
        this.displayName = ObjectUtils.identityToString(this);
        this.beanFactoryPostProcessors = new ArrayList();
        this.active = new AtomicBoolean();
        this.closed = new AtomicBoolean();
        this.startupShutdownMonitor = new Object();
        this.applicationListeners = new LinkedHashSet();
        this.resourcePatternResolver = this.getResourcePatternResolver();
    }
复制代码
protected ResourcePatternResolver getResourcePatternResolver() {
        //路径解析
        return new PathMatchingResourcePatternResolver(this);
    }
复制代码
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
		Assert.notNull(resourceLoader, "ResourceLoader must not be null");
		this.resourceLoader = resourceLoader;
	}
复制代码

PathMatchingResourcePatternResolver支持Ant风格的路径解析。 ###1.2 设置配置文件路径:ClassPathXmlApplicationContext.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) {
                //将占位符(placeholder)解析成实际的地址
                this.configLocations[i] = this.resolvePath(locations[i]).trim();
            }
        } else {
            this.configLocations = null;
        }
    }
复制代码

AbstractRefreshableConfigApplicationContext.resolvePath()

protected String resolvePath(String path) {
        return this.getEnvironment().resolveRequiredPlaceholders(path);
    }
复制代码

####1.2.1 Environment接口 上一步resolvePath(String path)中用到了getEnvironment().resolveRequiredPlaceholders(path),Environment接口主要包含了针对Property的一些操作:

  • 首先getEnvironment()获取Environment:如果Environment为null则new一个StandardEnvironment出来: AbstractApplicationContext.createEnvironment()
protected ConfigurableEnvironment createEnvironment() {
		return new StandardEnvironment();
	}
复制代码

而StandardEnvironment继承于AbstractEnvironment,AbstractEnvironment中包含MutablePropertySources属性:

public abstract class AbstractEnvironment implements ConfigurableEnvironment {
      private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);
      //PropertyResolver : Environment的顶层接口,主要提供属性检索和解析带占位符的文本。
      private final ConfigurablePropertyResolver propertyResolver =
			new PropertySourcesPropertyResolver(this.propertySources);
      public AbstractEnvironment() {
                //这个抽象方法在StandardEnvironment中实现
		customizePropertySources(this.propertySources);
		if (this.logger.isDebugEnabled()) {
			this.logger.debug(format(
					"Initialized %s with PropertySources %s", getClass().getSimpleName(), this.propertySources));
		}
	}
    }
复制代码

StandardEnvironment中实现抽象方法:

        @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()));
	}
复制代码

getSystemProperties():

    try {
		return (Map) System.getProperties();
		}catch (AccessControlException ex) {
                ...}
复制代码

###1.2.2 Properties接口 System.getProperties():

private static Properties props;
public static Properties getProperties() {
        //首先经过安全管理器的检查
        SecurityManager sm = getSecurityManager();
        if (sm != null) {
            sm.checkPropertiesAccess();
        }
        return props;
    }
复制代码

Properties类:

public
class Properties extends Hashtable<Object,Object> {
      public synchronized Object setProperty(String key, String value) {
        return put(key, value);
    }
    public String getProperty(String key) {
        Object oval = super.get(key);
        String sval = (oval instanceof String) ? (String)oval : null;
        return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
    }
}
复制代码

由此段代码可以看出Properties继承于Hashtable,以键值对的方式实现。

  • 回到上面的路径解析问题: this.getEnvironment().resolveRequiredPlaceholders(path)就是启动了AbstractEnvironment.resolveRequiredPlaceholders:
@Override
	public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
		return this.propertyResolver.resolveRequiredPlaceholders(text);
	}
复制代码

进而启动AbstractEnvironment.propertyResolver.resolveRequiredPlaceholders(text),而AbstractEnvironment.propertyResolver:

private final ConfigurablePropertyResolver propertyResolver =
			new PropertySourcesPropertyResolver(this.propertySources);
复制代码

PropertySourcesPropertyResolver继承于AbstractPropertyResolver,则最终触发AbstractPropertyResolver.resolveRequiredPlaceholders(String text):

@Override
	public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
                //初始化占位符解析器
		if (this.strictHelper == null) {
			this.strictHelper = createPlaceholderHelper(false);
		}
                //调用doResolvePlaceholders,进行替换占位符具体值
		return doResolvePlaceholders(text, this.strictHelper);
	}
复制代码
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
                //替换占位符具体值
		return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
			@Override
			public String resolvePlaceholder(String placeholderName) {
                                //通过key获取占位符对应的String类型具体值
				return getPropertyAsRawString(placeholderName);
			}
		});
	}
复制代码
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
		Assert.notNull(value, "'value' must not be null");
                //替换占位符逻辑
		return parseStringValue(value, placeholderResolver, new HashSet<String>());
	}
复制代码

###1.3 refresh AbstractApplicationContext中的refresh()方法是spring初始化中的核心方法,在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。 AbstractApplicationContext.refresh():

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 设置启动时间,是否激活标识位,初始化属性源(property source)配置
			prepareRefresh();

			// 创建beanFactory(过程是根据xml为每个bean生成BeanDefinition并注册到生成的beanFactory)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}
复制代码

####加载类 obtainFreshBeanFactory()方法实现了类的装载,AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类AbstractRefreshableApplicationContext的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程: AbstractApplicationContext.obtainFreshBeanFactory():

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}
复制代码

AbstractRefreshableApplicationContext.refreshBeanFactory():

@Override
	protected final void refreshBeanFactory() throws BeansException {
        //从这里可以看出,如果存在容器则销毁并关闭
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
            //new出一个新的DefaultListableBeanFactory作为IoC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
            //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等
			customizeBeanFactory(beanFactory);
            //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器(AbstractXmlApplicationContext)
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
复制代码

AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory):

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		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.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值