知道了IOC启动的需要多个阶段,接下来学习下第一个阶段 AbstractApplicationContext # prepareRefresh() 都干了啥!
工作内容
这个阶段主要是准备工作:
- 设置启动日期,启动标志;
- 给子类扩展点,自定义处理环境变量;
- 验证环境变量是否都已经准备好了;
- 处理事件监听器们;
spring-web | org.springframework.context.support.AbstractApplicationContext#refresh
protected void prepareRefresh() {
// 记录启动时间,设置状态表示开始启动
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 留给子类自定义处理
initPropertySources();
// 检测下需要验证的属性是否都已经正确的放入当前环境中
getEnvironment().validateRequiredProperties();
// 准备相关监听器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
this.earlyApplicationEvents = new LinkedHashSet<>();
}
代码验证环境变量
可以重写这个 initPropertySources() 来测试下工作。
准备个 bean.xml 及对应的实体
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"https://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="user" class="cn.lichenghao.entity.User">
<property name="name">
<value>Rod</value>
</property>
<property name="age">
<value>31</value>
</property>
</bean>
</beans>
测试用对象。
package cn.lichenghao.entity;
public class User {
private String name;
private String age;
public User() {
System.out.println("User construct run~~~");
}
public User(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
public void sayHello() {
System.out.println("hello world!");
}
}
然后先加载测试。
/**
* 编译后的第一个Hello World
*
* @author chenghao.li
*/
public class App {
public static void main(String[] args) {
// 根据配置文件加载bean
ClassPathXmlApplicationContext classPathXmlApplicationContext
= new ClassPathXmlApplicationContext("bean.xml");
User bean = classPathXmlApplicationContext.getBean(User.class);
bean.sayHello();
}
}
自定义个context。
/**
* 自定义
*
* @author chenghao.li
*/
public class MyApplicationContext extends ClassPathXmlApplicationContext {
public MyApplicationContext(String configLocation) throws BeansException {
super(configLocation);
}
@Override
protected void initPropertySources() {
getEnvironment().setRequiredProperties("ABC");
super.initPropertySources();
}
}
再测试下。
/**
* 编译后的第一个Hello World
*
* @author chenghao.li
*/
public class App {
public static void main(String[] args) {
// 自定义加载
MyApplicationContext myApplicationContext = new MyApplicationContext("bean.xml");
User mybean = myApplicationContext.getBean(User.class);
mybean.sayHello();
}
}
这个时候就会报错,因为我们的系统环境变量中并没有 ABC。
Exception in thread "main" org.springframework.core.env.MissingRequiredPropertiesException:
The following properties were declared as required but could not be resolved: [ABC]
添加个环境变量 ABC,再进行测试。
/**
* 编译后的第一个Hello World
*
* @author chenghao.li
*/
public class App {
public static void main(String[] args) {
System.setProperty("ABC", "1234");
// 自定义加载
MyApplicationContext myApplicationContext = new MyApplicationContext("bean.xml");
User mybean = myApplicationContext.getBean(User.class);
mybean.sayHello();
}
}