知道了IOC启动的需要多个阶段,接下来学习下第一个阶段 AbstractApplicationContext # prepareRefresh() 都干了啥!

工作内容

这个阶段主要是准备工作:

  • 设置启动日期,启动标志;
  • 给子类扩展点,自定义处理环境变量;
  • 验证环境变量是否都已经准备好了;
  • 处理事件监听器们;

spring-web | org.springframework.context.support.AbstractApplicationContext#refresh

  1. protected void prepareRefresh() {
  2. // 记录启动时间,设置状态表示开始启动
  3. // Switch to active.
  4. this.startupDate = System.currentTimeMillis();
  5. this.closed.set(false);
  6. this.active.set(true);
  7. if (logger.isDebugEnabled()) {
  8. if (logger.isTraceEnabled()) {
  9. logger.trace("Refreshing " + this);
  10. }
  11. else {
  12. logger.debug("Refreshing " + getDisplayName());
  13. }
  14. }
  15. // 留给子类自定义处理
  16. initPropertySources();
  17. // 检测下需要验证的属性是否都已经正确的放入当前环境中
  18. getEnvironment().validateRequiredProperties();
  19. // 准备相关监听器
  20. if (this.earlyApplicationListeners == null) {
  21. this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
  22. }
  23. else {
  24. // Reset local application listeners to pre-refresh state.
  25. this.applicationListeners.clear();
  26. this.applicationListeners.addAll(this.earlyApplicationListeners);
  27. }
  28. this.earlyApplicationEvents = new LinkedHashSet<>();
  29. }

代码验证环境变量

可以重写这个 initPropertySources() 来测试下工作。
准备个 bean.xml 及对应的实体

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
  3. "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
  4. <beans>
  5. <bean id="user" class="cn.lichenghao.entity.User">
  6. <property name="name">
  7. <value>Rod</value>
  8. </property>
  9. <property name="age">
  10. <value>31</value>
  11. </property>
  12. </bean>
  13. </beans>

测试用对象。

  1. package cn.lichenghao.entity;
  2. public class User {
  3. private String name;
  4. private String age;
  5. public User() {
  6. System.out.println("User construct run~~~");
  7. }
  8. public User(String name, String age) {
  9. this.name = name;
  10. this.age = age;
  11. }
  12. public String getName() {
  13. return name;
  14. }
  15. public void setName(String name) {
  16. this.name = name;
  17. }
  18. public String getAge() {
  19. return age;
  20. }
  21. public void setAge(String age) {
  22. this.age = age;
  23. }
  24. @Override
  25. public String toString() {
  26. return "User{" +
  27. "name='" + name + '\'' +
  28. ", age='" + age + '\'' +
  29. '}';
  30. }
  31. public void sayHello() {
  32. System.out.println("hello world!");
  33. }
  34. }

然后先加载测试。

  1. /**
  2. * 编译后的第一个Hello World
  3. *
  4. * @author chenghao.li
  5. */
  6. public class App {
  7. public static void main(String[] args) {
  8. // 根据配置文件加载bean
  9. ClassPathXmlApplicationContext classPathXmlApplicationContext
  10. = new ClassPathXmlApplicationContext("bean.xml");
  11. User bean = classPathXmlApplicationContext.getBean(User.class);
  12. bean.sayHello();
  13. }
  14. }

自定义个context。

  1. /**
  2. * 自定义
  3. *
  4. * @author chenghao.li
  5. */
  6. public class MyApplicationContext extends ClassPathXmlApplicationContext {
  7. public MyApplicationContext(String configLocation) throws BeansException {
  8. super(configLocation);
  9. }
  10. @Override
  11. protected void initPropertySources() {
  12. getEnvironment().setRequiredProperties("ABC");
  13. super.initPropertySources();
  14. }
  15. }

再测试下。

  1. /**
  2. * 编译后的第一个Hello World
  3. *
  4. * @author chenghao.li
  5. */
  6. public class App {
  7. public static void main(String[] args) {
  8. // 自定义加载
  9. MyApplicationContext myApplicationContext = new MyApplicationContext("bean.xml");
  10. User mybean = myApplicationContext.getBean(User.class);
  11. mybean.sayHello();
  12. }
  13. }

这个时候就会报错,因为我们的系统环境变量中并没有 ABC。

  1. Exception in thread "main" org.springframework.core.env.MissingRequiredPropertiesException:
  2. The following properties were declared as required but could not be resolved: [ABC]

添加个环境变量 ABC,再进行测试。

  1. /**
  2. * 编译后的第一个Hello World
  3. *
  4. * @author chenghao.li
  5. */
  6. public class App {
  7. public static void main(String[] args) {
  8. System.setProperty("ABC", "1234");
  9. // 自定义加载
  10. MyApplicationContext myApplicationContext = new MyApplicationContext("bean.xml");
  11. User mybean = myApplicationContext.getBean(User.class);
  12. mybean.sayHello();
  13. }
  14. }