BeanFactory创建流程及继承体系

Ioc容器初始化主体流程之BeanFactory及容器继承体系

文章内容输出来源:拉勾Java高薪训练营

首先我们来看这么一张图,可以看到容器的顶级接口是BeanFactory,但是BeanFactory接口却并没有多少方法,这也是Spring的精妙之处,通过继承顶级接口来各自完成各自的事情,各自分工。而ApplicaitonContext接口是容器的高级接口。它的主要实现类就是ClassPathXmlApplicationContextFileSystemXmlApplicationContext,前者从类路径加载配置资源,后者从系统文件加载配置文件。

Spring应用上下文,官方又称IOC容器,主要作用是管理创建Bean.那么首先了解一下Bean的生命周期。

那么通过搭建好的spring源码环境来启动测试用例来分析一下Bean的创建流程。首先一个 简单测试类:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
System.out.println(lagouBean);

这个代码的作用就是从类路径加载xml文件,生成一个Bean。我们主要是debug来看一下执行流程。

/**
	 * 构造函数
	 */
	public LagouBean(){
		System.out.println("LagouBean 构造器...");
	}

在构造函数处打一个断点,来看一下调用栈进入了哪一个方法:

org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization

可以看到它首先进入了AbstractApplicationContext的refresh方法,然后再refresh方法里调用finishBeanFactoryInitialization(beanFactory);

TIPS:记住这个refresh方法,后面要考。

接下来看初始化Bean的断点:

/**
	 * InitializingBean 接口实现
	 */
	public void afterPropertiesSet() throws Exception {
		System.out.println("LagouBean afterPropertiesSet...");
	}

调用栈和上面一样,初始化依然在refresh方法的finishBeanFactoryInitialization(beanFactory);执行。

那么这个refresh方法到底有什么呢?我们来看看

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");打一个断点。

在进入一个静态方法后跳出,然后继续进入,

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

        // 初始化父类
		super(parent);
		setConfigLocations(configLocations);
        // 重点。刷新方法
		if (refresh) {
			refresh();
		}
	}

进入到一个构造方法,重点跳进refresh方法。如下:

@Override
	public void refresh() throws BeansException, IllegalStateException {
        // 对象锁   fresh() 和 close() 都会用到锁
		synchronized (this.startupShutdownMonitor) {
			// 刷新前的处理
			prepareRefresh();

			// 获取beanfactory;默认实现是DefaultListableBeanFactory加载BeanDefition 并注册到 BeanDefitionRegistry
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// beanfactory的预备工作,比如context的类加载器
			prepareBeanFactory(beanFactory);

			try {
				// beanfactory准备工作完成后的后置处理工作
				postProcessBeanFactory(beanFactory);

				// 实例化并调用实现了了BeanFactoryPostProcessor接口的bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册beanPostProcessor在创建bean的前后执行
				registerBeanPostProcessors(beanFactory);

				// 国际化
				initMessageSource();

				// 初始化事件派发器
				initApplicationEventMulticaster();

				// 子类重写这个方法可以自定义容器刷新逻辑.
				onRefresh();

				// 检查监听器并注册.
				registerListeners();

				// 这是重点。初始化非懒加载 的单例bean,
                // 初始化创建非懒加载实例
                // 填充属性
                // 初始化方法调用
                // 调用BeanPostProecessor对实例bean进行后置处理
				finishBeanFactoryInitialization(beanFactory);

				// 完成context的刷新
				finishRefresh();
			}
// 异常部分省略

接下来讲讲是如何获取一个BeanFactory的。

进入到refresh方法的ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();这一行代码,断点进去。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	// 刷新beanfactory	
    refreshBeanFactory();
    // 返回beanfactory
		return getBeanFactory();
	}

进入到第一步刷新方法中

	@Override
	protected final void refreshBeanFactory() throws BeansException {
        // 如果有了工厂
		if (hasBeanFactory()) {
            // 销毁
           destroyBeans();
            // 关闭
			closeBeanFactory();
		}
		try {
            // 创建一个beanfactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
            // 设置序列号  
			beanFactory.setSerializationId(getId());
            // 自定义
			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);
		}
	}
posted @ 2020-09-09 12:52  杨小星儿  阅读(655)  评论(0)    收藏  举报