spring refresh()方法详解1之prepareRefresh()

1.方法代码如下:

	/**
	 * 准备工作
	 */
	protected void prepareRefresh() {
		//记录初始化开始时间
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);	//context是否关闭的标志,设置为false
		this.active.set(true);	//context是否激活的标志,设置为true

		if (logger.isDebugEnabled()) {	//记录日志
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		//留给子类实现的空方法
		initPropertySources();

		 /** AbstractPropertyResolver类的requiredProperties是个集合,
		  * 在下面的validateRequiredProperties方法中,都要拿requiredProperties中的元素作为key去检查是否存在对应的环境变量,
		  * 如果不存在就抛出异常
		  */
		getEnvironment().validateRequiredProperties();

		// 初始化earlyApplicationListeners容器 --LinkedHashSet
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// 清空applicationListeners容器  并将earlyApplicationListeners中的数据全部添加进来
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// 初始化earlyApplicationEvents容器  --LinkedHashSet
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

涉及到的各个属性定义如下:

        private long startupDate;
        /** context是否激活的标志 */
	private final AtomicBoolean active = new AtomicBoolean();

	/** context是否关闭的标志 */
	private final AtomicBoolean closed = new AtomicBoolean();

	@Nullable
	private Set<ApplicationListener<?>> earlyApplicationListeners;

	/** Statically specified listeners. */
	private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

	/** Statically specified listeners. */
	private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

	@Nullable
	private Set<ApplicationEvent> earlyApplicationEvents;

2.initPropertySources

这是一个留给子类实现的空方法,我们使用时可以重写该方法,在容器启动前,添加一些自定义校验或者进行其他处理,原方法代码如下:

	/**
	 * <p>Replace any stub property sources with actual instances.
	 * @see org.springframework.core.env.PropertySource.StubPropertySource
	 * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
	 */
	protected void initPropertySources() {
	}

2.1 initPropertySources使用举例

1.我们可以自定义一个类继承ClassPathXmlApplicationContext,并重写initPropertySources方法,代码如下:

/**
 * 自定义一个容器启动类继承ClassPathXmlApplicationContext 并重写其initPropertySources方法
 */
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
	
	public MyClassPathXmlApplicationContext(String string) {
		super(string);
	}

	@Override
	public void initPropertySources(){
		ConfigurableEnvironment env = getEnvironment();
		env.setRequiredProperties("Path");
		String property = env.getRequiredProperty("Path");
		//打印,方便观察
		Stream.of(property.split(";")).filter(x -> x.toUpperCase().contains("JAVA\\JDK")).forEach(System.out::println);
	}
}

2.写一个小demo用我们自定义的类启动容器。

public class Demo {

	public static void main(String[] args) {
		MyClassPathXmlApplicationContext context = new MyClassPathXmlApplicationContext("spring.xml");
	}
	
}

3.在容器启动时,控制台会多打印如下图:

3.getEnvironment与validateRequiredProperties详解

1.getEnvironment

	/**
	 * 获取环境属性
	 */
	@Override
	public ConfigurableEnvironment getEnvironment() {
		if (this.environment == null) {
	        // 1.创建Environment
			this.environment = createEnvironment();	
		}
		return this.environment;
	}

	/**
	 * 创建Environment
	 */
	protected ConfigurableEnvironment createEnvironment() {
		return new StandardEnvironment();
	}

2.validateRequiredProperties

	@Override
	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;
		}
	}

注:validateRequiredProperties方法的代码实现位于AbstractPropertyResolver类中

猜你喜欢

转载自blog.csdn.net/luo_mu_hpu/article/details/107315662