spring源码笔记--bean加载(一)

一、代码入口

3.1版本之前获取bean的方式:

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
bf.getBean("testBean");

3.1版本之后XmlBeanFactory废弃所以推荐采用ApplicationContext获取bean:本章主要介绍此种获取bean的方式,ApplicationContext BeanFacotry 两者都是用于加载 Bean 的,但是相比之下, ApplicationContext 提供了更多的扩展功能,简单点说 Application Context包含BeanFactory 的所有功能

 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml");
 TestBean testBean = (TestBean) applicationContext.getBean("testBean");

ps:beanFactory废弃原因:

(1)XmlBeanFactory对作用于的支持单一

(2)BeanFactory只支持两个作用域——Singleton和Prototype。

(3)XmlBeanFactory延迟加载 在企业及的项目当中,我们对bean的需求往往是比较大的,如果了解延迟加载的朋友,想必了解,延迟加载确实会给我们启动释放很多的压力,但是当我们在运行的时候,大量加载的时候,也会出现性能瓶颈

(4)XmlBeanFactory不会自动注册接口。

(5)XmlBeanFactory在企业级项目里面,并没有太好的支持

二、 类图全貌

三、源码解析:

1.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();
		}
	}

从第二段代码开始看,总共就做了三件事:

(1)super(parent)

   设置一下父级ApplicationContext,这里是null

(2)setConfigLocations(configLocations) 

里面做了两件事情:

       1. 将指定的Spring配置文件的路径存储到本地

        2.解析Spring配置文件路径中的${PlaceHolder}占位符,替换为系统变量中PlaceHolder对应的Value值,System本身就自带一些系统变量比如class.path、os.name、user.dir等,也可以通过System.setProperty()方法设置自己需要的系统变量

(3)refresh()

    这个就是整个Spring Bean加载的核心了,它是ClassPathXmlApplicationContext的父类AbstractApplicationContext的一个方法,顾名思义,用于刷新整个Spring上下文信息,定义了整个Spring上下文加载的流程。

2.refresh方法

上面已经说了,refresh()方法是整个Spring Bean加载的核心

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备此上下文以进行刷新。
			prepareRefresh();

			// 告诉子类刷新内部 bean 工厂。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 准备在此上下文中使用的 bean 工厂。
			prepareBeanFactory(beanFactory);

			try {
				// 允许在上下文子类中对 bean 工厂进行后处理。一个空的函数方便程序员扩展
				postProcessBeanFactory(beanFactory);

				// 调用在上下文中注册为 bean 的工厂处理器。激活各种 BeanFactory 处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册拦截 bean 创建的 bean 处理器。这里只是注册,真正的调用是在getBean时候
				registerBeanPostProcessors(beanFactory);

				// 为此上下文初始化消息源。为上下文初始化 Message源,即对不同语言的消息体进行国际化处理
				initMessageSource();

				// 为此上下文初始化事件多播器。
				initApplicationEventMulticaster();

				// 初始化特定上下文子类中的其他特殊 bean
				onRefresh();

				// 检查侦听器 bean 并注册它们。
				registerListeners();

				// 实例化所有剩余的(非延迟初始化)单例。
				finishBeanFactoryInitialization(beanFactory);

				// 最后一步:发布相应的事件。完成刷新过程,通知生命周期处理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 {
				// 重置 Spring 核心中的常见内省缓存,因为我们可能不再需要单例 bean 的元数据......
				resetCommonCaches();
			}
		}
	}

startUpShutdownMonitor对象是加锁的,这么做的原因是避免多线程同时刷新Spring上下文,而后续close()方法也是用的该对象锁,所以可以避免冲突

下面简单介绍核心的方法

(1)obtainFreshBeanFactory方法        


	
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

告诉子类刷新内部 bean 工厂。
返回:新建的 BeanFactory 实例

下面其中的refreshBeanFactory()方法

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

该方法中DefaultListableBeanFactory 类非常重要,后面会详讲,先继续看其他方法refresh()中的其他方法

(3)prepareBeanFactory方法

上一步已经把工厂建好了,但是还不能投入使用,因为工厂里什么都没有,还需要配置一些东西。看看这个方法的注释

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //设置BeanFactory的类加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        //设置支持表达式解析器
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        //添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        //设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xx,因为ApplicationContextAwareProcessor#invokeAwareInterfaces已经把这5个接口的实现工作做了
        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、ResourceLoader、ApplicationEventPublisher、ApplicationContext
        //其他组件中可以通过 @autowired 直接注册使用
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        //添加BeanPostProcessor【ApplicationListenerDetector】后置处理器,在bean初始化前后的一些工作
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        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()));
        }

        //给BeanFactory中注册一些能用的组件;
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            //环境信息ConfigurableEnvironment
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
          //系统属性,systemProperties【Map<String, Object>】
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
          //系统环境变量systemEnvironment【Map<String, Object>】
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值