写在前面

Spring源码解析系列文章是我最近在学习了一段Spring,SpringBoot和SpringMVC等一系列的源码后整理的文章。我会随着我对Spring的理解来进行相应的文章的整合和归纳。

我决定从提出一个问题开始。然后围绕着解决这个问题的方式来剖析源码。当我们把一个问题搞懂了的时候。里面的源码我们也就清楚了。事实上看源码不是目标。解决一些日常的困惑才是目标。

问题

为什么被Spring管理的类。只要实现了Aware接口。Spring就会自动把对应的对象注入进来。这个bean如果想要使用直接使用就可以了。如下: Spring会自动把ApplicationContext注入到AwareTest这个bean里面。

public class AwareTest implements ApplicationContextAware {public ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void checkAware(){if(applicationContext != null){System.out.println("ApplicationContext inject success");}}
}

源码解析:

1. 我们都知道在AbstractApplicationContext里面真正的启动ApplicationContext的函数是refresh()方法。具体的方法如下

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.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();}}}

2. 可以看到有一个prepareBeanFactory的方法,我们再往里面看一下这个方法里面究竟有什么。可以发现给BeanFactory添加了一个BeanPostProcessor。名字是ApplicationContextAwareProcessor

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));beanFactory.ignoreDependencyInterface(EnvironmentAware.class);... 多余的代码不贴出来了}

3. BeanPostProcessor这个接口我们都很熟悉了。我们看一下这个里面PostProcessBeforeInitialization()函数。传入bean和beanName。最后是调用了invokeAwareInterfaces(bean)这个函数。如果bean 是aware类的子类。那么就调用bean的set方法将ApplicationContext塞到bean里面。然后业务代码在需要使用ApplicationContext的时候就可以直接使用了。因为已经被set进来了。

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {AccessControlContext acc = null;if (System.getSecurityManager() != null &&(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);return null;}, acc);}else {invokeAwareInterfaces(bean);}return bean;}private void invokeAwareInterfaces(Object bean) {if (bean instanceof Aware) {if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}}

4. 我们再来看一下。Spring是什么时候调用了BeanPostProcessor的postProcessBeforeInitialization函数的。在AbstractAutowireCapableBeanFactory的initializeBean方法里面 , 在调用InvokeInitMethods的方法之前。先执行了applyBeanPost

ProcessorBeforeInitialization的方法。这个方法里面就是将所有的BeanPostProcessor的的postProcessBeforeInitialization()都执行一遍。包括之前创建的ApplicationContextAwareProcessor。于是ApplicationContextAwareProcessor这个时刻就将ApplicationContext注入到我们的Bean里面了。

   protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

上面是跟着源码走了一遍。我看完之后的理解就是。Spring在整个设计上对于这种松耦合和可插拔真是做了非常多的工作。可以说Spring 本身的ioc的代码并不复杂。大量的代码工作都是为了方便开发者自己去拓展Spring的边界。让开发者可以更好的去控制和管理bean这个对象。Spring的代码建议多读几遍。虽然每一遍读起来都很痛苦。但是每一次读都会有新的感受。

这一篇对原理的解析也还不错。参考链接

Spring源码解析:Spring Aware 原理解析相关推荐

  1. 手撸spring源码分析IOC实现原理

    手撸spring源码分析IOC实现原理 文章出处:https://github.com/fuzhengwei/small-spring 根据小付哥的手撸spring核心源码一步步学习出来的结果收货总结 ...

  2. Spring源码系列- Spring Beans - 核心类的基本介绍

    Spring源码系列- Spring Beans - 核心类的基本介绍 读过上一篇文章的读者应该都能对Spring的体系结构有一个大致的了解,在结尾处,我也说过会从spring-beans包开始分析, ...

  3. 【Spring源码】Spring Transactional事务:传播机制(Propagation) 介绍 和 源码剖析

    [Spring源码]Spring Transactional事务:传播机制(Propagation) 源码剖析 关键词 AMethod调用BMethod,转载BMethod的角度来考虑:站在被调用者的 ...

  4. spring 源码分析(1)-xml文件解析

    我们在最开始接触spring的时候,看到不少书spring入门的例子如下 ApplicationContext atx = new ClassPathXmlApplicationContext(&qu ...

  5. spring源码阅读--aop实现原理分析

    aop实现原理简介 首先我们都知道aop的基本原理就是动态代理思想,在设计模式之代理模式中有介绍过这两种动态代理的使用与基本原理,再次不再叙述. 这里分析的是,在spring中是如何基于动态代理的思想 ...

  6. 『互联网架构』软件架构-spring源码之spring结构概述

    spring从07年接触到目前2018年也差不多10年了,一个java的框架为什么能火这么多年.很多人对spring的使用轻车熟路,但是从未解读过spring的源码,老铁跟我一起看看源码,了解下内部的 ...

  7. Spring源码之Spring的大体框架

    Spring源码(一)----了解Spring的大体框架 Spring的源码数量特别多,在我下载了Spring FrameWork源码后,发现有些无从学起,那么就一步一步来,先不管其他,先了解一下Sp ...

  8. Spring源码:Spring源码阅读环境搭建

    本篇内容包括:Mac 环境下 gradle 的安装和配置.源码克隆.新建测试类,测试Spring源码 等内容! 第一步:Mac 环境下 gradle 的安装和配置 1.下载安装包 # 到 GitHub ...

  9. 【Spring源码】Spring事务原理

    目录 1.什么是事务 2.Spring事务基本概念 2.1.基础配置 2.1.1.Spring事务的基础配置 2.1.2.Spring事务的传播特性 2.1.3.Spring事务的隔离级别 2.2.基 ...

  10. spring源码阅读--@Transactional实现原理

    @Transactional注解简介 @Transactional是spring中声明式事务管理的注解配置方式,相信这个注解的作用大家都很清楚.@Transactional注解可以帮助我们把事务开启. ...

最新文章

  1. 布线时其他区域变黑、高亮Net时其他区域太黑
  2. 构建高可用ZooKeeper集群
  3. 2017年9月分c语言,2020年9月中国编程语言排行榜
  4. 权限管理系统之用户管理
  5. 锤子t1重置后怎么显示无服务器,解决锤子手机smartisanT1关机后无法正常开机(附带刷机教程图文)...
  6. 机器人施教器的信息丢失_一种精准定位学习难度的施教方法及教育机器人与流程...
  7. OpenFeign封装为springboot starter
  8. python tkinter输入框_python tkinter-按钮.标签.文本框、输入框
  9. 如何使用C#调用REST api?
  10. ABP:在多语句事务内不允许使用 CREATE DATABASE 语句
  11. python isinstance()方法的使用
  12. Vue/vant——使用阿里巴巴矢量图引入图标
  13. 电机控制进阶3——PID串级控制(附全套代码下载)
  14. windows批处理备份压缩文件夹rar
  15. Mac 本地起一个html 服务
  16. C++ 模板函数的使用
  17. 安卓系统入门_安卓玩家不可错过的神器:55GMagisk模块下载
  18. 统一用户认证和单点登录和授权的原理与流程
  19. QPSK调制解调过程,包括串并转换,电平转换,载波调制,相干解调,抽样判决等
  20. realEngine(UE4)实现开关门效果

热门文章

  1. t-SNE数据降维可视化
  2. java digestutils.md5hex_linux下md5sum和DigestUtils.md5Hex的关系 博客分类: java
  3. 无线网络技术(实验)——无线局域网组成与管理实验
  4. android魅族 小红点,魅族公布手机APP公约 小红点不能超过2个
  5. linux游戏盒子恢复默认,dnf多玩补丁_多玩dnf盒子我用了补丁,怎么还原成默认?具体点,......
  6. 信工所复试(专业面)
  7. matlab仿真step模块讲解,Simulink仿真教程(最好)
  8. MethodArgumentNotValidException异常拦截提示信息太长?
  9. Pyserial相关知识
  10. 小鹤输入法及练习工具推荐