SpringIoc源码跟踪整理

一.生成单例非代理Bean实例的大致流程

1.1DefaultListableBeanFactory.getBean(String name)
——>
1.2AbstractBeanFactory.doGetBean:先找缓存singleCache,earlySingleCache等Map中有没有这个Bean的实例,有就直接返回,没有继续往下调,三重缓存用于解决循环依赖,只适用于单例字段注入,对构造器注入及多例模式不支持,
三重缓存顺序:
singletonFactories(先存放ObjectFactory singletonFactory)–earlySingletonObjects(再存放singletonFactory.getObject()出来的对象,该对象还未开始依赖或者暂未依赖完全)–
singletonObjects(最后存放依赖完整的Bean)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								singletonObject = singletonFactory.getObject();
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

——>
1.3DefaultSingletonBeanRegistry.getSingleton:通过输入ObjectFactory的匿名内部类实例,并重写其getObject方法来调用AbstractAutowireCapableBeanFactory.createBean方法
——>
1.4AbstractAutowireCapableBeanFactory.createBean:调用AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation方法看看这个Bean是否会生成代理实例,如果生成则返回该代理实例,如果没有继续往下调
——>
1.5 AbstractAutowireCapableBeanFactory.doCreateBean
——>
1.6 AbstractAutowireCapableBeanFactory.createBeanInstance:如果是通过@Configuration类中标识了@Bean标签的方法,则BeanDefinition中的FactoryMethodName不为null为方法名,FactoryBeanName为@Configuration类,先获取FactoryBean实例,再通过FactoryBean实例调用@Bean标签的方法获取相关的实例(AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod)。
——>
1.7 AbstractAutowireCapableBeanFactory.autowireConstructor:通过反射获取构造器对象生成实例,带参构造器会自动注入相关参数

二.有设置TargetSource的代理Bean实例的生成流程(入口为1.4)

2.1 AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation:判断输入的RootBeanDefinition的beforeInstantiationResolved的属性是否为true,如果为true则继续判断RootBeanDefinition的isSynthetic属性是否为true,以及当前上下文中是否有 注册InstantiationAwareBeanPostProcessor接口的实现类如果之后的两个都有则继续调用后面的生成代理实例流程
——>
2.2 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation:
遍历当前上下文中所有InstantiationAwareBeanPostProcessor的实例并调用其postProcessBeforeInstantiation接口方法获取代理实例,如果有一个实例重写的方法返回了代理实例则返回该代理实例,否则返回null
——>
2.3 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization:如果2.2中返回值不是null,则遍历当前上下文中所有BeanPostProcessor的实例,并调用其postProcessAfterInitialization方法对实例化后的代理对象进行处理,当有一个BeanPostProcessor实例重写的方法返回了null,则返回null

3.registerBeanFactoryPostProcessor: 先执行已有的BeanDefinitionRegistryPostProcessor,再按排序执行PriorityOrdered(is a Ordered),再按排序执行Ordered的再(会排序但是一般是一样的,comparator对于没有实现ordered接口的都是返回0)执行没有的,再执行已有的BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor方法, 再按排序执行PriorityOrdered 的BeanFactoryPostProcessor ,再按排序执行Ordered的BeanFactoryPostProcessor再(不会排序)执行没有的

三.BeanFactory
3.ConfigurationClassPostProcessor(is a BeanDefinitionRegistryPostProcessor)会获取系统所有@Configuration标识的类,封装成ConfigurationClass,并对其进行解析,会执行其上注释的子父注释中所有的ImportBeanDefinitionRegistrar的registerBeanDefinitions方法中(Map)BeanDefinitionsMap和(List)BeanDefinitionsNames同时会添加,因为Map是无序的,需要用list来记录注册顺序

DefaultListableBeanFactory 是其最常用最完善的实现类

四.注解处理方式
@Autowired @value @ Inject(JSR-330) 通过AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法来处理(is a InstantiationAwareBeanPostProcessor postProcessPropertyValues方法在postProcessAfterInstantiation之后执行)来处理

@javax.xml.ws.WebServiceRef @javax.ejb.EJB @javax.annotation.Resource @javax.annotation.PostConstruct @javax.annotation.PreDestroy 通过CommonAnnotationBeanPostProcessor

五.环境变量相关
1.PropertySource
用于存放读取配置文件数据的抽象接口,实现类通过指定泛型类型来设置保存配置数据的数据结构类型,一般的实现类有1.1MapPropertySource,该实现类封装的是Map<String,Object>,用Map来保存配置文件数据的key-value
1.2MutablePropertySources,该实现类封装的是List 用list来保存多份配置文件,与多例相关。

2.StandardEnvironment
重写了其父类的方法,当新对象在调用其父类构的造方法时会把系统的环境变量值传入至(MutablePropertySources) propertySources 私有不可变成员变量中保存,通过getPropertySources方法获取。

六.资源加载相关
1.SpringFactoriesLoader用于加载spring.factories文件(默认路径是META-INF/spring.factories)

2.Resource及其实现类 一般是用来描述文件路径,是否文件,是否可读的,用什么类型的类加载其,提供输入IO流对象的,而不是真正读取或者存放文件数据的。

3.internalConfigurationAnnotationProcessor(ConfigurationClassPostProcessor is a BeanDefinitionRegistryPostProcessor)
最早被注册的BeanDefinitionRegistryPostProcessor 是个内置对象,用于解析配置类及其标签:(详情:整理资料Mybatis 1.3 )

七.延迟注入
可以通过字段上打@Lazy注解实现延迟注入,
当通过@Autowired @value @ Inject(JSR-330) 这些注解延迟注入时
被注入的Bean在容器中实例化后调用AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法(在postProcessAfterInstantiation之后)时会遍历被注入Bean中的所有被标识需要依赖注入的字段,并逐个调用ConfigurableListableBeanFactory的resolveDependency方法去解析每个字段信息及其上的注解信息,
当字段的类型是Optional时返回Optional的实现对象,
当类型是ObjectFactory或者ObjectProvider类型返回DependencyObjectProvider对象,
当类型是javax.inject.Provider时返回 Jsr330DependencyProvider对象,
通过ContextAnnotationAutowireCandidateResolver判断字段是否有@Lazy注解,如果当字段上有@Lazy注解时,通过ContextAnnotationAutowireCandidateResolve.buildLazyResourceProxy方法返回ProxyFactory生成的需要注入对象的代理对象, 每次调用延迟注入的实例的方法时,会调用DefaultListableBeanFactory 的doResolveDependency(descriptor, beanName, null, null)方法获取需要延迟注入的对象实例(调用AbstractAutowireCapableBeanFactory.doCreateBean获取)并执行其方法。
如果都不是上面的条件则直接去容器中查找对应实例
当通过@javax.xml.ws.WebServiceRef @javax.ejb.EJB @javax.annotation.Resource @javax.annotation.PostConstruct @javax.annotation.PreDestroy 这些注解延迟注入时
被注入的Bean在容器中实例化后调用CommonAnnotationBeanPostProcessor的postProcessPropertyValues方法时会遍历被注入Bean中的所有被标识需要依赖注入的字段,并调用与每个字段上的注入注解相关的InjectedElement的静态内部类InjectedElement的子类的getResourceToInject方法去处理每个字段信息及其上的注解信息,如通过@javax.annotation.Resource注解注入则通过 CommonAnnotationBeanPostProcessor.buildLazyResourceProxy方法返回ProxyFactory生成需要注入对象的代理的代理对象(对象的代理由ContextAnnotationAutowireCandidateResolve.buildLazyResourceProxy方法生成), 每次调用延迟注入的实例的方法时,会调用DefaultListableBeanFactory 的doResolveDependency(descriptor, beanName, null, null)方法获取需要延迟注入的对象实例(调用AbstractAutowireCapableBeanFactory.doCreateBean获取)并执行其方法。

通过@javax.annotation.Resource注解延迟注入其实就是再多代理了一层 通过@Autowired @value @ Inject(JSR-330) 这些注解延迟注入的代理对象,其对需要延迟注入的原始实例进行了两次代理,因此相对于@Autowired @value @ Inject这些只代理一次原始实例的延迟注入性能要差。

八.实例的延迟加载
通过类上打@Lazy标签实现。在上下文刷新的过程中如果没有调用getBean等方法(如依赖查找的过程,依赖注入的过程)从容器中获取有@Lazy标签的类实例,则其不会在
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
这个方法中被实例及初始化,需要被从容器中调用时再实例及初始化,如果配合字段上依赖注入的@Lazy使用,也不会提前实例初始化,而会在调用这个依赖的实例时被容器实例及初始化。(与字段上@lazy的区别在于,类的不会在容器启动的时候实例化,而字段上的无关是否实例化只是使用的时候去容器拿如果容器有则直接用如果没有则进行实例化再赋予)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值