Spring源码解读

容器和对象的创建流程

  1. 创建容器
  2. 加载配置文件,封装成BeanDefinition
  3. 调用执行BeanFactoryPostProcessor
  4. (准备工作:准备beanPostProcessor,准备监听器,事件,广播器)
  5. 实例化
  6. 初始化
  7. 获取到完整对象

重要的refresh()

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
            /*
             *前戏,做容器新前的准备工作
             *1.没置容器的启动时间
             *2、没置活跃状态为true
             *3、没置关闭状态为false
             *4、获取Environment对象,并加载当前系统的属性值的Environment对象中
             *5、准备监听器和事件的集合对象,默认为空的集合
             * */
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
            // 创建容器对象:DefaultListableBeanFactory
            // 加载xmL配置文件的属性值到当前工厂中,最重要的就是BeanDefinition
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
            // BeanFactory的准备工作,对各种属性进行填充
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
                // 子类覆盖方法做额外的处理,此处我们自己一般不做任何操作,但是可以查看web中的代码,是有具体实现的(模板方法,留给子类实现)
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
                // 调用各种beanFactory处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
                // 注册bean处理器,这里只是注册功能,真正调用的是getBean方法。
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
                // 为上下文初始化message源,即不同语言的消息体,国际化处理
				initMessageSource();

				// Initialize event multicaster for this context.
                // 初始化事件监听多路广播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
                // 留给子类来初始化其他bean,空实现,模板方法
				onRefresh();

				// Check for listener beans and register them.
                // 在所有注册的bean中查找listener bean,并注册到消息广播中。
                /*本方法会注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中。
        BeanPostProcessor 接口是 Spring 初始化 bean 时对外暴露的扩展点,Spring IoC 容器允许 BeanPostProcessor 在容器初始化 bean 的前后,添加自己的逻辑处理。在 registerBeanPostProcessors 方法只是注册到 BeanFactory 中,具体调用是在 bean 初始化的时候。
				具体的:在所有 bean 实例化时,执行初始化方法前会调用所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法,在执行初始化方法后会调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法。*/

				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
                //初始化所有剩下的单实例(非懒加载的)***重要
               /*
				* 1、bean实例化过程
				* 2、依赖注入
				* 3、解析@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value等注解
				* 4、BeanPostProcessor的执行
				* 5、Aop的入口
				*
				* */

				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + 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();
			}
		}
	}

***在spring源码中,所有do开头的方法都是真正干事的方法,都很重要,例如:doGetBean方法。

doProcessConfigurationClass方法中对注解进行解析。

*** aware接口存在的意义是:方便通过spring中的bean对象来获取对应容器中的相关属性值

Spring是如何加载配置文件到应用程序的?

@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
            //创建DefaultListableBeanFactory 对象
			DefaultListableBeanFactory beanFactory = createBeanFactory();
            //定制beanFactory,设置相关属性,包括是否允许覆盖同名称不同定义对象以及循环依赖
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
            //初始化documentReader,并进行xml文件的读取及解析,默认命名空间的解析,自定义标签的解析
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

真正做事的方法:doLoadBeanDefinitions

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
            /*
             *此处获取xml文件的Document对象,这个解析是由documentLoader完成的,从
             *String[]-String-Resource[]-resource,最终是将resource读取成一个Document对象
             */
			Document doc = doLoadDocument(inputSource, resource);
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
	}

解析xml里面的标签及数据

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

        //解析class属性
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
        //解析parent属性
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
            //创建装在bean信息的AbstractBeanDefinition对象,实际的实现是GenericBeanDefinition
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
            //解析bean标签的各种其他属性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            //解析description信息
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
            //解析元数据
			parseMetaElements(ele, bd);
            //解析lookup-method属性
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            //解析replaced-method属性
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            //解析构造函数参数
			parseConstructorArgElements(ele, bd);
            //解析Property子元素
			parsePropertyElements(ele, bd);
            //解析Qualifier子元素
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		}
		finally {
			this.parseState.pop();
		}

		return null;
	}

Spring中Bean的生命周期源码解读

Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:
1.BeanNameAware's setBeanName
2.BeanClassLoaderAware's setBeanClassLoader
3.BeanFactoryAware's setBeanFactory
4.EnvironmentAware's setEnvironment
5.EmbeddedValueResolverAware's setEmbeddedValueResolver
6.ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)
7.ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)
8.MessageSourceAware's setMessageSource (only applicable when running in an application context)
9.ApplicationContextAware's setApplicationContext (only applicable when running in an application context)
10.ServletContextAware's setServletContext (only applicable when running in a web application context)
11.postProcessBeforeInitialization methods of BeanPostProcessors
12.InitializingBean's afterPropertiesSet
13.a custom init-method definition
14.postProcessAfterInitialization methods of BeanPostProcessors

在refresh()方法中的finishBeanFactoryInitialization(beanFactory)进行了bean的完整生命周期。

getBean()---》doGetBean()---》createBean()---》doCreateBean()---》populateBean()进行数据的渲染---》initializeBean()---》applyBeanPostProcessorsBeforeInitialization---》invokeInitMethods()---》applyBeanPostProcessorsAfterInitialization()---》最后得到bean

bean的生命周期:实例化bean-----》填充属性(populateBean)-------》before(applyBeanPostProcessorsBeforeInitialization返回的是一个bean)------》init-method方法(初始化bean:invokeInitMethods)------》after(applyBeanPostProcessorsAfterInitialization:aop的代理,jdk和cjlib)------》完整对象-----》销毁

在程序运行期间,要读取当前系统的环境变量和系统属性,可以使用System.getEnv/System.getProperties。

如果想要在spring的生命周期的不同阶段做不同的处理工作,应该怎么办?

观察者模式:监听器/监听事件/多播器

Spring循环依赖问题

使用构造器注入的,无法解决循环依赖,使用set方法注入,使用三级缓存解决循环依赖。

方法的调用流程:

在DefaultSingletonBeanRegistry类中的三级缓存。

一级缓存  singletonObjects :存放完整的bean对象,单例池。

二级缓存  earlySingletonObjects :存放提前声明的bean,可能是代理对象,可能是普通对象。

三级缓存 singletonFactories :打破循环依赖,存放的是一个singletonFactory。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** Cache of singleton objects: bean name to bean instance. */
    //一级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
    //三级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
    //二级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
}

在循环依赖的时候,将初始化的a放入到三级缓存,然后在进行a的实例化,进行数据的填充。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值