接上篇文章,上篇讲到了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>
总结:这里其实就干了一件事,验证是否存在需要的属性。