Spring源码之bean的解析obtainFreshBeanFactory方法解读

目录前言前言一直以来,只是知道 spring 会解析所有的配置文件(通常我们会放在 resources 目录下),然后将从配置文件中解析到的 bean 定义封装成 BeanDefinition,加载到 IOC 容器中。而不知道其内部是如何解析,执行的,本篇文章将予以揭秘...
摘要由CSDN通过智能技术生成

前言

一直以来,只是知道 Spring 会解析所有的配置文件(通常我们会放在 resources 目录下),然后将从配置文件中解析到的 bean 定义封装成 BeanDefinition,加载到 IOC 容器中。而不知道其内部是如何解析,执行的,本篇文章将予以揭秘

何时解析

要知道 spring 何时去解析配置文件,我们可以断定是在 IOC 容器启动时,那么我们可以根据 IOC 容器启动流程进行找寻

测试类

public class TransactionTest_2 {
   

    public static void main(String[] args) {
   
        /* 初始化启动 spring ioc 容器 */
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
        /* 从 spring ioc 容器中获取一个 bean */
        ProductInfoService productInfoService = (ProductInfoService) applicationContext.getBean("productInfoServiceImpl");
        System.out.println("拿到的Bean为:" + productInfoService);
    }
}

在第五行代码处打上断点,DEBUG 模式去调试

ClassPathXmlApplicationContext 的构造器

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   
	// 调用如下
	this(new String[] {
   configLocation}, true, null);
}

public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
   

	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
   
		refresh();
	}
}

它的核心方法肯定就在 refresh() 方法里面,实际上它调用的是抽象类AbstractApplicationContextrefresh()

refresh() 方法

@Override
public void refresh() throws BeansException, IllegalStateException {
   
	synchronized (this.startupShutdownMonitor) {
   
		
	   /**
		* 刷新上下文环境,初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验
	    */
		prepareRefresh();

		// 该方法会解析所有 spring 配置文件(通常我们会放在 resources 目录下)
		// 将配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		/**
		 * 为上下文准备BeanFactory,即对BeanFactory的各种功能进行填充,如常用的注解@Autowired @Qualifier等
		 * 设置SPEL表达式#{key}的解析器
		 * 设置资源编辑注册器,如PerpertyEditorSupper的支持
		 * 添加ApplicationContextAwareProcessor处理器
		 * 在依赖注入忽略实现*Aware的接口,如EnvironmentAware、ApplicationEventPublisherAware等
		 * 注册依赖,如一个bean的属性中含有ApplicationEventPublisher(beanFactory),则会将beanFactory的实例注入进去
		 */
		prepareBeanFactory(beanFactory);

		try {
   
			/**
			 * 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
			 * 在当前上下文使用的Bean容器BeanFactory的标准初始化完成后对其做一些修改。此时
			 * 所有的Bean definition都已经加载但是还没有 Bean 被创建
			 */
			postProcessBeanFactory(beanFactory);

			/**
			 * 实例化和调用所有 BeanFactoryPostProcessor,包括其子类 BeanDefinitionRegistryPostProcessor
			 * 激活各种BeanFactory处理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor
			 * 执行对应的postProcessBeanDefinitionRegistry方法 和  postProcessBeanFactory方法
			 */
			invokeBeanFactoryPostProcessors(beanFactory);

			/**
			 * 注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中
			 * 注册拦截Bean创建的Bean处理器,即注册BeanPostProcessor,不是BeanFactoryPostProcessor,注意两者的区别
			 * 注意,这里仅仅是注册,并不会执行对应的方法,将在bean的实例化时执行对应的方法
			 */				
			registerBeanPostProcessors(beanFactory);

			// 初始化上下文中的资源文件,如国际化文件的处理等
			initMessageSource();

			// 初始化上下文事件广播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher
			initApplicationEventMulticaster();

			// 给子类扩展初始化其他Bean
			onRefresh();

			// 注册监听器
			registerListeners();

			/**
			 * 设置转换器
			 * 注册一个默认的属性值解析器
			 * 冻结所有的bean定义,说明注册的bean定义将不能被修改或进一步的处理
			 * 初始化剩余的非惰性的bean,即初始化非延迟加载的bean
			 */
			finishBeanFactoryInitialization(beanFactory);

			/**
			 * 初始化生命周期处理器DefaultLifecycleProcessor,DefaultLifecycleProcessor含有start方法和stop方法,spring启动的时候调用start方法开始生命周期,
			 * spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,启动有一直运行,如一直轮询kafka
			 * 启动所有实现了Lifecycle接口的类
			 * 通过spring的事件发布机制发布ContextRefreshedEvent事件,以保证对应的监听器做进一步的处理,即对那种在spring启动后需要处理的一些类,这些类实现了
			 * ApplicationListener<ContextRefreshedEvent> ,这里就是要触发这些类的执行(执行onApplicationEvent方法)另外,spring的内置Event有ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、RequestHandleEvent
			 * 完成初始化,通知生命周期处理器lifeCycleProcessor刷新过程,同时发出ContextRefreshEvent通知其他人
			 */
			finishRefresh();
		}

		catch (BeansException ex) {
   
			if (logger.isWarnEnabled()) {
   
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}
			destroyBeans();
			cancelRefresh(ex);
			throw ex;
		}
		finally {
   
			resetCommonCaches();
		}
	}
}

obtainFreshBeanFactory() 方法会解析所有 spring 配置文件。在此也证明了我们的推断:在 IOC 容器启动时,会去解析所有的 spring 配置文件

obtainFreshBeanFactory() 方法

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

refreshBeanFactory() 方法

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
   
    ...
    
    @Override
	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);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
   
				this.beanFactory = beanFactory;
			}
		}
		catch (
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值