4、Spring详解
2021-03-20 20:20:51 2 举报
讲解Spring的Bean的创建过程
作者其他创作
大纲/内容
主要是最后能获得beanFactory
将所有的BeanPostProcessor按照PriorityOrdered、Ordered、普通进行分组
利用reader把componentClasses注册为一个BeanDefinition
默认情况下,此时只有一个EventListenerMethodProcessor进行注册,其实通过DefaultEventListenerFactory添加了DefaultEventListenerFactory用来支持Spring发布、监听事件功能
循环我们手动调用addBeanFactoryPostProcess方法添加的。判断手动添加的是否为BeanDefinitionRegistryPostProcess,因为它是特殊的BeanFactoryPostProcessor,所以需要先执行postProcessBeanDefinitionRegister方法如果不是就添加到普通的PostProcessors中去
// 得到配置的作用域,设置给BeanDefinitionthis.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 检查一下mergedBeanMap中是否存在这个// 记录一下创建了这个bean,记录beanNamemarkBeanAsCreated(beanName)
实例化
开始扫描包路径,得到BeanDefinitionHolderscanner.doScan(StringUtils.toStringArray(basePackages))
在此处获取beanName的时候,会对merged的bean按照BeanDefinition生成Class
初始化后
// 将mbd放到// mergedBeanDefinitions中
// 解析@CompentScan注解,并扫描
实现PriorityOrdered接口
此处用do{}while();循环;主要用于在方法上标注@Bean后会有新的Bean进行注册,导致扫描不到的问题
判断bean的Scope
refresh()
这个方法也很重要将@ImportResource、@Bean转换成BeanDefinition
// 销毁上下文中的 beandestroyBeans();
// 关闭 bean factorycloseBeanFactory();
SingleBean
添加一个Bean的后置处理器,ImportAwareBeanPostProcessor
添加一个默认的BeanPostProcessorChecker
实例化前
AbstractRefreshableApplicationContext#refreshBeanFactory()
主要是将主启动类的类,变成Beandefinition并注册到容器中去
prepareBeanFactory(beanFactory);
执行所有的BeanFactoryPostProcessor
如果存在parentBeanFactory的话,就让parentBeanFactory去创建这个bean
// 设置ExcludeFilters,忽略扫描的类componentScan.getAnnotationArray(\"excludeFilters\")
// 设置LazyInit,懒加载componentScan.getBoolean(\"lazyInit\");
获取所有的BeanPostProcessor的BeanDefinition
默认情况下,就只有ConfigurationClassPostProcessor类进行执行postProcessBeanDefinitionRegistry、postProcessBeanFactory两个后置处理器。postProcessBeanDefinitionRegistry:从配置信息中将BeanDefinition注册到Spring中postProcessBeanFactory:对Configuration类标记成full类,并代理增强Configuration类
// 自定义上下文使用的内部 bean factorycustomizeBeanFactory(beanFactory);
// 加载bean definitionsloadBeanDefinitions(beanFactory);
生成并注册了6个BeanDefinition
postProcessBeanFactory(beanFactory);
合成BeanDefinition
// 创建新的BeanFactorycreateBeanFactory();
1. 创建BeanFactory 2. 生成AnnotatedBeanDefinitionReader 2.1 主要生成了5个BeanDefinition3. 生成ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner#doScan(String... basePackages)
// 是否在BeanDefinition中设置了属性值PropertyValues pvs = (mbd.hasPropertyValues() ?
从配置类中Import进来的资源文件加载BeanDefinition,比如xml文件
//获取父bd的beanNameString parentBeanName = transformedBeanName(bd.getParentName());
// 解析@ImportResource// 得到导入进来的Spring.xml配置文件进行解析this.environment.resolveRequiredPlaceholders(resource);
其实本身就已经有ApplicationListenerDetector了,只是现在在重新添加的话,就会把之前的放到最后
主要分为两部分的原因是BeanDefinitionRegistryPostProcessor其实也是BeanDefinitionPostProcessor,但是因为其特殊性(可以去注册bean)所以需要提前进行执行。默认情况下,只有一个BeanDefinitionRegistryPostProcessor就是ConfigurationClassPostProcessor,这个很重要用来进行扫描,并注册bean,注册的bean包含了所有的bean(包含:mergedBean、@bean、@Compent等)这时的bean中的beanName还是字符串(其实就是bean的包路径)
用来处理加载properties文件
判断是否使用代理对象增强Configuration类enhanceConfigurationClasses(beanFactory);
IOC结束 / AOP开始
一共生成了5个PostProcess和1个BeanFactory。注意:此处默认注入的BeanDefinition中的BeanName并不是类的路径,所以后期在找的时候会有点儿坑分别是:1、ConfigurationClassPostProcessor 解析@Configuration、@ComponentScan、@ComponentScans、@Import、@Bean。这个就蛮多的,注册为配置类,进行扫描或者扫描多个路径,引入一个外部的资源(java文件),注册成为bean2、AutowiredAnnotationBeanPostProcessor 解析@Autowired。不用多说,就是Bean属性的自动注入3、CommonAnnotationBeanPostProcessor 解析@Resource、@WebServiceRef、@EJB。用于引入资源到Spring中进行使用4、PersistenceAnnotationBeanPostProcessor 解析@PersistenceUnit、@PersistenceContext。不是特别的了解,也不怎么会用5、EventListenerMethodProcessor 解析@EventListener。将其转换为ApplicationListener,添加对应BeanDefinition的监听6、DefaultEventListenerFactory 默认的事件发布工厂,创建事件发布器以及监听器
剩下的
通过invokeBeanDefinitionRegistryPostProcess执行postProcessBeanDefinitionRegistry
// 检查是否正在创建,正在创建的Bean不能继续创建第二次beforeSingletonCreation(beanName);
6个BeanDefinition
通过ConfigurationClassPostProcessor类跳跳转到processConfigBeanDefinitions(registry)
所谓提前暴露,其实是利用了三级缓存,直接将没有创建好的bean直接放到了三级缓存中去,并且在二级缓存中移除。但是添加到三级缓存中的是一个后置处理器的方法,即为
// 从合并的BeanDefinition集合中获取RootBeanDefinitionmbd = this.mergedBeanDefinitions.get(beanName);
getBean(beanName)
this.scanner = new ClassPathBeanDefinitionScanner(this);
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
通过processImport()方法进行解析,@Import三种类:1、Import普通类2、ImportSelector3、ImportBeanDefinitionRegistry
普通的实现BeanPostProcessor注册到beanFactory中
// 获取所有的BeanDefinitionfindCandidateComponents(basePackage);
存在
AbstractAutowireCapableBeanFactory
只要是看用户有没有自己配置BeanNameGenerator,有的话就直接覆盖设置之前Spring生成SingletonBeanRegistry singletonRegistry = null; if (registry instanceof SingletonBeanRegistry) { singletonRegistry = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet && singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) { BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } }
isFactoryBean(beanName)
// 放到返回的集合中,并注册到Spring中去beanDefinitions.add(definitionHolder);
不存在
loadBeanDefinitionsForBeanMethod(beanMethod);
通过findCandidateComponents(String basePackage)方法进行获得,总共分为以下几步:1、获取path下面的所有class2、判断是否是@Compent修饰的注册类通过isCandidateComponent(metadataReader)方法进行判断:不是接口或者抽象类,如果是抽象类那么抽象类上得是Lookup注解
//如果有父类,则返回父类给上层遍历进行处理sourceClass.getSuperClass();
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
判断这个BeanDefinition中方法上是否添加了Spring的注解,比如@Bean之类的注解,通过此方法进行单独生成一个BeanDefinition
// 获取原始对象,即创建好的classinstanceWrapper.getWrappedInstance();
DefaultListableBeanFactory#preInstantiateSingletons()
// 已经判断出来了构造函数(非重点)if (resolved)
// 注册事件监听器registerListeners();
// 空方法一个,用于给不同的Spring容器做不同的事情onRefresh();
实现了MergedBeanDefinitionPostProcessor注册到beanFactory中
进行解析扫描出来的BeanDefinitionparser.parse(candidates);
// 设置自身作用域的范围,如果有父级就向上传播componentScan.getEnum(\"scopedProxy\");
使用lambda调用createBean();
Bean的创建过程
排序实现Ordered接口的BeanPostProcessor注册到beanFactory中
实例化剩下的单例Bean,比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。这时会用到之前注册的各种BeanPostProcessor
通过retrieveBeanMethodMetadata()方法进行解析,此时并不是直接转换成BeanDefinition,而是先用一个Set接收
启动ApplicationContext
finishBeanFactoryInitialization(beanFactory);
看看是否有新添加的类,然后放到集合中去,继续注册BeanDefinition
直接说结论(这部分源码实在是,一言难尽): 1. 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化 2. 如果没有确定的构造方法或构造方法参数值,那么 a. 如果没有确定的构造方法,那么则找出类中所有的构造方法 b. 如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化 c. 如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入 d. 根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数 e. 对所有的构造方法进行排序,参数个数多的在前面 f. 遍历每个构造方法 g. 如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值 h. 如果时调用getBean方法时所指定的构造方法参数值,就直接利用这些值 i. 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的
// 创建事件多播器initApplicationEventMulticaster();
processConfigurationClass(ConfigurationClass configClass)
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
initMessageSource();
// 设置比较器,用来排序beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);// 设置自动装配候选者解析式// 判断类是不是可以用来自动注入beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 先设置一个默认值给Scope// 根据containingBd设置Scope值
// 设置要扫描的资源正则表达式(粗略过滤一批数据)scanner.setResourcePattern(componentScan.getString(\"resourcePattern\"));
通过beanFactory.preInstantiateSingletons();调用子类DefaultListableBeanFactory的方法
// 从缓存中移除构造信息this.factoryBeanInstanceCache.remove(beanName);
进行扫描
最后会有默认的Spring会有6个后置处理器1、ApplicationContextAwareProcessor2、ImportAwareBeanPostProcessor3、BeanPostProcessorChecker4、CommonAnnotationBeanPostProcessor5、AutowiredAnnotationBeanPostProcessor6、ApplicationListenerDetector
一般来讲就只有配置的那个类会进去,因为此时除了Spring默认生成的哪些类,就只有一个配置进去的。这个配置进去的类一定是@Configuration注解标注的,给这个类添加Full属性,其余一些类的属性设置为lite
// 创建单例Bean,执行lambda表达式singletonObject = singletonFactory.getObject();
// 使用当前bd的值覆盖合并bd的值mbd.overrideFrom(bd);
初始化
AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)
将Configuration的Class对象转换成enhance代理对象,主要是为了解决被@Configuration修饰的类中必须是单例。因为如果在一个被@Bean注解修饰的方法中new了一个呗@Configuration修饰的类,此时,Spring要保障被@Configuration修饰的类不会再次被创建
从BeanFactory中扫描得到BeanDefinitionProcessor,实例化并注册到BeanFactory中
this.configurationClasses.put
先执行之前特殊的、实现PriorityOrdered/Ordered接口
循环扫描包路径,一级级向包下面扫描类
registerBeanDefinitionForImportedConfigurationClass(configClass);
prepareRefresh();
// 设置IncludeFilters,只扫描到的类componentScan.getAnnotationArray(\"includeFilters\")
用于解析BeanDefinition类中Method注解this.reader.loadBeanDefinitions(configClasses);
查看用户是否有自己设置BeanNameGenerator
否
// 从单例池中获取beanObject singletonObject = this.singletonObjects.get(beanName);
通过refreshBeanFactory()
填充属性
通过processMemberClasses(ConfigurationClass configClass,SourceClass sourceClass)方法进行解析
初始化前
主要是创建一个新的ConfigurationClassParser,用来给后面用,并且设置一些属性,如metadataReaderFactory、environment、registry、conditionEvaluator
ConfigurationClassPostProcessor#processConfigBeanDefinitions(BeanDefinitionRegistry registry)
invokeBeanFactoryPostProcessors(beanFactory);
ConfigurationClassParser
手动添加的BeanDefinitionRegistryPostProcess、实现了PriorityOrdered/Ordered接口、以及在实现了排序接口中添加的那些BeanDefinitionRegisterPostProcessor此时只会将@Import之类的通过className替换成对应的Class类
// 解析配置类中加了@Bean注解的方法retrieveBeanMethodMetadata(sourceClass)
准备刷新spring的上下文信息。其中包含一个空方法用于扩展,创建一个StandardEnvironment()
因为不管什么情况都会进到这个方法,索性直接看Spring是如何获得Bean对象的
// 创建bean完成,从正在创建bean的集合中移除afterSingletonCreation(beanName);
调用ImportBeanDefinitionRegistrar对象的registerBeanDefinitions方法加载BeanDefinition
获取不到
执行Aware
和最终主流程关系不大,就是获得了一个最终获得了DefaultListableBeanFactory
// 直接从单例池中获取beangetSingleton(beanName)
主要是根据Scope去创建BeanDefinition,此处只说明SingleBean。其余的如prototype,非SingleBean、Prototype不做讲解
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);\t\t\t\tcandidate.setScope(scopeMetadata.getScopeName());
BeanDefinition的后置处理器
registerBeanPostProcessors(beanFactory);
// 获取配置的包路径componentScan.getStringArray(\"basePackages\");
// 如果父bd为空bd.getParentName() == null
推断构造方法
// 完成刷新整个spring上下文finishRefresh();
// 设置BeanName生成器componentScan.getClass(\"nameGenerator\");
// 判断是通过什么哪种方式进行自动注入// byType还是byNamembd.getResolvedAutowireMode();
未执行的普通
处理Configuration类打上full标记
第一次调用bean后置处理器,调用beanPostProcessor的applyBeanPostProcessorsBeforeInstantiation方法,在bean实例化之前的进行处理, Spring内置的后置处理器中,无相关实现,可使用自定义的后置处理器在这里进行中止bean的创建过程操作
添加一个BeanPostProcessor替换原有的,ApplicationListenerDetector
// 得到合并后的BeanDefinitionfinal RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)
执行实现了MergedBeanDefinitionPostProcessor的接口的postProcessMergedBeanDefinition后置处理器
// 如果继承了RootBeanDefinition的话// 就克隆一个自己,作为pbd// 否则就按照自己的属性创建
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
空方法一个,用于后期拓展
AbstractApplicationContext#refresh
手动添加的BeanDefinitionRegistryPostProcess
是否存在beanFactory
如果单例池中缓存过,判断是否是FactoryBean,是的话就用getObject()方法获得bean,不是就直接返回bean
this();
通过invokeBeanFactoryPostProcess执行postProcessBeanFactory
创建BeanFactory
生成BeanDefinition
会在AutowiredAnnotationBeanPostProcessor类中执行postProcessProperties,即循环遍历属性,将属性通过反射的方式进行设置到属性值上
ConfigurationClassPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
执行BeanFactory后置处理器
加载类
准备BeanFactory,主要是做了以下事:1、添加两个BeanPostProcessor。 ApplicationContextAwareProcessor与ApplicationListenerDetector2、注册3个默认的SingletonBean environment、systemProperties、systemEnvironment3、设置了 忽略自动装配 和 允许自动装配的接口4、设置bean表达式解析器
只是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法,后面会在ConfigurationClassPostProcessor中再重新创建一个ClassPathBeanDefinitionScanner
// 设置bean的序列化ID
从parentBeanFactory获取
执行postProcessBeanFactory
// 可以通过实现InstantiationAwareBeanPostProcessor// 来控制对象的属性注入
实现Ordered接口
BeanFactory设置Comparator、AutowireCandidateResolver
排序实现PriorityOrdered接口的BeanPostProcessor注册到beanFactory中
是否缓存过
// 如果BeanName是以【&】符号开头// 那就去掉【&】返回BeanNameString beanName = transformedBeanName(name);
直接上结论(源码劝退。。。):1. 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化2. 如果没有确定的构造方法或构造方法参数值,那么 a. 如果没有确定的构造方法,那么则找出类中所有的构造方法 b. 如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化 c. 如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入 d. 根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数 e. 对所有的构造方法进行排序,参数个数多的在前面 f. 遍历每个构造方法 g. 如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值 h. 如果时调用getBean方法时所指定的构造方法参数值,就直接利用这些值 i. 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的为什么分值越低,优先级越高?因为分值越低,匹配程度就越高假设bean的类型为A,A的父类是B,B的父类是C,同时A实现了接口D如果构造方法的参数类型为A,那么完全匹配,得分为0如果构造方法的参数类型为B,那么得分为2如果构造方法的参数类型为C,那么得分为4如果构造方法的参数类型为D,那么得分为1
// 通过匹配构造方法的参数值,进行判断。。。。
Spring的核心
此时,入参beanFactoryPostProcessors和所有的BeanDefinitionRegistryPostProcessor已经处理完毕,接下来处理普通的BeanFactoryPostProcessor
AnnotationConfigApplicationContext#(Class<?>...componentClasses)
根据@Order的配置进行排序Collections.sort()
判断当前这个类是否是通过@Import导入进来的,如果是导入进来的,那么就解析这个类上面的@Scope、@Lazy等注解信息
是
初始化BeanFactory
创建一个ConfigurationClassParser
拿出在实现了PriorityOrdered/Ordered接口中添加的BeanDefinitionRegistryPostProcessor
初始化MessageSource,如果背了一个名字叫做\"messageSource\"的BeanDefinition,就会把这个Bean创建出来,并赋值给ApplicationContext的messageSource属性这样ApplicationContext就可以使用国际化的功能了
这个方法很重要将扫描包路径下的类进行解析
register(componentClasses);
// 按照pbd创建一个// RootBeanDefinitionmbd = new RootBeanDefinition(pbd);
0 条评论
下一页