spring-ioc源码浅析

1 说明

  1. 本文只是作为阅读spring源码梳理,没有太多源码贴进来;
  2. 梳理的只是个人认为比较重要的点
  3. 入口是机遇注解的spring容器,用的是 AnnotationConfigApplicationContext

2 使用

2.1 pom文件

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.9</version>
</dependency>

2.2 配置类

package spring.kewen.ding.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "spring.kewen.ding.bean")
public class DingConfig {
}

2.3 bean

package spring.kewen.ding.bean;

import org.springframework.stereotype.Component;

@Component
public class DingBean {
    public String name = "dingkewen";
}

2.4 启动类与使用

package spring.kewen.ding;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import spring.kewen.ding.bean.DingBean;
import spring.kewen.ding.config.DingConfig;

public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(DingConfig.class);
        DingBean dingBean = (DingBean)acac.getBean("dingBean");
        System.out.println(dingBean.name);
    }
}

3 源码入口

3.1 启动类构造函数说明

org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class<?>…)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	/*
	// this()方法中的重点代码
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	1.this()
	1.this()中看似只调用了两个方法,但是其实还有一个super(),super()中有各种受气的创建,比如:DefaultListableBeanFactory等
	1.2. new AnnotatedBeanDefinitionReader(this) 除了创建reader,初始化registry等最重要的一点还有向beanDefs中设置各种spring自定义的各种PostProcessor
	1.3. new ClassPathBeanDefinitionScanner(this)初始化扫描器
	*/
	this();
	/*
	2.register(componentClasses);//将自定定义的,并且传入到到启动容器中的配置类注册到BeanDefinition池中
	最重要方法: this.beanDefinitionMap.put(beanName, beanDefinition);
	*/
	register(componentClasses);
	/*
	扫描所有文件,拿到因该被spring容器管理的类,注册到BeanDefinition池中,再从池中取出,创建spring中的bean对象,并缓存
	下面进行重点解析
	*/
	refresh();
}

3.2 刷新方法说明(包含容器创建大部分功能,还有的功能在上面的构造方法中)

3.2.1 org.springframework.context.support.AbstractApplicationContext#refresh

重点关注方法:

  1. invokeBeanFactoryPostProcessors(beanFactory);//执行所有BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor
  2. registerBeanPostProcessors(beanFactory);// 将所有的 BeanPostProcessors 创建对象,放到单例池中;并且注册到beanfactory中(存在 private final List beanPostProcessors = new BeanPostProcessorCacheAwareList();)
  3. finishBeanFactoryInitialization(beanFactory);// 根据所有的beandefinition创建对象,放到单例池中
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

		/*
		1. 设置容器激活标志,并初始化一些变量比如监听器容器等
		*/
		// Prepare this context for refreshing.
		prepareRefresh();

		/*
		2. 给spring容器设置序列化id,并返回容器(DefaultListableBeanFactory)
		*/
		// Tell the subclass to refresh the internal bean factory.
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		/*
		向容器中添加postProsser
		并且注册(是不是一部分,没有具体来找)前面放在BeanDefinition池中的benadefinition(直接跳过一级缓存,二级缓存,进入三级缓存),忽略一些接口
		*/
		// Prepare the bean factory for use in this context.
		prepareBeanFactory(beanFactory);

		try {
			/*
			什么也没有做,只是一个空方法,留待子类扩展
			*/
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			
			/*

			说明:
				1)先执行所有的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
				2)再执行 BeanFactoryPostProcessor#postProcessBeanFactory(这个先分成两大类,一种仅仅是BeanFactoryPostProcessor 还有一种是BeanDefinitionRegistryPostProcessor 因为BeanDefinitionRegistryPostProcessor implements BeanFactoryPostProcessor)
				3)每个右分成三种,没有继承排序接口,继承Ordered,继承 PriorityOrdered,执行顺序是PriorityOrdered,Ordered到没有继排序接口的
				4)防止重复执行,有一个 processedBeans 集合来保存beanName
			执行顺序:
				1)先执行传入的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
				2)到BeanDefinations中找BeanDefinitionRegistryPostProcessor和PriorityOrdered,然后执行 postProcessBeanDefinitionRegistry
				3)到BeanDefinations中找BeanDefinitionRegistryPostProcessor和Ordered,然后执行 postProcessBeanDefinitionRegistry
				4)到BeanDefinations中找BeanDefinitionRegistryPostProcessor然后执行 postProcessBeanDefinitionRegistry
				5)所有在容器中找都会判断不能在processedBeans出现并且每次找到了也要放到processedBeans中
				5)然后执行BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
				6)到容器中拿BeanFactoryPostProcessor
				7)循环,排除已经在processedBeans的,按照排序接口分类
				8)然后执行BeanFactoryPostProcessor#postProcessBeanFactory
			*/
			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors(beanFactory);

			/*
			找到所有的BeanPostprocessors,
			1)放到单例池中;
			2)并且注册到beanfactory中(存在 private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();)
			*/
			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();

			/*
			初始化国际化相关bean(name必须是messageSource),如果有就用自己的,如果没有就用默认的(DelegatingMessageSource)
			*/
			// 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();
			contextRefresh.end();
		}
	}
}

3.2.2 ConfigurationClassPostProcessor特别说明

ConfigurationClassPostProcessor 是 BeanDefinitionRegistryPostProcessor的实现类之一,在 postProcessBeanDefinitionRegistry方法中对传入的文件夹进行扫描,根据class对象生成BeanDefinition (包括解析各种注解,比如import等)

1)执行链路(从ConfigurationClassPostProcessor开始,到拿到class文件):
    postProcessBeanDefinitionRegistry:247, ConfigurationClassPostProcessor (org.springframework.context.annotation)
        processConfigBeanDefinitions:331, ConfigurationClassPostProcessor (org.springframework.context.annotation)
            parse:175, ConfigurationClassParser (org.springframework.context.annotation)
                parse:207, ConfigurationClassParser (org.springframework.context.annotation)
                    processConfigurationClass:250, ConfigurationClassParser (org.springframework.context.annotation)
                        doProcessConfigurationClass:296, ConfigurationClassParser (org.springframework.context.annotation)
                            parse:132, ComponentScanAnnotationParser (org.springframework.context.annotation)
                                doScan:276, ClassPathBeanDefinitionScanner (org.springframework.context.annotation)
                                    findCandidateComponents:315, ClassPathScanningCandidateComponentProvider (org.springframework.context.annotation)
                                        scanCandidateComponents:429, ClassPathScanningCandidateComponentProvider (org.springframework.context.annotation)
2)简述过程
1.找到传入的配置文件,解析注解@ComponentScan 拿到传入的包名,
2.根据包名和classpath等,定位到文件夹,
3.找到文件下所有文件,封装成resource
4.根据resource和classlaod 通过asm框架,生成 MetadataReader (这里面有class,拿到了class,也就能拿到注解等了)
5.将MetadataReader根据条件(有没有某些注解等)转换成 BeanDefinition 缓存起来

3.3 对象创建说明(普通的没有引用的对象的创建)

说明:

  • org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization(调用链路实在太长,就不一个一个贴代码了,只说重要的地方调用)
  • 按照spring的bean的生命周期顺序来说明
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(spring生命周期前半段创建对象~使用基本都逃不过这个方法)

下面按照生命周期以及调用生命周期的方法以及关键代码进行说明

  1. 构造方法
    推导构造方法的方法:
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance;
    上面方法中,如果我们的bean没有构造方法,会调用 return ctor.newInstance(argsWithDefaultValues);最终一步步点下去(比较简单,就没有一步步写了)调用如下方法:
    return ctor.newInstance(argsWithDefaultValues);
  2. 执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法
实现类功能
CommonAnnotationBeanPostProcessor解析注解@PostConstruct,@PreDestroy和@Resource
AutowiredAnnotationBeanPostProcessor解析注解@Autowrite和@Value
ApplicationListenerDetector记录当前beanDefination是不是单例
简单说明解析@Resources注解和@Autowrite注解
  • @Resource org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata中会把复合的字段或方法组合成 ResourceElement 放到 List<InjectionMetadata.InjectedElement> elements中
  • @Autowrite org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata中会把字段或方法组合成 AutowiredFieldElement 放到 List<InjectionMetadata.InjectedElement> elements 中
  1. 放入三级缓存
    这个方法org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean中
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  2. 根据InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation判断要不要继续往下执行
实现类功能
ConfigurationClassPostProcessor扫描文件转换成BeanDefinition,前面有说过了
AnnotationAwareAspectJAutoProxyCreatoraop创建代理,到aop中具体说明
CommonAnnotationBeanPostProcessor@Resource 依赖注入,详情见下面
AutowiredAnnotationBeanPostProcessor@Autowrite 依赖注入,详情见下面

依赖注入用到的最终方法是java.lang.reflect.Field#set
重点在于怎么拿到该设置的值

  1. 调用InstantiationAwareBeanPostProcessor#postProcessProperties给需要依赖注入的字段设置属性(还是上面的几个实现类),尤其是CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor
  2. BeanNameAware
  3. BeanClassLoaderAware
  4. BeanFactoryAware
  5. BeanPostProcessor#postProcessBeforeInitialization(@PostConstruct修饰的方法在InitDestroyAnnotationBeanPostProcessor中被调用,属于BeanPostProcessor)
  6. InitializingBean#afterPropertiesSet
  7. BeanPostProcessor#postProcessAfterInitialization
  8. 放入第一级缓存

  1. 销毁 先执行 加注解@PreDestroy的 DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
  2. DisposableBean#destroy

3.4 CommonAnnotationBeanPostProcessor(@Resource拿依赖的调用链路)

/**
重要的功能是依赖注入    InstantiationAwareBeanPostProcessor#postProcessProperties
 */
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

/**
这里循环到 CommonAnnotationBeanPostProcessor
*/
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessProperties


/**
InjectionMetadata
*/
org.springframework.beans.factory.annotation.InjectionMetadata#inject


/**
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement(CommonAnnotationBeanPostProcessor解析@Resource时创建的对象)
*/
org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject

/**
CommonAnnotationBeanPostProcessor.ResourceElement
*/
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject

/**
CommonAnnotationBeanPostProcessor
*/
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#getResource

/**
CommonAnnotationBeanPostProcessor
*/
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#autowireResource

/**
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeanByName
*/
resolveBeanByName:461, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

/**
AbstractBeanFactory
*/
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class<T>)

3.5 AutowiredAnnotationBeanPostProcessor(@Autowired拿依赖的调用链路)

/**
重要的功能是依赖注入    InstantiationAwareBeanPostProcessor#postProcessProperties
 */
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

/**
这里循环到 AutowiredAnnotationBeanPostProcessor
*/
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessProperties

/**
InjectionMetadata
*/
org.springframework.beans.factory.annotation.InjectionMetadata#inject

/**
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement
(CommonAnnotationBeanPostProcessor解析@Autowrite时创建的对象)
*/
org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject

/**
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement
*/
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue

/**
DefaultListableBeanFactory
*/
org.springframework.beans.factory.config.AutowireCapableBeanFactory#resolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set<java.lang.String>, org.springframework.beans.TypeConverter)

/**
DefaultListableBeanFactory
*/
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

/**
DependencyDescriptor
*/
org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate

/**
AbstractBeanFactory
*/
org.springframework.beans.factory.BeanFactory#getBean(java.lang.String)

4 三级缓存说明

4.1 哪三级缓存,存的分别是什么

  • private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    第一级缓存,存放的是已经给变量赋值好的bean,拿出来就可以用的
  • private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
    第二级缓存,存放的虽然是我们取出时的对象,但是并没有进行依赖注入
  • private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    第三级缓存,存放的是ObjectFactory
    大概是这么放的 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));(可以自己定义创建对象的细节,比如动态代理也是从这个方法进入的)

4.2 每一级缓存是什么时候放的

情况一:没有循环依赖(没有用到第二级缓存)
1.创建对象
2.组装成ObjectFactory,放到第三级缓存
3.给对象设置属性等操作
4.从第三级缓存中取出对象(删除第三级缓存),放入第一级缓存

情况二:有循环依赖(A与B相互引用)

// A
public class A{
	@Autowrite
	private B b;
}

// B
public class B{
	@Autowrite
	private A a;
}

1.创建对象A
2.将对象A组装成ObjectFactory,放到第三级缓存
3.给A对象设置属性值(需要对象B,但是对象B暂时不存在,所以没有办法设置,要去创建B)
4.创建对象B
5.将对象B组装成ObjectFactory,放到第三级缓存
6.给B设置属性值,(需要对象A,但是对象A存在与第三级缓存中,以ObjectFactory形式存在)
7.从三级缓存中取出对象A(经过SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference处理),并存放到第二级缓存中
8.拿到第二级缓存中的A对象,给B对象设置属性值
9.B对象依赖注入结束,放到第一级缓存中
10.给A对象依赖注入结束,放到第一级缓存中

4.3 二级缓存足以解决循环依赖,为什么是三级缓存

1)首先第三级缓存中存放的是ObjectFactory,以便可以自己定制化创建对象,这种形式存在是必要的
2)如果存在代理,每次调用ObjectFactory.getObject()都会进行代理,生成一个新的代理对象
3)循环依赖中先创建的对象会有两次被取出,第一次是给后创建的对象赋值,第二次是移动到第一级缓存,这两次取出的对象要是同一个对象吧,但是从第三级缓存中取,每次取出的都是新建的代理对象。
4)总结,第二级缓存存在的含义既是存没有依赖注入完全的对象,也是暂存这个唯一的代理对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值