image.png

一、整体流程

1、先创建容器
2、加载配置文件,封装成 BeanDefinition
3、调用执行 BeanFactoryPostProcessor
准备工作:
beanPosytProcessor
准备监听器,事件,广播器
4、实例化(为bean的属性设置值和对其他bean引用)
5、初始化
6、获取到完整对象

二、源码解读

实例代码

  1. public static void main(String[] args) {
  2. // 获取核心容器
  3. ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //更常用
  4. // ApplicationContext ac = new FileSystemXmlApplicationContext("/Users/superking/Desktop/bean.xml");
  5. // 根据id获取bean对象( 以下两种方式强转 可以直接强转,也可以获取字节码.class)
  6. IAccountService as = (IAccountService) ac.getBean("accountService");
  7. IAccountDao accountDao = ac.getBean("accountDao",IAccountDao.class);
  8. System.out.println(as);
  9. System.out.println(accountDao);
  10. }
  11. }

1、创建容器

1、debug进入 ClassPathXmlApplicationContext
2、首先是初始化一些父类方法(super),然后是设置配置文件路径setConfigLocations
�最后进入 refresh 方法
image.png
3、进入 refresh 的obtainFreshBeanFactory

  1. @Override
  2. public void refresh() throws BeansException, IllegalStateException {
  3. synchronized (this.startupShutdownMonitor) {
  4. // Prepare this context for refreshing.
  5. prepareRefresh();
  6. // Tell the subclass to refresh the internal bean factory.
  7. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  8. // Prepare the bean factory for use in this context.
  9. prepareBeanFactory(beanFactory);
  10. try {
  11. // Allows post-processing of the bean factory in context subclasses.
  12. postProcessBeanFactory(beanFactory);
  13. // Invoke factory processors registered as beans in the context.
  14. invokeBeanFactoryPostProcessors(beanFactory);
  15. // Register bean processors that intercept bean creation.
  16. registerBeanPostProcessors(beanFactory);
  17. // Initialize message source for this context.
  18. initMessageSource();
  19. // Initialize event multicaster for this context.
  20. initApplicationEventMulticaster();
  21. // Initialize other special beans in specific context subclasses.
  22. onRefresh();
  23. // Check for listener beans and register them.
  24. registerListeners();
  25. // Instantiate all remaining (non-lazy-init) singletons.
  26. finishBeanFactoryInitialization(beanFactory);
  27. // Last step: publish corresponding event.
  28. finishRefresh();
  29. }
  30. catch (BeansException ex) {
  31. if (logger.isWarnEnabled()) {
  32. logger.warn("Exception encountered during context initialization - " +
  33. "cancelling refresh attempt: " + ex);
  34. }
  35. // Destroy already created singletons to avoid dangling resources.
  36. destroyBeans();
  37. // Reset 'active' flag.
  38. cancelRefresh(ex);
  39. // Propagate exception to caller.
  40. throw ex;
  41. }
  42. finally {
  43. // Reset common introspection caches in Spring's core, since we
  44. // might not ever need metadata for singleton beans anymore...
  45. resetCommonCaches();
  46. }
  47. }
  48. }

依次进入
image.png
image.png
这里的 createBeanFactory 创建的是一个默认容器
image.png

2、加载配置文件

image.png
经过 loadBeanDefinitions 载入bean之后,beanDefinitionMap的size变为了2。
到这里之后,完成了 配置文件 bean.xml 中的bean的加载,但是还没有值。
image.png
loadBeanDefinitions 结束之后回到 refresh 方法,进行下一步 prepareBeanFactory ,这里会完成 bean工厂 参数的赋值操作
image.png
image.png

3、调用执行 BeanFactoryPostProcessor

调用各种 beanFactory处理器,例如 PlaceholderConfigurerSupport
image.png

4、准备工作

registerBeanPostProcessors 注册 bean 处理器,这里只是注册功能,真正调用的是 getBean 方法。
image.png
initMessageSource(); 方法,为上下文初始化 message原,即不同语言的消息体,国际化操作。
initApplicationEventMulticaster();初始化事件监听多路广播器
onRefresh();留给子类初始化其他的bean
�registerListeners();在所有注册的bean中查找listener bean,注册到消息广播器中。

5、实例化

通过 方法 finishBeanFactoryInitialization() 初始化所有非懒加载的单例对象。
image.png
进入 finishBeanFactoryInitialization() 直接到最后一行(代码太多不细看)看到 preInstantiateSingletons()。
image.png
经过层层判断,最后如果beanName对应的bean不是FactoryBean,只是普通的bean,则通过beanName获取bean实例。
image.png
进入 getBean—>doGetBean,在 doGetBean 方法中会先获取单例对象,如果获取不到,则会进行创建。
image.png
获取单例对象 getSingleton (此处可以联想到单例模式 单例模式
image.png
�创建 bean,doGetBean -> createBean -> doCreateBean -> createBeanInstance
image.png
在 createBeanInstance 的最后一行(只有无参构造方法,前面的方法都用不了,最后一行创建无参构造器) instantiateBean(beanName, mbd)
image.png
image.png
继续进去,看到了久违的 constructorToUse = clazz.getDeclaredConstructor();
到这里可以回顾下
2、反射进行实例化操作
image.png
�继续走,看到后面 BeanUtils.instantiateClass(constructorToUse),最后newInstance(),到这里完成了对象的创建,但是对象还没有值。
image.png
对象创建结束之后会到方法 doCreateBean ,在这里调用 populateBean 用于填充值(org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean),然后 调用方法initializeBean 初始化 bean。

6、初始化

6.1 第一次初始化

在 initializeBean 方法内部,(第一次初始化 aware)执行 invokeAwareMethods(Aware接口处理器,调用 BeanNameAware、BeanClassLoaderAware、beanFactoryAware)
image.png
image.png

6.2 第二次初始化

接着继续初始化(第二次初始化 aware),调用 applyBeanPostProcessorsBeforeInitialization 方法。
image.png
�使用里面的 BeanPostProcessor.postProcessBeforeInitialization
image.png
在进入 postProcessBeforeInitialization 的方法 invokeAwareInterfaces
org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
image.png
�结束之后 得到完整的bean

6.3 为什么需要初始化两次

image.png
因为 beanFactory 和 applicationContext 是两套分支,所以spring会使用 invokeAwareMethods(初始化 beanFactory) 和 applyBeanPostProcessorsBeforeInitialization(初始化 applicationContext) 各初始化一次。
image.png

三、AnnotationConfigApplicationContext

�参考 https://blog.csdn.net/weixin_42412601/article/details/104784111