• 三哥


该文章的内容有视频讲解,地址👉:​​点我直达​

一、refresh 方法之 prepareRefresh()

方法源码

org.springframework.context.support.AbstractApplicationContext#prepareRefresh

protected void prepareRefresh() {
// 纪录启动时间
this.startupDate = System.currentTimeMillis();
// spring 标记为未关闭
this.closed.set(false);
// spring 当前激活状态
this.active.set(true);

// 打印一些日志
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}

// Initialize any placeholder property sources in the context environment
// 空方法
initPropertySources();

// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
// 校验 xml 配置文件
getEnvironment().validateRequiredProperties();

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 初始化 applicationListeners 监听容器
this.earlyApplicationEvents = new LinkedHashSet<>();
}

总结一下这个方法干了些啥:

  1. 记录启动时间,并且设置 Spring 为激活状态
  2. 校验 xml 配置文件
  3. 初始化 applicationListeners 监听容器

二、refresh 方法之 obtainFreshBeanFactory()

进入源码

org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新 BeanFactory,并执行加载和解析配置文件的操作
refreshBeanFactory();
// 获取 beanFactory 并返回
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

这里显然重要的方法在 ​​refreshBeanFactory​​ 处,但结合我们的启动方式为 AnnotationConfigApplicationContext 类,所以我们会来到下面源码

org.springframework.context.support.GenericApplicationContext#refreshBeanFactory

protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}

嗯,很简单的几行代码,判断了是否为重复刷新及设置 Bean 工厂的序列化 id 就完事了。

那我们的配置文件解析呢!

这里不卖关子,因为我们是注解配置类方式启动,所以不需要执行解析配置文件并加载 Bean 定义等操作。但如果我们是 ClassPathXmlApplicationContext 方式启动 Spring 那么对应的 refreshBeanFactory 方法则如下:

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

protected final void refreshBeanFactory() throws BeansException {
// 判断是否存在beanFactory
if (hasBeanFactory()) {
// 注销所有的单例 bean
destroyBeans();
// 重置beanFactory
closeBeanFactory();
}
try {
// 创建一个新的BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 指定序列化id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
beanFactory.setSerializationId(getId());
// 定制BeanFactory
customizeBeanFactory(beanFactory);
// 加载 bean 定义(重点!!!!!!!!!!!!!)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

总结一下这个方法干了些啥:

  1. 判断 beanFactory 是否存在,存在则销毁
  2. 创建一个新的 beanFactory 并设置相关属性
  3. 加载 Bean 定义(​​重点​​)

而至于这个 loadBeanDefinitions 方法我不打算在这里进行分析,因为本次我分析的是注解方式启动,所以不会去解析 XML 进行 Bean 定义的加载。

​后续如果有时间可以单独拿出来分析分析​​。


三、refresh 方法之 prepareBeanFactory

方法源码

org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 设置上下文环境的启动类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置解析器,用于解析bean的定义中出现的spel表达式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加一个属性编辑注册器,该接口有一个方法registerCustomEditors,用来设置自定义转换器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
// 部署一个bean的后置处理器ApplicationContextAwareProcessor,用于将spring的环境信息注入到实例化的bean中
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// bean在初始化时,如果bean含有某些属性(比如ResourceLoaderAware),则该属性不会被依赖注入
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 在普通工厂中,如果一个bean有BeanFactory.class属性,那么这个属性会被设置为beanFactory
// 消息源会被注册(会被自动装配)为一个bean
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.
// 早期注册的post-processor将会被添加作为检测内部的应用监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.
// aop的代码织入,如果发现beanFactory中包含loadTimeWeaver的bean,则添加一个LoadTimeWeaverAwareProcessor
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
// 类型匹配设置一个暂时的类加载器
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

// Register default environment beans.
// 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}

// 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

总结一下这个方法干了些啥:

  1. 向 BeanFactory 中设置一些属性(类加载器、解析spel表达式、自定义转换器等)
  2. 向 BeanFactory 中添加一些 Bean(XXXAware、监听器等)
  3. 忽略某些属性类型不被自动装配

四、refresh 方法之 postProcessBeanFactory

方法源码

org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

显然这是要给空方法,后续 Spring 可能会对其扩展或者其子类进行实现。

比如我们自己继承 AnnotationConfigApplicationContext 类,并重写 postProcessBeanFactory 方法。

案例:

public class MyApplicationContext extends AnnotationConfigApplicationContext {

// 此处完美继承父类的功能
public MyApplicationContext(Class<?>... componentClasses) {
super(componentClasses);
}

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 此处我们获取到了beanFactory对象
// 通过调用beanFactory的API可以进行任何的操作。
if (beanFactory instanceof DefaultListableBeanFactory){
System.out.println(true);
}
}
}

测试

public class SpringDemo {
public static void main(String[] args) {
// 此处我随便注册了一个类
MyApplicationContext myApplicationContext = new MyApplicationContext(Config.class);
Phone phone = myApplicationContext.getBean(Phone.class);
}
}



  • 由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。


  • 感谢您的阅读,十分欢迎并感谢您的关注。