Spring源码分析

关键类介绍

ApplicationContext

万能的 applicationContext, 但实际上各种能力都是依赖于其他的类, 比如 getBean 是 beanFactory 的, publishEvent 是事件广播器的, 等等. 其本身是一个综合体, 整合这些能力, 便于开发者调用和理解.

# 下面列一下相关的接口, 抽象类, 和具体类
ApplicationContext
	是一个只读的 bean 容器
	可以加载解析配置文件(如xml)
	可以发布事件和注册监听
	具有国际化消息处理能力
ConfigurableApplicationContext
	是一个具有可配置能力的 容器(可设置各个参数, 如id, 父容器)
	具有容器生命周期概念, 如启动,停止,关闭.
AbstractApplicationContext
	模板方法模式的抽象类, 定义了容器的模板(refresh方法), 但由具体的子类实现部分方法
	管理Bean和BeanFactory的PostProcessor
	管理事件的监听和处理
AbstractRefreshableApplicationContext
	为可重复刷新的容器提供基类
	加入了BeanFactory的管理(创建/关闭等)
AbstractRefreshableConfigApplicationContext
	加入了configLocation字段, 用于某些容器初始化BeanFactory和Bean
AbstractXmlApplicationContext
	定义了读取xml配置文件来加载BeanFactory的代码, 使得子类只需提供配置文件地址或Resource
ClassPathXmlApplicationContext
	继承基类, 提供配置文件地址的构造方法, 调用refresh加载BeanFactory
		

BeanFactory

1.核心中的核心, 加载和管理 beanDefinitions(Bean配置信息), 创建和管理 bean 对象实例, 注册和管理 BeanPostProcessor(Bean扩展)

# 下面列一下相关的接口, 抽象类, 和具体类
BeanFactory
  定义了 Bean 的基础操作接口, 如 getBean, getType, isSingleton 等

SingletonBeanRegistry
  定义了单例对象的操作接口 (注册/获取/是否已存在) 

HierarchicalBeanFactory
  定义了父 BeanFactory 的相关操作接口(获取)

ConfigurableBeanFactory
  定义了对 BeanFactory 做各种配置的操作接口, 包括 BeanPostProcessor, setParentBeanFactory, destroyBean, registerAlias, resolveAliases 等

DefaultSingletonBeanRegistry
  实现了 SingletonBeanRegistry 接口, 即实现了单例对象的缓存管理, 包括一级/二级/三级(二级三级只依赖循环用上的两个缓存)
  
FactoryBeanRegistrySupport
  继承了 DefaultSingletonBeanRegistry
	实现对使用 FactoryBean 存储和获取 bean 对象实例方式的支持
	
AbstractBeanFactory
  继承了 FactoryBeanRegistrySupport
  实现了 BeanFactory/HierarchicalBeanFactory/ConfigurableBeanFactory 定义的接口
  实现了具体 getBean, 包括缓存管理等
  
AutowireCapableBeanFactory
  定义了根据 class 类型获取 BeanDefinition 信息以及 Bean 对象的接口

AbstractAutowireCapableBeanFactory
  继承自 AbstractBeanFactory 
  实现了 AutowireCapableBeanFactory 中定义的方法(就是实现了根据 class 获取 bean 或 BeanDefinition)
  实现了 createBean, 也就是真正的实例化一个对象的过程, 包括实例化, 为需要赋值的字段注入相应的值
  同时触发了 BeanPostProcessor 的方法调用
  
BeanDefinitionRegistry
  定义了 BeanDefinition 的注册/获取/移除
  
ListableBeanFactory
	定义了 BeanDefinition 的可遍历性
  
ConfigurableListableBeanFactory
  结合 ListableBeanFactory 和 ConfigurableBeanFactory 并补充完善了几个相关接口 (如 getBeanNamesIterator 接口 )

DefaultListableBeanFactory
  继承了 AbstractAutowireCapableBeanFactory
  实现了 BeanDefinitionRegistry/ConfigurableListableBeanFactory 的接口
 
# 总结:
定义处:
BeanFactory(getBean)
SingletonBeanRegistry(addSingleton)
HierarchicalBeanFactory(getParentBeanFactory)
ConfigurableBeanFactory(addBeanPostProcessor)
AutowireCapableBeanFactory(autowireBean)
BeanDefinitionRegistry(registerBeanDefinition)
ListableBeanFactory(getBeanDefinitionNames)
ConfigurableListableBeanFactory(getBeanNamesIterator)

实现处:
DefaultSingletonBeanRegistry(registerSingleton)
FactoryBeanRegistrySupport(getObjectFromFactoryBean)
AbstractBeanFactory(doGetBean)
AbstractAutowireCapableBeanFactory(createBean)
DefaultListableBeanFactory(registerBeanDefinition)

容器初始化过程

1.setParent(): 处理父容器 
2.setConfigLocations(): 解析并设置xml配置文件路径
3.refresh(): 创建 beanFactory 对象并初始化, 读取 xml 配置文件得到 beanDefinitions, 接着处理两种 PostProcessor, 然后添加国际化处理器和事件广播器以及相应的初始化和一些处理, 最后实例化单例的 bean 等等.

#外圈结束, 再看 refresh() 里面的每个方法
1.prepareRefresh(): 准备工作, 一些字段值的设置和处理.
2.obtainFreshBeanFactory(): 创建一个 beanFactory 对象并注册到 applicationContext (即赋值到字段上), 然后解析 xml 配置文件(或注解配置)的信息, 解析得到 beanDefinitions 并注册到容器中.
3.然后是一些对 beanFactory 对象的完善配置的代码
4.扫描并执行 BeanFactoryPostProcessor(其作用是为beanFactory对象添加东西提供扩展性), 其中我认识的就只有 ConfigurationClassPostProcessor(这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan等基础注解).
5.扫描实现了 BeanPostProcessor 接口的 bean 并注册到 beanFactory 中存起来, 等 createBean 创建对象时会在对应的时机执行一些对应的方法(钩子). 常见的各种 XxxAware 就是靠这个实现的咯.
6.接着, 初始化国际化资源处理器, 事件广播器, 并注册一些需要注册的事件(也注册容器内实现对应接口的 bean)
7.处理一些 beanFactory 的配置, 接着为所有单例且非懒加载的(不就是默认策略嘛) bean 创建实例, 缓存起来.
8.广播容器加载完成了的事件. 以及处理生命周期.

最后总结下, 先创建容器, 再将根据配置文件解析得到 BeanDefinition 注册到容器中, 然后处理两大扩展(BeanFactoryPostProcessor/BeanPostProcessor), 接着是Spring的国际化, 以及相当有用的事件广播器, 最后实例化 bean. 整体感觉其实很简单, 但其实有大量的工作交给了 BeanPostProcessor.

超长源码分析过程

// 先随便写个 main 方法, 如我写的, 可测试依赖循环问题和事件监听:
// 包名: cn.gudqs7.spring.tests, 改动则需同步修改xml哦
// 进入对应类代码: 快捷键 Cmd+Option+鼠标点击 (或 Ctrl+Alt+鼠标左键 ); 如果是接口松开 Option(或Alt)键

Test.java
public class Test {

	public static void main(String[] args) {
		ApplicationContext xmlContext = new ClassPathXmlApplicationContext("application-wq.xml");
		UserServiceImpl userService = xmlContext.getBean(UserServiceImpl.class);
		userService.sayHi();
	}

}


application-wq.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">

	<bean name="userService" class="cn.gudqs7.spring.tests.UserServiceImpl">
		<property name="starter"><ref bean="serverStarter"/></property>
	</bean>
	<bean name="serverStarter" class="cn.gudqs7.spring.tests.ServerStarter">
		<property name="userService"><ref bean="userService"/></property>
	</bean>

</beans>

    
UserServiceImpl.java
@Service
public class UserServiceImpl {

	@Resource
	private ServerStarter starter;

	public void sayHi() {
		System.out.println(starter);
		System.out.println("Hello Spring!");
	}

	public void setStarter(ServerStarter starter) {
		this.starter = starter;
	}
}


ServerStarter.java
@Service
public class ServerStarter implements ApplicationListener<ContextRefreshedEvent> {

	@Inject
	private UserServiceImpl userService;

	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		String applicationName = event.getApplicationContext().getApplicationName();
		System.out.println(applicationName);
		System.out.println(userService);
		System.out.println("========== started by gudqs7 ==============");
		System.out.println("========== started by gudqs7 ==============");
		System.out.println("========== started by gudqs7 ==============");
	}

	public void setUserService(UserServiceImpl userService) {
		this.userService = userService;
	}
}

😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄

// 接下来, 进入ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(java.lang.String) 方法中

// 其跳转到了
  public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		// 为容器的 parent 字段赋值, 若 parent 不为空, 且有 ConfigurableEnvironment, 则合并数据(将父容器有的加到子容器中)
		// 即执行了 org.springframework.context.support.AbstractApplicationContext.setParent()
		super(parent);

		// 为 configLocations 字段赋值(告知配置文件位置), 赋值前会根据环境变量解析(此时环境变量中只有系统环境变量: 如JAVA_HOME).
		setConfigLocations(configLocations);
		if (refresh) {
			// 注释在下面
      refresh();
		}
	}
  
  

😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄

// 然后具体的看 refresh 方法
public void refresh() throws BeansException, IllegalStateException {
		// 1.设置容器初始的一些属性(时间,状态),初始化占位符数据源并校验所有 bean 所使用的占位符是否存在, 清空事件和监听
		// 2.清空重置旧的 beanFactory, 再创建新的 beanFactory 并通过解析 xml或注解 加载 beanDefinitions
		// 3.设置了一些 beanFactory 的属性, 添加了几个有用的 BeanPostProcessor, 还添加了几个 bean 到容器中(都是环境相关的 bean)
		// 4.子类对beanFactory 添加自己的特殊的 BeanPostProcessor (如servletContxt/servletConfig注入)
		// 5.扫描容器中实现了 BeanFactoryPostProcessor 接口的 bean 将其注册到 beanFactory 中并执行
		// 6.扫描容器中实现了 BeanPostProcessor 接口的 bean 将其注册到 beanFactory 但不执行(实例化 bean 对象那会有几个执行时机)
		// 7.创建一个国际化资源解析器并注册到 beanFactory; 创建一个事件广播器并注册到 beanFactory.
		// 8.调用子类的其他刷新时需要做的事情(模板方法)
		// 9.扫描容器中实现了 ApplicationListener 接口的 bean, 将其预存到广播器中但不执行
		//10.完成 beanFactory 的一些配置(包括终结一些东西, 如 setTempClassLoader(null) ); 将单例的 bean 创建出来放入容器中(未设置lazy-init=true)的 bean
		//11.广播 ContextRefreshedEvent 事件, 初始化LifeCycleProcessor及调用其 onRefresh 方法.

		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 设置容器初始的一些属性(时间,状态),初始化占位符数据源并校验所有 bean 所使用的占位符是否存在, 清空事件和监听
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 清空重置旧的 beanFactory, 再创建新的 beanFactory 并解析 xml或注解 加载 beanDefinitions
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 设置了一些 beanFactory 的属性, 添加了几个有用的 BeanPostProcessor, 还添加了几个 bean 到容器中(都是环境相关的 bean)
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 子类对beanFactory 添加自己的特殊的 BeanPostProcessor (如servletContxt/servletConfig注入)
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 扫描容器中实现了 BeanFactoryPostProcessor 接口的 bean 将其注册到 beanFactory 中并执行
				//   扫描6次, 2(BeanDefinitionRegistry/BeanFactory) x 3(优先级:高/中/其他)
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 扫描容器中实现了 BeanPostProcessor 接口的 bean 将其注册到 beanFactory 但不执行; 扫描6次: 2(MergedBeanDefinitionPostProcessor/其他) x 3(优先级: 高/中/其他)
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 创建一个国际化资源解析器并注册到 beanFactory.
				initMessageSource();

				// Initialize event multicaster for this context.
				// 创建一个事件广播器并注册到 beanFactory.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 调用子类的其他刷新时需要做的事情(模板方法)
				onRefresh();

				// Check for listener beans and register them.
				// 将可能存在的 applicationListeners 注册到事件广播器中(新建时是不存在的),
				// 然后扫描容器中实现了 ApplicationListener 接口的 bean, 将其预存到广播器中但不执行
				// 将之前 publishEvent() 想广播的事件广播出去, 然后字段 earlyApplicationEvents 赋值为空(代表之后可立即广播)
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 完成 beanFactory 的一些配置(包括终结一些东西, 如 setTempClassLoader(null) )
				// 注册默认的表达式解析器(若无相应的bean存在)
				// 扫描容器中实现了 LoadTimeWeaverAware 接口的 bean, 并触发(getBean)之前注册过的 BeanPostProcessor
				// 将单例的 bean 创建出来放入容器中(未设置lazy-init=true)的 bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 广播 ContextRefreshedEvent 事件, 初始化LifeCycleProcessor及调用其 onRefresh 方法.
				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();
			}
		}
	}

我错了, 代码都放上去不如给个GitHub地址, 接下来省略代码吧, 只放注释😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄

// 挨个看里面的方法
org.springframework.context.support.AbstractApplicationContext#prepareRefresh
    // 1.设置容器初始的一些属性, 如启动时间, 当前状态
		// 2.打印开始日志
		// 3.初始化占位符数据源
		// 4.校验所有 bean 所使用的占位符是否存在
		// 5.清空事件和监听
		// Switch to active.
  
org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
    // 1.存在旧的则先摧毁 bean 对象实例及缓存数据, 再将旧的置为 null
		// 2.创建一个新的 beanFactory 对象, 再设置 id及一些配置
		// 3.扫描并加载 beanDefinations
		// 4.设置这个新的 beanFactory 对象为 applicationContext 的 beanFactory 字段值.
  
org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
    // 1.设置 beanFactory 的类加载器
		// 2.设置 beanFactory 的表达式解析器
		// 3.1:注册一个 BeanPostProcessor 用于将实现了ApplicationContext能力相关的Aware接口的 bean, 触发赋值setter 注入 applicationContext 对象
		// 3.2:设置 beanFactory 处理 bean 时要忽略的接口(主要是setter注入时忽视一些也是setter的方法, 因为这些方法会由 PostProcessor 来触发)
		// 4.注册一些特殊的 bean(注入这些bean时会注入 this 对象: 多功能工具人 ApplicationContext, 可见其和普通 bean 的注册方式不一样)
		// 5.注册一个 BeanPostProcessor 用于检测加载的 bean 是否实现了 ApplicationListener 接口, 若是, 则注册到事件广播器中(不是,是暂存在applicationListeners字段中, 等事件广播器创建后才注册)
		// 6.注册一个 BeanPostProcessor 用于触发实现了 LoadTimeWeaverAware 接口的 bean 的 setLoadTimeWeaver() 社会 LTW 实例.
		// 7.注册几个环境相关 bean 到容器中(Spring的环境对象, 以及系统环境变量和系统配置文件)

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
    // 1.若 beanFactory 实现了 BeanDefinitionRegistry 接口(new AnnotationConfigApplicationContext 就实现了)
		//    则扫描所有实现了 BeanDefinitionRegistryPostProcessor 接口的 bean, 根据优先级分三类(高/中/其他)依次执行
		// 2.然后扫描所有实现了 BeanFactoryPostProcessor 接口的 bean, 依旧是根据优先级分三类依次执行.
		// 3.每次执行前都会根据 Order 信息排序, 再遍历执行
  
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)
    // 1.扫描6次: 2(MergedBeanDefinitionPostProcessor/其他) x 3(优先级: 高/中/其他)
		//    将其加入到 beanFactory 的 beanPostProcessors 集合中
		// 2.再次加入 ApplicationListenerDetector (用于处理实现 ApplicationListener 的 bean 注册到事件广播器), 主要是使其在链末尾, 可以最后执行.

org.springframework.context.support.AbstractApplicationContext#registerListeners
    // 1.将可能存在的 applicationListeners 注册到事件广播器中(新建时是不存在的)
		// 2.扫描容器中实现了 ApplicationListener 接口的 bean, 将其预存到广播器中但不执行
		// 3.将之前 publishEvent() 想广播的事件广播出去, 然后字段 earlyApplicationEvents 赋值为空
		//    (因为 publishEvent() 中根据是否为空判断立刻执行或先存着) (另这也解释了 prepareRefresh() 中为何要赋值一个空集合)

  
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
    // 1.完成 beanFactory 的一些配置
		// 2.注册默认的表达式解析器(若无相应的bean存在)
		// 3.扫描容器中实现了 LoadTimeWeaverAware 接口的 bean, 并触发(getBean)之前注册过的 BeanPostProcessor
		// 4.将单例的 bean 创建出来放入容器中(未设置lazy-init=true)的 bean

org.springframework.context.support.AbstractApplicationContext#finishRefresh
    // 1.清空资源缓存
		// 2.创建一个生命周期管理器(start, refresh, stop等)并注册到 beanFactory
		// 3.触发生命周期管理器的 onRefresh()
		// 4.广播容器刷新完成的事件
		// 5.为 Spring Tool Suite 提供某些便捷(没用过, 不知道...)

可算复制完了, 如果你有幸直接跳读到这里, 那么送上地址 : 注意分支吧

另外上面方法前带个 # 的, 复制到 IDEA 双击 Shift 然后粘贴, 选择 Symbols 搜索更准确呢!

获取容器对象过程

# 从getBean(Class type) 中进入
1.检查 applicationContext 和 beanFactory 的状态, 若有异常则给出准确的错误.
2.扫描容器中所有此 type 的 beanName, 遍历判断每个 beanName 是否可用
   可用则判断可用的个数是否刚好是一个, 是则直接调用 getBean() 返回对象实例
   若可用的个数超过一个, 则根据 beanDefinition 的 isPrimary 和对比配置的优先级是否为有最高的再返回最高的
   若都不行, 则报错.
3.接着看 getBean, 先试着从单例的缓存中获取, 若存在则返回.
4.若缓存中不存在, 则判断父容器是否存, 若存在则从父容器获取
   若父容器不存在, 则自己新建, 先标记 beanName 到 alreadyCreated 中(表示已经创建了防止重复创建) 再开始创建一个 bean.
5.创建一个新的 bean 实例, 先处理 beanDefinition 的 dependsOn 属性(即若存在则先调用 getBean 获取依赖的 bean)
6.若 beanDefinition 的设置是单例, 则通过闭包对创建对象前后进行一些异常处理和缓存处理(主要是彻底创建完后加入到单例一级缓存, 移除二级和三级缓存[循环依赖相关的两个缓存]).
7.通过反射根据 beanClass 创建一个对象实例, 然后将其添加到 singletonFactories 中(解决依赖循环问题)
8.调用 populateBean() 为对象的字段(属性)注入它所需要的值(可能是@Resource, @Value等); (此时可能会遇到依赖循环问题, 但解决这个问题的缓存在此之前就添加了, 所以不怕)
9.最后调用 initializeBean() 完成 bean 的初始化(调用 bean 的一些方法, 如 afterPropertiesSet), 返回对象实例.

总结: 先根据 type 找到 beanName, 找到后根据 beanName 创建对象; 创建对象前先检查缓存(单例), 再考虑父容器, 最后才是自己创建, 自己创建会先创建 dependsOn 的 bean 对象, 然后才通过反射实例化出一个对象实例(这里反射用到的class和构造方法, 通过实现 SmartInstantiationAwareBeanPostProcessor接口都可进行干预), 实例化后存到二级缓存, 再为字段赋值(注入); 最后调用 bean 的 init 相关的接口(如afterPropertiesSet), 就可以返回这个对象实例了.

超长源码分析过程

// 从这个方法进入@Overridepublic <T> T getBean(Class<T> requiredType) throws BeansException {  // 判断容器的状态, 确保 beanFactory 可用.(主要是若不可用, 提示的错误信息会比getBeanFacgtory()中更准确)  // 使用 beanFactory 的 getBean 方法获取对象并返回.  assertBeanFactoryActive();  return getBeanFactory().getBean(requiredType);}// 然后其他所有涉及的核心方法的注释org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean    // 调用 resolveNamedBean, 如存在 bean 则直接返回. (核心)		// 若不存在则从父容器中寻找, 父容器实现了 DefaultListableBeanFactory 则调与同子容器相同的方法		// 若没实现则 通过 getBeanProvider 获取.  org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)    // 1.调用 getBeanNamesForType 获取所有与 type 相匹配的 beanName 集合.		// 2.遍历判断每个 beanName 是否可用		// 3.若可用的 beanName 只有一个, 则调用 getBean(beanName) 获取对象实例并返回		//   若可用数超过一个, 则试着根据是否主要以及高优先级来确定一个 beanName 实例, 若能确定则返回, 不能则报错.org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean    // 1.获取完整的 beanName		// 2.调用 getSingleton1() 检查是否存在缓存, 这层检查可防止依赖循环.		//     若存在, 则通过 getObjectForBeanInstance() 判断缓存的是 bean 还是 FactoryBean 并返回相应的对象实例.		// 3.若不存在, 先试着从父容器获取(子容器不存在这个 beanDefinition 且父容器不为空)		//     没有父容器则 调用 markBeanAsCreated() 标记这个 bean已经创建了 (先标记, 再创建)		//     获取 beanDefinition, 判断其 dependsOn 属性是否存在, 存在则 先获取依赖的 bean		//     调用 getSingleton2() 处理单例缓存		// 4.而 getSingleton2() 中的闭包中 执行的 createBean() 方法中则才是创建实例并调用 BeanPostProcessororg.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)    // 1.判断是否存在于 singletonObjects 中		// 2.若不存在则判断 bean 是否处于创建中(未创建完成, 如循环依赖时)		// 3.若处于创建中, 则同步后判断是否存在于 earlySingletonObjects (也就是 singletonFactories 移除后存入的地方)		//      (因为FactoryBean占用空间大, 获取对象麻烦且速度更慢, 这是为了防止如果循环依赖链条很长 多次获取浪费CPU的问题)		// 4.不存于 earlySingletonObjects 则代表第一次(也只会有一次)取 singletonFactories		//    取出后调用 getObject() 并将其存入到 earlySingletonObjects, 然后从 singletonFactories 中移除. 以后就少走几行代码了.  org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)    // 1.先确保是第一次创建单例对象, 防止重复创建		// 2.进行一些异常处理		// 3.调用 singletonFactory.getObject() 创建对象		// 4.创建对象结束添加单例缓存和清空 singletonFactories / earlySingletonObjects 缓存.  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])    // 1.调用 resolveBeanClass 解析得到真正的 bean class, 若解析不为空且处于某些情况下, 则复制一份 beanDefinition 并设置 beanClass 为解析所得		// 2.执行 BeanPostProcessor 的 postProcessorsBeforeInstantiation() 方法		// 3.调用 doCreateBean() 创建对象 并返回org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean    // 1.调用 createBeanInstance() 获得一个 对象实例的 包装类		// 2.同步锁下执行 BeanFactoryPostProcessor 的 postProcessMergedBeanDefinition().		// 3.添加 singletonFactories 缓存, 移除 earlySingletonObjects; 解决循环依赖问题.		// 4.调用 populateBean() 检查字段是否需要注入对象实例, 是则获取对应的 bean 注入. (可能引起循环依赖)		// 5.调用 initializeBean() 执行对象的一些 Aware 和 init 方法和 BeanPostProcessor 的 postProcessBeforeInitialization.		// 6.最后返回对象实例.

各种实现的原理

1.为何我写的 class 实现一些接口(如ApplicationContextAware)后并放入容器中, 就可以获取到一些对象(如applicationContext)?2.为何我写的 class 实现 ApplicationListener<XxxEvent> 后并放入容器中, 就能监听我想知道的事件?3.为何Spring中遇到各种顺序问题, 只需要实现 Ordered 接口(或加上@Order注解)就能使其有序?4.Spring是如何解决循环依赖的(指用字段注入而非构造方法)?5.Spring可以用注解替换XML配置文件了, 是如何实现的呢(常用注解的实现原理)?6.Spring AOP是如何实现的(指@Aspect)?7.Spring 事务是如何实现的(指@Transaction)?

为何我写的 class 实现一些接口(如ApplicationContextAware)后并放入容器中, 就可以获取到一些对象(如applicationContext)?

1) 首先 AbstractApplicationContext#prepareBeanFactory 会添加一个ApplicationContextAwareProcessor2) 这个 beanPostProcessor 负责在bean初始化之前注入context对象.3) 这个 beanPostProcessor 的执行时机是在 doCreateBean 中的 postProcessBeforeInitialization()

为何我写的 class 实现 ApplicationListener 后并放入容器中, 就能监听我想知道的事件?

1) 在 AbstractApplicationContext#registerListeners() 中扫描容器内所有相关实现类加入到事件监听者集合中2) 然后在publishEvent时,遍历事件监听者集合调用bean的方法即可。观察者模式!3) 另外也用了BeanPostProcessor去实现, 叫 ApplicationListenerDetector, 加入时机同1, 执行时机同1.4) 至于为何使用2种机制, 应该是因为 registerListeners() 时, 扫描只是当前的, 后续可能容器内的 bean 还会增加(我也猜不到啥形式增加, 反正简单写个类肯定不会), 所以还是需要 ApplicationListenerDetector 在这个 Bean 初始化时加入到监听者中去.

为何Spring中遇到各种顺序问题, 只需要实现 Ordered 接口(或加上@Order注解)就能使其有序?

因为 Spring 预先在执行这些东西之前, 进行一个排序动作, 然后才遍历执行. 包括AOP, BeanFactoryPostProcessor, BeanPostProcessor .

1) 比如说 BeanPostProcesser, 容器扫描后, 会像对bean集合排序, 再遍历执行.2) 详细过程见 PostProcessorRegistrationDelegate#sortPostProcessors()

Spring是如何解决循环依赖的(指用字段注入而非构造方法)?

1) 首先, 假定有两个单例 bean AB, A 持有 B, B 持有A, 构成循环2) 此时程序调用getBean获取A,则在 doCreateBean 中 创建后将 bean 缓存到 singletonFactories 中3) 然后设置属性B, 解析属性, 需要获取B对象4) 获取B, 则执行doCreateBean 后执行解析属性, 需要获取 A对象 (又一次)5) 获取A, 进入 doGetBean 中的 getSingleton, 此时判断 singletonFactories 中有A, 则可以直接取出A6) 获得A, 即可完成B的属性赋值, 然后会完成B的创建.7) B创建完后, A就能获得B,A也完成了属性赋值, 最后完成创建A.8) 到此, 返回即可.> 总结: 首次获取A, 创建A对象后缓存一个存储A对象的 ObjectFactory 实例, 再解析属性时触发 getBean(B), 同理也会做缓存, 然后也解析属性, 触发getBean(A), 第二次获取A, 进入另一个逻辑, 返回 ObjectFactory 实例中存储的对象A, 即可完成getBean(A), 然后完成getBean(B), 再完成外层的getBean(A).    TIPS:步骤4, 会先判断 earlySingletonObjects, 不存在才判断 singletonFactories, 而从 singletonFactories 中取得对象后, 则会将其从 singletonFactories 移除并加入 earlySingletonObjects这是因为 singletonFactories 缓存的 FactoryBean, 若反复调用 getObject(), 则每次获取都会调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference 方法, 而此方法会执行 SmartInstantiationAwareBeanPostProcessorgetEarlyBeanReference(), 这会导致 BeanPostProcessor 重复执行, 显然是不行的.

Spring可以用注解替换XML配置文件了, 是如何实现的呢(常用注解的实现原理)?

1) 首先是指定包名或指定类名	如指定包名则 scan 时会执行, 如指定类名则在构造方法初始化 reader 时执行2) 无论哪种, 最终都会走一段代码 AnnotationConfigUtils#registerAnnotationConfigProcessors()3) 这段代码会添加一些 BeanFactoryPostProcessor	如 ConfigurationClassPostProcessor 负责解析 @Configuration/@Import/@Bean 等注解    	然后由 ConfigurationClassBeanDefinitionReader 负责将信息转换成BeanDefinition再注册到容器。	如 AutowiredAnnotationBeanPostProcessor 负责解析 @Autowired/@Value 注解    如 CommonAnnotationBeanPostProcessor 负责解析 @Resource 注解    解析放在 postProcessProperties() 方法中, 先扫描bean的字段和方法, 然后一一调用方法和为字段注入值4) 之后, 他会将扫描的类放到 beanDefinitions 中(或指定的类注册进去)5) BeanFactory加载完毕后, 回到AbstractApplicationContext的refresh逻辑	如会执行 postProcessBeanFactory(), 调用前面加入的ConfigurationClassPostProcessor	然后会添加更多的类到容器中.    注意事项:    @Configuration 和 @Component的区别?    观察发现,即使使用@Component 其下带 @Bean 的方法依然可以注入到容器中。所以似乎两者没有区别?    仔细查看源码和资料后,发现 postProcessBeanFactory() 方法在 processConfigBeanDefinitions() 后还会调用 enhanceConfigurationClasses()    而在这个方法中, 对前面解析了class 是 CONFIGURATION_CLASS_FULL (即代表@Configuration)的类    会生成一个 cglib 的代理, 这样获取@Bean注解的方法的bean时,不会每次调用方法new 一个, 而是有缓存.

总结: 就是利用 BeanFactoryPostProcessor 可获取 BeanDefinitionRegistry 对象, 然后扫描容器内带有注解的 bean, 解析这些注解得到一些 BeanDefinition, 再通过获得的 BeanDefinitionRegistry对象注册到 BeanFactory 中.

Spring AOP是如何实现的(指@Aspect)?

1) 使用 @EnableAspectJAutoProxy2) @EnableAspectJAutoProxy 中使用了 @Import(AspectJAutoProxyRegistrar.class)3) ConfigurationClassPostProcessor 会解析@Import, 进入 registerBeanDefinitions() 中4) registerBeanDefinitions() 中添加了 AnnotationAwareAspectJAutoProxyCreator 到容器中5) AnnotationAwareAspectJAutoProxyCreator 本质上时一个 BeanPostProcessor6) 因此在 createBean 时, 会被自动调用. 其中 postProcessAfterInitialization() 负责创建代理对象7) 而 getAdvicesAndAdvisorsForBean() 则负责查找对应的增强. 然后会调用子类的findCandidateAdvisors8) 如 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() 负责注解编写增强@Before/@After等9) 简单说下逻辑, 就是查找容器所有类, 判断这个类有没有 @Aspect 注解, 然后先找出所有Pointcut	再遍历所有方法, 找出方法上带有@Before等注解且有关联的Pointcut的方法,    然后使用这个方法和关联的Pointcut 来new 一个Advisor, 加入到Advisor集合中, 遍历结束后返回即可.10) 查找到所有的增强后, 再比较Pointcut表达式是否匹配当前的bean, 如可以则加入.11) 根据找到的Advisor集合, 创建一个带配置(advisor集合等)的代理对象, 代理对象执行方法前12) 会先根据配置中的advisor集合生成一个执行链, 然后在拦截代理方法处调用. 执行链会负责执行通知.13) 不同的通知由不同的适配器执行.

总结就是通过 @EnableAspectJAutoProxy 的@Import, 使得程序最终会执行 AnnotationAwareAspectJAutoProxyCreator 的 postProcessAfterInitialization(对象初始化后调用) 方法, 这个方法在 BeanFactory创建完对象后触发, 此时便可通过 CGlib 等动态代理技术为 创建的 bean 对象创建一个代理对象, 然后这个代理对象会根据 Pointcut 找到关联的 Advisor, 并在合适的时机执行对应的 Advisor, 如 @Before产生的Advisor 会在执行了 bean 对象的指定方法(看Pointcut配置)后执行.

Spring 事务是如何实现的(指@Transaction)?

0) 事务是由AOP实现的, 所以需要找到对应的Pointcut 和 Advisor1) 打开了 @EnableTransactionManagement 注解2) 然后@Import 了 TransactionManagementConfigurationSelector3) 之后导入了 ProxyTransactionManagementConfiguration 到容器中4) ProxyTransactionManagementConfiguration 带有 @Configuration5) @Bean 注入了一个通用的Advisor: BeanFactoryTransactionAttributeSourceAdvisor6) 这个Advisor的 Pointcut 是由 TransactionAttributeSourcePointcut 实现的	实现逻辑是 TransactionAttributeSourcePointcut 的 matches()    这个方法调用了 getTransactionAttributeSource() 获取 AnnotationTransactionAttributeSource    然后通过 getTransactionAttribute() 调用了 findTransactionAttribute()    最终使用SpringTransactionAnnotationParser 类判断方法是否有@Transactional注解    并解析注解信息然后返回. 另外这个方法还可以获取@Transactional注解的信息, 而这里只用于判断是否需要拦截这个方法.7) TransactionInterceptor 是一个Advisor    也可以通过AnnotationTransactionAttributeSource获取@Transactional注解上的信息    然后在invoke中, 拦截方法, 打开事务, 在执行完方法后, 提交事务, 报错时回滚事务    这个 Advisor 不同于传统的前置/后置, 而是更具体的 MethodInterceptor(动态代理直接相关).

总结: 就是基于AOP实现的, 只需找到对应的 Pointcut 和 Advisor 即可. Pointcut 就是根据 @Transaction 注解判断方法是否需要代理, 这个很简单; 比较有意思的是 Advisor 不是我们写AOP那种 @Before,@Around之类的, 而是更接近动态代理原始的语法的 MethodInterceptor 即 TransactionInterceptor.

BeanFactoryPostProcessor 相关类分析

BeanFactoryPostProcessor 生效原理

生效原理就是, ApplicationContext 的 refresh 方法中会扫描出容器中实现了 BeanFactoryPostProcessor 接口的 bean, 将其排序后执行相应的接口, 这样我们写的类实现的相应的接口的方法就被执行了.

常用的 BeanFactoryPostProcessor# ConfigurationClassPostProcessor这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan 等基础注解. 是注解开发的基石, 更是 Spring Boot 的基石.

BeanPostProcessor 相关类分析

BeanPostProcessor 生效原理

在 refresh() 中会扫描容器中所有 实现了 BeanPostProcessor 接口的类, 添加到 BeanFactory 的 beanPostProcessors 字段中(是个List[CopyOnWriteArrayList自定义版, 自定义加入了清空缓存的逻辑]), 然后在 BeanFactory 创建对象时 createBean() 在适当的时机调用对应的方法.

有哪几种 BeanPostProcessor (默认的+扩展)1.InstantiationAwareBeanPostProcessor	postProcessAfterInstantiation: 对象实例化后调用	postProcessBeforeInstantiation: 对象实例化前调用	postProcessProperties: 设置属性值前	postProcessPropertyValues: 设置属性值前, 若上个方法不处理(返回null)才会触发2.SmartInstantiationAwareBeanPostProcessor  predictBeanType: 获取一个 bean 的 class 类型前调用  getEarlyBeanReference: 获取一个二级缓存对象(singletonFactories的getObject)时调用  determineCandidateConstructors: 决定一个 bean 实例化的构造参数是什么时调用	3.DestructionAwareBeanPostProcessor	postProcessBeforeDestruction: 对象销毁前调用	requiresDestruction: 判断这个类针对某个 bean 是否执行 postProcessBeforeDestruction()	4.MergedBeanDefinitionPostProcessor  postProcessMergedBeanDefinition: 在创建对象前调用, 可对 BeanDefinition 做修改  resetBeanDefinition: 在重置 BeanDefinition 时调用, 用于清空 PostProcessor 对应的缓存	5.BeanPostProcessor(基础)  postProcessBeforeInitialization: 创建对象后(也设置好了字段), 在调用 init 之前调用  postProcessAfterInitialization: 在创建对象时, 调用了 init 之后调用  总结: 0.对 BeanDefinition 做干预1.对象实例化过程中(对class/构造参数进行干预)2.对象实例化前后3.对象设置属性前, 对属性做干预4.对象初始化(init)前后5.对象销毁前

调用时机

    // 1.1: InstantiationAwareBeanPostProcessor 的 postProcessAfterInstantiation()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean 第一段		// 1.2: InstantiationAwareBeanPostProcessor 的 postProcessProperties()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean 第二段		// 1.3: InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean 第三段		// 1.4: InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation 中		// 2.1: SmartInstantiationAwareBeanPostProcessor 的 predictBeanType()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType 中		// 2.2: SmartInstantiationAwareBeanPostProcessor 的 getEarlyBeanReference()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getEarlyBeanReference 中		// 2.3: SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors 中		// 3.1: MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition()		//   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors 中		// 3.2: MergedBeanDefinitionPostProcessor 的 resetBeanDefinition()		//   在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resetBeanDefinition 中		// 4.1: DestructionAwareBeanPostProcessor 的 postProcessBeforeDestruction()		//   在 org.springframework.beans.factory.support.DisposableBeanAdapter.destroy 中		// 4.2: DestructionAwareBeanPostProcessor 的 requiresDestruction()		//   在 org.springframework.beans.factory.support.DisposableBeanAdapter.filterPostProcessors 和 org.springframework.beans.factory.support.DisposableBeanAdapter.hasApplicableProcessors 中

😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁

# 有哪些常用的 BeanPostProcessor1.AsyncAnnotationBeanPostProcessor: 用于在将 @Async 相应的 Advisor 加入到对象的代理中2.ScheduledAnnotationBeanPostProcessor: 用于处理 @Scheduled 注解, 将 bean 生产代理类3.AnnotationAwareAspectJAutoProxyCreator: AOP 实现核心类4.AutowiredAnnotationBeanPostProcessor: 用于处理 @Autowired 注解5.ApplicationListenerDetector: 用于处理实现 ApplicationListener 接口的 bean 对象, 将其添加到事件广播器的监听者集合中....
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring 源码分析是一个相对复杂和庞大的话题,无法在一次对话中详细讨论。不过,我可以给你提供一些关于 Spring 源码分析的一般指导和建议。 1. 了解 Spring 的核心模块:Spring 框架是模块化的,每个模块都有不同的功能和职责。在开始源码分析之前,你需要先了解 Spring 的核心模块,如 Spring Core、Spring MVC、Spring Data 等。 2. 阅读官方文档和源码注释:Spring 框架的官方文档和源码注释是你学习和理解源码的重要资源。官方文档提供了对 Spring 各个模块的详细说明,源码注释则解释了代码的作用和实现细节。 3. 调试和跟踪代码:在进行源码分析时,调试器是你的好帮手。通过设置断点、单步跟踪以及观察变量的值,你可以深入理解代码的执行流程和逻辑。 4. 理解设计模式和原理:Spring 框架采用了许多设计模式和原理来实现其功能。在分析源码时,你需要熟悉这些设计模式和原理,例如依赖注入、AOP、工厂模式等。 5. 参考开源社区和博客:Spring 框架是一个非常活跃的开源社区,许多开发者在博客和论坛上分享了他们的源码分析和理解。阅读这些文章可以帮助你更好地理解 Spring 框架的实现细节。 请记住,深入分析 Spring 源码需要耐心和时间投入,同时也需要有一定的 Java 和设计模式的基础。希望这些指导对你有所帮助!如果你有具体的问题或者需要更详细的信息,欢迎继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值