实现自己的IOC容器——Winter(三)Spring原生ApplicationContext机制梳理
在继续实现WinterApplicaitonContext之前,梳理一下Spring原生容器的机制。主要是注解驱动容器AnnotationConfigApplicationContext。
一、整体流程
AC是完全体的容器,注解驱动的AC完全体是AnnotationConfigApplicationContext。这个ACAC有4种构造方法,可以传入多个配置类、scan的包名或者什么都不传。无论是哪种方式,它们都需要先创建一个BeanFactory,这是Bean管理的核心。它用的就是BF的完全体DefaultListableBeanFactory。之后,它还需要两个工具,AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。Reader可以解析配置类,Scanner可以扫描目录,将目录中的配置类转成BeanDefinition。
- 当传入的是目录时,Scanner可以扫描目录中配置类,转成BeanDefinition并注册进容器。
- 当创建AC传入的是配置类时,Reader可以解析配置类,转成BeanDefinition并注册进容器。这里传的配置类是必须要有ComponentScan注解的,这样它就包含了Scanner的功能。包括后面Springboot启动的时候也是用的这种方式。
注:什么是配置类?就是可以用容器管理的Bean,就是@Component、@Service、@Controller、@Repository 等注解的类。
1. 构造函数
首先会调用父类的构造方法创建一个DefaultListableBeanFactory。其次,前面说AC在构造的时候会设置两个工具Reader和Scanner,这两个工具在构造的时候也会做一些准备工作。
首先是Reader,它会注册7个组件,将它们的BeanDefinition放入容器:值得关注的前3个,一个BeanFactoryPostProcessor和两个BeanPostProcessor。
- ConfigurationClassPostProcessor:BFPP。注解驱动核心,用来解析 @Configuration、@ComponentScan、@Import 等注解的核心引擎
- AutowiredAnnotationBeanPostProcessor:BPP,用于处理 @Autowired、@Value 注入
- CommonAnnotationBeanPostProcessor:BPP,用来处理 @Resource、@PostConstruct 等 JSR-250 注解
- EventListenerMethodProcessor:处理 @EventListener 事件监听。
- DefaultEventListenerFactory:支持事件监听器的工厂。
- AnnotationAwareOrderComparator:注解感知的排序器,用于处理 @Order。
- ContextAnnotationAutowireCandidateResolver:增强 @Qualifier 和注解依赖解析
其次是Scanner,它在构造方法中会设置includeFilters这个属性,用于指定哪些注解标记的类会被扫描为Bean。一般是@Component注解。(@Service、@Controller、@Resource、@Configuration这些属于Componet的派生注解,也会生效。@ComponentScan这个是单独的注解)
2. 对配置类的解析register
解析用的Reader的register方法。这个方法做了什么?
- 首先新建一个BeanDefinition,然后将配置的class设置进去。再利用反射获取类上的所有注解(类中的@Bean这样的注解不会解析),并放到BD的AnnotationMetadata中
- 解析配置类上的@Lazy、@Primary、@DependsOn、@Role 和 @Description,如果有,就将BD中的属性设置为true
- 将这个配置类注册进容器
解析之后,就是将配置类的BD放进了容器,接下来就要来填充ApplicaitonContext了,也就是通过refresh方法。
3. 刷新容器refresh
refresh方法的功能彻底开启AC容器的开关,是Spring的一个核心方法,它做了哪些事情?具体流程就是下面的12个方法,其中有一些不太重要的方法就不会分析了。
- prepareRefresh:准备工作,设置容器的启动时间、状态、事件集合
- obtainFreshBeanFactory:如果是xml驱动,这里会创建BeanFactory和解析加载Bean。注解驱动这里是空实现。注解驱动的准备工作在构造方法时就已经做了。
- prepareBeanFactory:配置BeanFactory,因为前面创建的BF是完全空的,为了让它能够工作,这里要设置一下。它做的事情比较杂。比如给BF配置一些工具,比如类加载器、SpEL解析器、属性编辑器注册器;添加一下BPP如ApplicationContextAwareProcessor、ApplicationListenerDetector(事件相关)等等。它还会把BeanFactory和ApplicaitonContext也注册进容器
- postProcessBeanFactory:BeanFactory的后处理,默认空实现。拓展用的,可以自己对配置好的BF再处理一下。
- invokeBeanFactoryPostProcessors:在工厂创建好了之后,用BFPP处理BeanDefinition(处理之前会取出所有BFPP然后进行排序等等)。最重要的就是ConfigurationClassPostProcessor,也是注解驱动唯一一个BFPP。
- registerBeanPostProcessors:这里会获取到前面注册过的BPP,进行排序。其中重要的是AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor。
- initMessageSource:国际化支持,不关注
- initApplicationEventMulticaster:初始化事件广播器,不关注
- onRefresh:初始化特殊的Bean,Spring是空实现。Springboot会在这里创建Tomcat服务器并启动
- registerListeners:注册事件监听,不关注
- finishBeanFactoryInitialization:完成BeanFactory初始化。会冻结所有的 BeanDefinition,并创建所有需要管理的非懒加载的Bean。
- finishRefresh:完成刷新。因为Bean已经完全创建好了,会清理所有缓存;发布事件,表示容器创建成功等等。
二、核心类BFPP和BPP
BFPP其实就只有一个ConfigurationClassPostProcessor,在前面的文章已经梳理过了。BPP主要是AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor。它们的功能类似,只是处理的是不同的注解。前者用来处理Spring 自家的自动装配注解(如 @Autowired、@Value),后者专门负责 Java 官方标准(JSR-250)定义的通用注解(如 @Resource、@PostConstruct、@PreDestroy)。后续继续分析。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)