spring4.2.9 java项目环境下ioc源码分析(二)——refresh之prepareRefresh方法

接上篇文章,上篇讲到了refresh之前,做了一些什么事。接下来就是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.
			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) {
				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.
				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();
			}
		}
	}

prepareRefresh()方法做了一些什么事情呢,从注释上看是准备上下文刷新的工作。进入其方法
protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}

		// Initialize any placeholder property sources in the context environment
		initPropertySources();

		// Validate that all properties marked as required are resolvable
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
	}

这里主要做了设置其启动日期startupDate和活动标志active以及执行任何属性源初始化initPropertySources。但是这里initPropertySources是空方法,是第一个扩展点,如果需要自己实现自己的ApplicationContext,并且在验证之前为系统属性设置一些值可以在子类中实现此方法。
validateRequiredProperties是验证是否系统环境中有RequiredProperties参数值,其代码如下
public void validateRequiredProperties() {
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) {
				ex.addMissingRequiredProperty(key);
			}
		}
		if (!ex.getMissingRequiredProperties().isEmpty()) {
			throw ex;
		}
	}

如果前面设置了环境需要的属性值,但是系统环境中没有这里会报错。这里用不上,如果你自己实现一个ApplicationContext去继承AbstractApplicationContext,并且设置了getEnvironment().setRequiredProperties("11")必须的属性11,但是在系统环境中没有会报错。
下面是个简单的例子:
public class Test {

	public static void main(String[] args) {
		MyApplicationContext context=new MyApplicationContext();
	}
}
class MyApplicationContext extends AbstractApplicationContext{
	public MyApplicationContext() {
		getEnvironment().setRequiredProperties("11");
		refresh();
	}
	@Override
	protected void refreshBeanFactory() throws BeansException, IllegalStateException {
	}
	@Override
	protected void closeBeanFactory() {
	}
	@Override
	public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException {
		return null;
	}
}

MyApplicationContext继承了AbstractApplicationContext并且构造函数中为环境设置了需要的属性‘11’,但是很明显系统属性里不存在这时会报错
Exception in thread "main" org.springframework.core.env.MissingRequiredPropertiesException: 
	The following properties were declared as required but could not be resolved: [11]
	at org.springframework.core.env.AbstractPropertyResolver.validateRequiredProperties(AbstractPropertyResolver.java:123)
	at org.springframework.core.env.AbstractEnvironment.validateRequiredProperties(AbstractEnvironment.java:515)
	at org.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:589)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:510)
	at com.pactera.test.MyApplicationContext.<init>(Test.java:22)
	at com.pactera.test.Test.main(Test.java:16)

很明显根本找不到11属性值,报错MissingRequiredPropertiesException异常。
如果把main方法改一下,加上系统属性如下:
public static void main(String[] args) {
		Properties properties = System.getProperties();
		properties.setProperty("11", "applicationContext.xml");
		MyApplicationContext context=new MyApplicationContext();
	}

就不会报上面的异常(虽然还是报错,因为自己没有加进配置文件)。
回到prepareRefresh方法中,最后一行代码,新建一个LinkedHashSet<ApplicationEvent>
总结:这里其实就干了一件事,验证是否存在需要的属性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackson陈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值