spring-源码-AnnotationConfigApplicationContext-创建分析-5

tech2025-07-27  2

文章目录

前言后顾之前调用refresh()调用prepareRefresh()扩展阅读initPropertySources()getEnvironment() 后言

前言

这个方法是重中之重!!! 慢慢啃吧,这里只是分析几个简单的方法,需要说明的是不同的 ApplicationContext实现可能略有不同,比如springboot 中的是AnnotationConfigServletWebServerApplicationContext而我用于研究源码的是AnnotationConfigApplicationContext

而本文仅仅讲解prepareRefresh() 这一个方法后续文章会对方法一个一个的分析

后顾之前

先回顾一下容器启动器都 创建了或者设置了那些属性,需要说明的是也就是说AnnotationConfigApplicationContext

源码-1:ApplicationContext-1源码-2:ApplicationContext-2源码-3:ApplicationContext-3源码-4:ApplicationContext-4

调用refresh()

public AnnotationConfigApplicationContext(Class<?>... componentClasses) { //刷新容器,需要注意的是 refresh() 是父类的方法 refresh(); } 实现 @Override public void refresh() throws BeansException, IllegalStateException { // 先加个锁. 防止这个方法还没执行完,其他的也开始搞了. synchronized (this.startupShutdownMonitor) { //个方法是做准备工作的,记录容器的启动时间、标记“已启动”状态、 prepareRefresh(); // 获取 beanFactory ,也就是说获取的是 DefaultListableBeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //可以说是对 DefaultListableBeanFactory 进行一些初始化的配置 prepareBeanFactory(beanFactory); try { //beanFactory 的后置处理器,在BeanFactory初始化之后执行的,这个后置处理是空的,需要子类去实现 postProcessBeanFactory(beanFactory); // BeanFactory 的后置处理器,在 BeanFactory 初始化之后执行的 invokeBeanFactoryPostProcessors(beanFactory); // 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程 registerBeanPostProcessors(beanFactory); // 初始化MessageSource组件(做国际化功能;消息绑定,消息解析) initMessageSource(); // 初始化事件派发器 initApplicationEventMulticaster(); // 空方法,可以用于子类实现在容器刷新时自定义逻辑, onRefresh(); // 注册时间监听器,将所有项目里面的ApplicationListener注册到容器中来 registerListeners(); // 实例化所有的单例Bean,懒加载除外,也就是说被修饰过@Lazy的除外 finishBeanFactoryInitialization(beanFactory); // 完成BeanFactory的初始化创建工作,IOC容器就创建完成; finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }

调用prepareRefresh()

就是对容器进行初始化一些属性填充

protected void prepareRefresh() { // 记录开始时间 this.startupDate = System.currentTimeMillis(); //容器是否关闭 this.closed.set(false); //容器是否激活 this.active.set(true); // 自定义的一些属性,由子类去实现,比如 springboot... initPropertySources(); // 获取 Environment,然后去校验 属性 // 而 Environment 创建是由 AnnotatedBeanDefinitionReader 去创建的.. // 也就说这里是获取 环境 并对参数进行校验~~ getEnvironment().validateRequiredProperties(); // 获取本地环境的一些监听器 if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // 将本地应用程序侦听器重置为预刷新状态。 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } //早期应用的一些事件 this.earlyApplicationEvents = new LinkedHashSet<>(); }

扩展阅读

initPropertySources()

这个方法是留给子类去初始化的比如: springboot中GenericWebApplicationContext就对该类进行一个重写…

protected void initPropertySources() { // 获取环境 ConfigurableEnvironment env = getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { // 初始化一些内容.. 这里不深究 ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null); } }

getEnvironment()

我们可以针对环境做一个配置比如: 设置环境设置正在激活的 profile

@ComponentScan public class PrepareRefreshContext { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); ConfigurableEnvironment environment = context.getEnvironment(); // 配置 profiles environment.setActiveProfiles("test"); context.register(PrepareRefreshContext.class); // 在这里调用刷新容器,为什么呢?如果传入了配置类,它内部就自动初始化完成了,所以需要在刷新容器前进行配置~~ context.refresh(); User bean = context.getBean(User.class); System.out.println(bean); } } @Profile("dev") @Component class User { }

后言

可以看到 这个方法并没有帮我们做过多的事情,如果单纯从方法名来看 是准备刷新,这里准备刷新 可以理解为容器启动的一些初始化…比如记录容器启动事件、环境参数校验等

最新回复(0)