1.Spring是什么

Spring是一款轻量级的开发框架 . 简而言之 Spring提高了开发效率 两个核心 IOC 和 AOP

1.1 IOC ( Inversion of Control ) 是什么

Inversion of Control 控制反转

1.1.1 控制了什么

想象一下如果没有使用spring ,我们要创建一个A对象 它 有属性 id name age 等等 我们是不是需要

new A(id,name,age)

而使用了spring框架后 你所需要的组件没有使用过new 吧 那这个对象 又是谁帮我们创建的呢 又是从哪里来的呢

显而易见的是 对象由spring 帮我们创建的 从容器中获取的 这就是"控制" 控制了 对象的创建以及生命周期的管理

1.1.2 反转了什么

又假如 我们要创建对象A 而又依赖于对象B 没有使用Spring我们通常的做法是 在对象A创建之前创建对象B 而使用了Spring之后 Spring容器能帮我们注入对象A所需要的依赖 这就是反转 反转了 对象与对象之间依赖的获取

1.2 AOP 是什么

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方
式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个
热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑
的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高
了开发的效率。---  百度的解释

2.Spring容器的启动过程

2.1 三种启动Spring容器的方式

(1) 从类的根路径下加载配置⽂件,创建spring容器

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

(2) 从磁盘路径上加载配置⽂件,创建spring容器

ApplicationContext applicationContext =new FileSystemXmlApplicationContext();

(3) 加载注解配置类,创建spring容器

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

2.2 启动过程分析 先看图 ( 使用第一种方式 根路径加载配置文件 )

2.2.1 准备工作

2.2.1.1 创建测试类

/*** @author sz* @DATE 2022/2/25  18:20*/
public class TestBean {public TestBean() {System.out.println("testBean构造方法执行了");}
}

2.2.1.2 创建 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd
"><!--  创建测试bean对象    --><bean id="testBean" class="com.qiuri.sz.TestBean"/></beans>

2.2.1.3 主启动类

 /***  Ioc 容器启动过程分析*/@Testpublic void testAOP() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext-----.xml");TestBean bean = applicationContext.getBean(TestBean.class);}

2.2.2 断点分析

跟进去 来到 ClassPathXmlApplicationContext 类

调用了另外一个构造方法

public ClassPathXmlApplicationContext(String[] configLocations,boolean refresh,@Nullable ApplicationContext parent) throws BeansException {/***调用父类构造*/super(parent);// 2.解析配置文件的路径setConfigLocations(configLocations);// 3.判断是否需要刷新容器if (refresh) {   //true  // 刷新容器refresh();}}

最终执行了 refresh()方法

2.2.3 refresh() 方法分析

org.springframework.context.support.AbstractApplicationContext#refresh

​ 首先可以看到 方法第一行就是个同步代码块 解决线程安全问题

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {prepareRefresh();ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);try {postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory);registerBeanPostProcessors(beanFactory);initMessageSource();initApplicationEventMulticaster();onRefresh();registerListeners();finishBeanFactoryInitialization(beanFactory);finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}destroyBeans();cancelRefresh(ex);throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

2.2.3.1 prepareRefresh()方法 准备上下文刷新工作,记录容器的启动时间以及状态

protected void prepareRefresh() {// 记录启动时间.this.startupDate = System.currentTimeMillis();// 设置容器为未关闭状态this.closed.set(false);// 设置容器为激活状态this.active.set(true);if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);}else {logger.debug("Refreshing " + getDisplayName());}}initPropertySources();// Validate that all properties marked as required are resolvable:* 作用:校验属性*/getEnvironment().validateRequiredProperties();// Store pre-refresh ApplicationListeners...if (this.earlyApplicationListeners == null) {/** 初始化监听器,用于初始化使用 */this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...this.earlyApplicationEvents = new LinkedHashSet<>();}

该方法主要是 准备上下文刷新工作,记录容器的启动时间以及状态

2.2.3.2 obtainFreshBeanFactory()方法 创建beanFactory工厂以及 解析创建BeanDefinition对象

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

跟进去

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();}

跟进 refreshBeanFactory()方法

protected final void refreshBeanFactory() throws BeansException {// 看名字  是否有bean工厂存在if (hasBeanFactory()) {// 如果有bean工厂存在 销毁 beandestroyBeans();// 关闭bean工厂closeBeanFactory();}try {// 创建bean工厂,返回Bean工厂类型是:DefaultListableBeanFactory//return new DefaultListableBeanFactory(getInternalParentBeanFactory());DefaultListableBeanFactory beanFactory = createBeanFactory();// 设置序列化IDbeanFactory.setSerializationId(getId());//设置bean是否可以被覆盖以及是否允许循环引用.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);}}

loadBeanDefinitions(beanFactory) 方法执行前 beanDefinitionMap 为空

loadBeanDefinitions(beanFactory) 方法执行后 beanDefinitionMap 有元素了

其中map的key为 我们xml配置文件中 bean标签的ID 也就是容器中bean的name value 的 beanClass记录了 testBean的全限定类名 com.qiuri.sz.TestBean

在obtainFreshBeanFactory 获取Bean工厂,解析bean定义信息.生成BeanDefinition对象,存入BeanDefinitionMap中

2.2.3.3 prepareBeanFactory(beanFactory)方法 设置bean工厂的属性

 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {beanFactory.setBeanClassLoader(getClassLoader());// 设置SPEL解析器beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 添加属性编辑注册器beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 添加bean的后置处理器。此处添加的是Spring自己的后置处理器,用来回调bean所实现的aware接口中的方法.beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 下面的ignoreDependencyInterface是用来设置bean工厂中需要忽略的接口beanFactory.ignoreDependencyInterface(EnvironmentAware.class);// 可以通过实现EmbeddedValueResolverAware接口来获取String类型值的解析器beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);// 资源加载器,例如使用:@Autowired ResourceLoaderAware aware; 将不会被注入beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);// 事件发布器beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);// 消息资源beanFactory.ignoreDependencyInterface(MessageSourceAware.class);// 应用的上下文信息beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);// 注册一些可以自动装配的接口。 当类型为dependencyType时, 注入autowiredValue。为了解决一个类型有多个子类实现时,优先注入那个子类实现的问题。// 例如下面第一个,当注入类型为BeanFactory时,注入的值为beanFactory,默认为DefaultListableBeanFactorybeanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);// 当注入类型为ResourceLoader时,注入的值为ApplicationContextbeanFactory.registerResolvableDependency(ResourceLoader.class, this);// 当注入类型为ApplicationEventPublisher时,注入的值为ApplicationContextbeanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);// 当注入的类型为ApplicationContext时,注入的值为ApplicationContext.beanFactory.registerResolvableDependency(ApplicationContext.class, this);// 增加一个bean的后置处理器,ApplicationListenerDetector// Register early post-processor for detecting inner beans as ApplicationListeners.beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.// 如果bean工厂中存在着名称为loadTimeWeaver的bean定义,则给bean工厂中加入LoaderTimeWeaverAwareProcessor后置处理器// 补充:1、增加对AspectJ的支持,在Java中织入分为3种:(1) 编译期织入; (2) 类加载期织入; (3) 运行期织入。编译期织入指的是在java编译期,//         采用特殊的编译器,将切面织入到java类中;类加载期织入则指的是通过特殊的类加载器,在字节码加载到JVM时,织入切面;运行期织入则是//         通过采用cglib或者jdk进行切面的织入。//      2、aspectJ中提供了两种方式://         (1) 通过特殊编译器,在编译期,将aspectJ语言编写的切面类织入到java类中;//         (2) 类加载期织入,就是通过下面的LoadTimeWeavingif (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()));}// 给容器中注册一些与运行环境相关的单实例Beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {// beanName: environment,直接将new出来的Spring内部对象放入到Spring的单实例缓存池中.beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {// beanName: systemProperties   方法:System.getProperties();beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {// beanName: systemEnvironment,   方法:System.getEnv();beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}

2.2.3.4 postProcessBeanFactory(beanFactory) 空方法,bean定义信息加载完成后执行,可以用来修改beanFactory中定义的bean定义信息

 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}

2.2.3.5 invokeBeanFactoryPostProcessors(beanFactory) 执行 BeanFactory的后置处理器方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 执行Bean工厂的所有后置处理器PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

我们没有BeanFactory的后置处理器,所以方法跟进去后if判断直接跳过

2.2.3.6 registerBeanPostProcessors(beanFactory) 注册(不是执行)Bean的后置处理器

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

2.2.3.7 initMessageSource() 消息国际化

protected void initMessageSource() {// 获取bean工厂ConfigurableListableBeanFactory beanFactory = getBeanFactory();// 判断是否在bean工厂中定义了id为messageSource的bean对象if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {// 如果有id为messageSource,而且类型是MessageSource的组件,直接赋值给messageSource属性this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// Make MessageSource aware of parent MessageSource.if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;if (hms.getParentMessageSource() == null) {// Only set parent context as parent MessageSource if no parent MessageSource// registered already.hms.setParentMessageSource(getInternalParentMessageSource());}}if (logger.isTraceEnabled()) {logger.trace("Using MessageSource [" + this.messageSource + "]");}}else {// Use empty MessageSource to be able to accept getMessage calls.// 如果没有,则创建一个DelegatingMessageSource类型的messageSource对象DelegatingMessageSource dms = new DelegatingMessageSource();dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;// 将messageSource注册到容器中,在获取国际化配置文件中的某个值时,可以直接通过注入MessageSource,// 调用其getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale)方法来获取.beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);if (logger.isTraceEnabled()) {logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");}}}

2.2.3.8 initApplicationEventMulticaster() 初始化上下文事件派发器

protected void initApplicationEventMulticaster() {// 获取Bean工厂ConfigurableListableBeanFactory beanFactory = getBeanFactory();// APPLICATION_EVENT_MULTICASTER_BEAN_NAME =  applicationEventMulticaster// 判断当前的bean工厂中有没有id为applicationEventMulticaster的事件派发器if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {// 如果有,则直接获取到ApplicationEventMulticaster类型的事件多播器,并赋值给applicationEventMulticaster.this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isTraceEnabled()) {logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else {// 如果没有则创建一个类型为SimpleApplicationEventMulticaster事件监听器,this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);// 将创建的事件多播器注册到容器中,在其他组件需要派发事件时,直接获取这个applicationEventMulticasterbeanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isTraceEnabled()) {logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");}}}

2.2.3.9 ionRefresh() 初始化特殊的Bean,通过继承AbstractApplicationContext类,重写该方法完成自定义特殊bean的初始化.

 protected void onRefresh() throws BeansException {//空,什么也没有,留给我们去实现  SpringBoot也是在改步骤中启动内嵌Tomcat容器的}

2.2.3.10 registerListeners() 注册监听器

protected void registerListeners() {// 将注册的监听器绑定到广播器for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// 根据类型获取listener监听器的名称String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {// 将事件监听器注册到派发器中,以后使用的时候,就可以直接通过事件派发器执行.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}/*** 派发之前产生的事件。* earlyApplicationEvent是在prepareRefresh中声明的.*/Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}

2.2.3.11 finishBeanFactoryInitialization(beanFactory) 初始化所有的单例bean (核心)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 1. 初始化此上下文的转换服务,用来自定义将Spring中的某个Bean的属性从一个类型转换到另外一个类型.//    判断Bean工厂中是否存在名称为conversionService的转换服务bean,如果存在而且类型为ConversionService,则获取该Bean实例,并将其设置到BeanFactory中if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)&& beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}if (!beanFactory.hasEmbeddedValueResolver()) {// 调用resolvePlaceholders方法解析strVal对应的值beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// 停止使用临时的类加载器.beanFactory.setTempClassLoader(null);// 缓存(冻结)所有的BeanName(注册的bean定义不会被修改或进一步做处理了,因为下面马上要创建Bean的实例对象了)beanFactory.freezeConfiguration();// 初始化所有的单实例Bean,包括创建单实例bean的全部过程beanFactory.preInstantiateSingletons();}
直接看 beanFactory.preInstantiateSingletons()方法 跟进去
public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// 创建beanName集合List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 遍历所有的beanNames,创建所有的单实例Beanfor (String beanName : beanNames) {// 获取beanName对应的MergedBeanDefinition.    BeanDefinitionMap的value  key为beanName   不记得了可以看  2.2.3.2RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 如果bd对应的Bean实例满足:(不是抽象类 && 是单例 && 不是懒加载)if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 判断BeanName对应的Bean实例是否是FactoryBean.if (isFactoryBean(beanName)) {// 通过beanName获取FactoryBean的实例,factoryBean的名称是:"&" + beanNameObject bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;// 判断这个FactoryBean是否需要紧急初始化.if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {// 如果需要紧急初始化,则通过beanName获取Bean的实例.getBean(beanName);}}}else {// 如果BeanName对应的Bean实例不是FactoryBean,则通过BeanName去获取Bean实例.getBean(beanName);}}}/*** 上一步for循环中已经创建完了所有的单实例Bean,这个for循环中,会拿出所有的单实例Bean,*   然后遍历,判断单实例bean是否实现了SmartInitializingSingleton接口,如果实现了该接口,*   则调用单实例Bean的afterSingletonsInstantiated方法*/for (String beanName : beanNames) {// 获取beanName对应的bean实例Object singletonInstance = getSingleton(beanName);// 判断当前的bean是否实现了SmartInitializingSingleton接口.if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;// 触发SmartInitializingSingleton实现类的afterSingletonInstantiated方法.if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {/*** 如果实现了SmartInitializingSingleton接口,则会调用afterSingletonInstantiated方法*   例如@EventListener注解的实现原理,就是利用EventListenerMethodProcessor后置处理器完成的,*   而在EventListenerMethodProcessor中就是实现了SmartInitializingSingleton接口*/smartSingleton.afterSingletonsInstantiated();}}}}
跟进getBean(beanName)方法 org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
@Overridepublic Object getBean(String name) throws BeansException {// 空方法return doGetBean(name, null, null, false);}
继续跟进 doGetBean方法 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean ( Spring循环依赖问题在此解决)
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取真正的BeanName。主要包括:(1) 去掉FactoryBean名称前面的&前缀;(2) bean别名解析;final String beanName = transformedBeanName(name);Object bean;// 先尝试从缓存中获取单实例Bean,如果能获取到,说明已经被创建过//   注意:如果是通过FactoryBean方式创建对象。在根据名称获取目标bean对象(非FactoryBean实例)时,此处返回的sharedInstance是FactoryBean对象Object sharedInstance = getSingleton(beanName);/*** 当组件实现了FactoryBean接口,并重写了getObject方法时。在从容器中获取bean的时候,sharedInstance就是容器中返回的bean对象* 此时sharedInstance不为空,就会调用getObjectForBeanInstance方法,这个方法内部会调用子类重写的getObject方法.*/if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}// 获取bean对象,包括使用FactoryBean来创建bean的逻辑.bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// 如果当前创建的是单实例类型的bean,则尝试解决循环依赖,此处仅仅只是一个校验;如果当前的多实例bean正在创建中,而且存在循环依赖,直接抛出异常if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 获取Bean的父工厂BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}// 标记Bean已经被创建,防止多线程时,Bean可能会被创建多个,就不是单实例了if (!typeCheckOnly) {// 将beanName对应的bean定义从mergedBeanDefinitions中移除,并将beanName添加到alreadyCreated集合中.markBeanAsCreated(beanName);}try {// 获取合并之后的Bean定义final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 校验bean对应的类是否为抽象的,如果bean对应的类标注了抽象,直接会抛出异常checkMergedBeanDefinition(mbd, beanName, args);/*** 获取当前Bean所依赖的其他Bean解决循环依赖问题*/String[] dependsOn = mbd.getDependsOn();// 如果有依赖的Beanif (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// 维护依赖和被依赖的bean之间的关联关系registerDependentBean(dep, beanName);try {// 先去创建当前bean所依赖的其他bean对象getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// bean定义如果是单例的,则调用createBean方法进行单实例bean的创建.if (mbd.isSingleton()) {// 此处的lambda表达式为:ObjectFactory的getObject方法sharedInstance = getSingleton(beanName, () -> {try {/*** 创建对象并初始化,Spring用来创建Bean实例的核心方法*  此处调用的子类AbstractAutowireCapableBeanFactory的createBean方法.*/return createBean(beanName, mbd, args);}catch (BeansException ex) {// 如果创建单实例bean失败,则会删除关于该bean的一切信息,包括三级缓存和已经注册的bean集合中有关该bean的信息destroySingleton(beanName);throw ex;}});/*** 如果一个类实现了FactoryBean接口,回调FactoryBean的getObject自定义方法进行应用bean的创建工作*/bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 当前需要创建的bean如果是多例else if (mbd.isPrototype()) {// 创建多实例beanObject prototypeInstance;try {// 进行多实例bean创建之前的准备工作,将当前正在创建的多实例bean的名称添加到prototypesCurrentlyInCreation中.beforePrototypeCreation(beanName);// 创建多实例对象,和创建单实例bean使用的是同一个方法prototypeInstance = createBean(beanName, mbd, args);}finally {// 从prototypesCurrentlyInCreation【ThreadLocal】中移除afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}// 未明确指定将要创建的bean是单例的还是多例的else {String scopeName = mbd.getScope();// 从bean定义中获取bean的scope信息,如果bean的scope信息为null,也就是随意设置的scope,直接抛出异常final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {// 根据指定的scope获取bean实例Object scopedInstance = scope.get(beanName, () -> {// 初始化之前准备工作,将bean的名称添加到prototypesCurrentlyInCreationbeforePrototypeCreation(beanName);try {// 创建bean实例return createBean(beanName, mbd, args);}finally {// 从prototypesCurrentlyInCreation中移除afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}/*** 判断是否需要将bean转换为我们指定类型的Class,如果需要转换,则使用自定义的TypeConverter进行bean类型的转换*  如果未指定TypeConverter,则默认使用SimpleTypeConverter,converter需要设置一个用来转化的Service实现类,即:ConversionService,*  ConversionService是在finishBeanFactoryInitialization方法的最前面进行注册的,可以在xml中配置对应的ConversionService实现类*/if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}
跟进 createBean(beanName, mbd, args)方法 创建实例对象
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {// 删除之前工厂bean缓存中的工厂bean对象,重新进行实例化.instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// 创建Bean的实例,并且包装为一个包装对象返回.if (instanceWrapper == null) {// 使用策略方法创建实例,包括:工厂方法,构造函数注入,简单初始化.// TODO 里面调用的方法超级长instanceWrapper = createBeanInstance(beanName, mbd, args);}// 获取新创建的bean对象和对应的classfinal Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {// 如果还未执行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法if (!mbd.postProcessed) {try {// 依次调用所有MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法,用来处理类中使用注解标注的属性,并放入到缓存中./*** 其中包括了*  【AutowiredAnnotationBeanPostProcessor】,  用来处理@Autowired,@Value,@Inject注解*    【CommonAnnotationBeanPostProcessor】,    用来处理@Resource注解*     【RequiredAnnotationBeanPostProcessor】, 用来处理@Required注解*  【InitDestroyAnnotationBeanPostProcessor】,用来处理@Predestroy和@PostConstruct注解*   【ScheduledAnnotationBeanPostProcessor】,用来处理@Scheduled注解*         等后置处理器*/applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}/*** 当前的bean是单例的 && 允许bean之间的循环依赖 && bean正在创建中*/boolean earlySingletonExposure = (mbd.isSingleton()&& this.allowCircularReferences&& isSingletonCurrentlyInCreation(beanName));// 判断是否需要提前暴露自己。如果需要提前暴露,会将创建完但未填充属性和初始化的bean放入到singletonFactories中,用来解决循环依赖.//         Spring中的单实例Bean,而且是使用属性注入的方式,默认支持循环依赖的;如果是prototype类型的,默认不支持循环依赖//     如果是单例bean,而且使用构造器注入的方式,默认不支持循环依赖,可在构造器上添加@Lazy注解,让依赖的属性延迟初始化来解决//     如果是单例bean和prototype类型的bean混用,则如果先创建单例,可以成功,如果先创建prototype类型的bean,则会失败if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}/*** getEarlyBeanReference: 是用来获取到被SmartInstantiationAwareBeanPostProcessor后处理器处理过的刚刚实例化结束的bean对象** addSingletonFactory: 是用来将刚刚初始化的bean对象放入到singletonFactories中,singletonFactories是个map集合,*  key: bean的名称,value: 是一个ObjectFactory,当存在着循环依赖时,可以通过ObjectFactory.getObject方法获取到刚刚实例化的bean对象*/addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}/** 初始化单实例bean。 包括:填充属性及执行初始化方法 */Object exposedObject = bean;try {/*** 【依赖注入】* 填充的属性包括:普通属性和使用@Autowired和@Resource注解标注的引用类型属性的赋值。使用了反射操作set方法完成赋值.** eg: 重点操作举例:*      【创建完成Bean之后,填充Bean的属性,填充过程中会调用InstantiationAwareBeanPostProcessorAdaptor类的postProcessProperties方法】*/populateBean(beanName, mbd, instanceWrapper);/*** 完成Bean的初始化(执行afterPropertiesSet和init-method)*       注意:会调用@PostConstruct标注的方法,这个方法是在Bean创建完成,而且属性填充完成之后,才会被调用*/exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}try {/*** 注册bean的销毁方法,如果bean不是prototype类型,而且requiresDestruction方法返回true*  则会将当前的bean放入到一个需要被销毁的map集合中.*/registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

**addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); ** 把实例对象放入三级缓存中

getSingleton(String beanName) 缓存中获取Bean (解决循环依赖)

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

public Object getSingleton(String beanName) {// 从缓存中获取单实例Beanreturn getSingleton(beanName, true);}

继续根据 getSingleton(beanName, true);

protected Object getSingleton(String beanName, boolean allowEarlyReference) {//首先从一级缓存  singletonObjects中  尝试获取beanObject singletonObject = this.singletonObjects.get(beanName);// 一级缓存中都是以及初始化完成的单例bean  如果一级没有,可能在二级缓存 earlySingletonObjects  也就是半成品bean 正在初始化的if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {// 加锁操作.synchronized (this.singletonObjects) {//尝试从二级缓存中获取半成品beansingletonObject = this.earlySingletonObjects.get(beanName);// 如果早二级缓存中没有,而且允许创建早期单实例对象引用if (singletonObject == null && allowEarlyReference) {// 则从三级缓存中获取BeanName对应的单例工厂.ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 如果存在着单例对象工厂,则通过工厂创建一个单例对象,// 调用的是:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))中的lombda表达式singletonObject = singletonFactory.getObject();// 将单例工厂对象创建的bean放到二级缓存  earlySingletonObjects中this.earlySingletonObjects.put(beanName, singletonObject);// 删除三级缓存中的bean对应的工厂对象this.singletonFactories.remove(beanName);}}}}//返回bean单例对象return singletonObject;}

3.循环依赖问题

3.1什么是循环依赖

依赖注入的时候 ,发现A 依赖于B 而B依赖注入的时候发现依赖于A 两者都需要依赖于对方完成属性注入

3.2 Spring中的三级缓存

一级缓存 singletonObjects 存放已经完成实例化的单例bena 本质是一个 ConcurrentHashMap

二级缓存 earlysingletonObjects 存放半成品单例Bean ( 已经实例化,未完成初始化 ) 本质是一个 HashMap

三级缓存 singletonFactorie 存放bean工厂对象 本质是一个HashMap

源码 可以看 getSingleton(String beanName) 缓存中获取Bean

3.3 spring是如何解决循环依赖的

sping在初始化一个bean对象时,会看这个bean是有有依赖的其他bean ,如果有 先初始化依赖的bean ,依赖的bean对象完成初始化后,再来初始化当前bean

具体详细过程:

1,A创建过程中需要B,于是A将自己放到三级缓里面,去实例化B

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

2,B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A

3,B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)

然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A自己放到一级缓存里面。

         ⭐️秋日的晚霞⭐️⭐️玲珑骰子安红豆 入骨相思知不知⭐️												

【Spring】SpringIOC容器启动过程源码分析 以及 循环依赖问题相关推荐

  1. SpringBoot2 | SpringBoot启动流程源码分析(一)

    首页 博客 专栏·视频 下载 论坛 问答 代码 直播 能力认证 高校 会员中心 收藏 动态 消息 创作中心 SpringBoot2 | SpringBoot启动流程源码分析(一) 置顶 张书康 201 ...

  2. Android系统默认Home应用程序(Launcher)的启动过程源码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还须要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...

  3. Activity启动流程源码分析-浅析生命周期函数

    源码分析 接着上一篇 Activity启动流程源码分析-setContentView源码阅读 的讲解,本节介绍一下Activity的生命周期函数何时被调用 要看Activity的生命周期函数何时被调用 ...

  4. Activity启动流程源码分析(基于Android N)

    Activity启动流程源码分析 一个Activity启动分为两种启动方式,一种是从Launcher界面上的图标点击启动,另一种是从一个Activity中设置按钮点击启动另外一个Activity.这里 ...

  5. Spring源码分析系列-循环依赖和三级缓存

    目录 循环依赖 多级缓存 一级缓存 二级缓存 当循环依赖遇上AOP 三级缓存 Spring三级缓存源码实现 总结 循环依赖   BeanFactory作为bean工厂管理我们的单例bean,那么肯定需 ...

  6. Spring Boot启动过程源码分析--转

    https://blog.csdn.net/dm_vincent/article/details/76735888 关于Spring Boot,已经有很多介绍其如何使用的文章了,本文从源代码(基于Sp ...

  7. Activity启动过程源码分析

    老罗的Android系统源码分析讲的很不错,网上有很不同层面多源码分析.了解细节,还是自己看源码最直接.个人并没有透彻的研究过Android系统,这一系列的博客就当是读Android源码笔记了.有不对 ...

  8. DataNode启动流程源码分析

    我们都知道在Hadoop hdfs文件系统中,Datanode是负责hdfs文件对应的数据块存储管理的组件,其会在启动时向NameNode汇报其上拥有的数据块,以及周期性心跳并接收来自NameNode ...

  9. spring源码分析04-spring循环依赖底层源码解析

    1. 什么是循环依赖 很简单,就是A对象依赖了B对象,B对象依赖了A对象. // A依赖了B class A{public B b; }// B依赖了A class B{public A a; } 如 ...

最新文章

  1. C++:将char*指针强制转换成一个指向结构体的指针
  2. webpack v3 结合 react-router v4 做 dynamic import — 按需加载(懒加载)
  3. 谈一谈:抽象工厂+反射+配置文件 实现数据访问程序
  4. sparksql删除MySQL数据_Databricks 第6篇:Spark SQL 维护数据库和表
  5. 产品经理必须要了解的经济学原理--“口红效应”
  6. SQL CE 3.0 与SQL CE 3.5区别
  7. linux-shell命令之mkdir(make dir)【创建目录】
  8. leetcode130. 被围绕的区域(bfs)
  9. MySQL中事务控制语句_Mysql事务控制语言
  10. 上项线体表位置_心理成熟的人都有哪些具体表现呢?
  11. 各路由协议防环机制汇总(一)
  12. repair table accessright
  13. ARIMA模型的定阶原理与建模分析
  14. forward和include的区别详解
  15. UnityEditor之VisualElement的样式uss的背景颜色和字体设置
  16. Fabric.js 上划线、中划线(删除线)、下划线
  17. HEVC解码器HM源码阅读(二)解码器中类的介绍
  18. 3650m5设置u盘启动_联想启天M415设置u盘启动步骤(支持uefi/bios双启动)
  19. Ubuntu高分屏下Matlab工具栏字体过小
  20. HTML+CSS+JAVASCRIPT简介

热门文章

  1. [PDF]我们经常使用的PDF是什么? PDF, PDF/A, PDF/Archive, OFD
  2. 深度之眼Paper带读笔记1:Deep learning
  3. java 风的角度转风向
  4. 云厂商下一块必争之地就是它了!
  5. 2021安道拓企业研究数据报告_爱普搜汽车
  6. 关于谷歌浏览器74以上无法自动加载flash问题的解决
  7. scala编程_Scala可以带回编程的喜悦吗?
  8. larvael 8 联表查询
  9. 笔试题-搜狐手机网Python开发工程师
  10. 对抗样本学习笔记:Adversarial Examples: Attacks and Defenses for Deep Learning