十堰英文网站建设,比较好的网站建设技术开发,外贸网站产品分析,三端互通的传奇手游发布网推断构造方法源码解析 一、确认候选构造——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors二、autowireConstructor 方法源码解析三、总结 阅读此需阅读下面这些博客先【Spring源码分析】Bean的元数据和一些Spring的工具【Spring源码分析】BeanFactory系… 推断构造方法源码解析 一、确认候选构造——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors二、autowireConstructor 方法源码解析三、总结 阅读此需阅读下面这些博客先【Spring源码分析】Bean的元数据和一些Spring的工具【Spring源码分析】BeanFactory系列接口解读【Spring源码分析】执行流程之非懒加载单例Bean的实例化逻辑【Spring源码分析】从源码角度去熟悉依赖注入一【Spring源码分析】从源码角度去熟悉依赖注入二【Spring源码分析】Resource注入的源码解析【Spring源码分析】循环依赖的底层源码剖析
Spring 在推断构造方法的逻辑上面写的实在太复杂了构造种类贼多贼多恕我实力有限这里的话算不上源码分析只能说是原理吧这我只考虑了平常开发会遇到的什么getBean去添加参数的、BeanDefinition去填充的我都一概跳过看不懂一点比如多参构造参数相同的情况下Autowired注解修饰后的required为false会进行评分操作有点复杂感觉遇不着就不想研究了。
这篇博客可能有点水了 一、确认候选构造——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors
确认候选的构造也是通过 BeanPostProcessor 来进行的SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors引进的代码如下 // Candidate constructors for autowiring?// 提供一个扩展点可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法// 比如AutowiredAnnotationBeanPostProcessor会把加了Autowired注解的构造方法找出来具体看代码实现会更复杂一点Constructor?[] ctors determineConstructorsFromBeanPostProcessors(beanClass, beanName);Nullableprotected Constructor?[] determineConstructorsFromBeanPostProcessors(Nullable Class? beanClass, String beanName)throws BeansException {if (beanClass ! null hasInstantiationAwareBeanPostProcessors()) {for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {Constructor?[] ctors bp.determineCandidateConstructors(beanClass, beanName);if (ctors ! null) {return ctors;}}}return null;}Spring 实现的 SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors 方法中就一个对其进行实现了——AutowireAnnotationBeanPostProcessor。
下面俺对其核心代码进行解析 OverrideNullablepublic Constructor?[] determineCandidateConstructors(Class? beanClass, final String beanName)throws BeanCreationException {// Quick check on the concurrent map first, with minimal locking.Constructor?[] candidateConstructors this.candidateConstructorsCache.get(beanClass);if (candidateConstructors null) {// Fully synchronized resolution now...synchronized (this.candidateConstructorsCache) {candidateConstructors this.candidateConstructorsCache.get(beanClass);if (candidateConstructors null) {Constructor?[] rawCandidates;try {// 拿到所有的构造方法rawCandidates beanClass.getDeclaredConstructors();} catch (Throwable ex) {throw new BeanCreationException(beanName,Resolution of declared constructors on bean Class [ beanClass.getName() ] from ClassLoader [ beanClass.getClassLoader() ] failed, ex);}ListConstructor? candidates new ArrayList(rawCandidates.length);// 用来记录required为true的构造方法一个类中只能有一个required为true的构造方法Constructor? requiredConstructor null;// 用来记录默认无参的构造方法Constructor? defaultConstructor null;// 遍历每个构造方法for (Constructor? candidate : rawCandidates) {// 当前遍历的构造方法是否写了AutowiredMergedAnnotation? ann findAutowiredAnnotation(candidate);// 当前构造方法上加了Autowiredif (ann ! null) {// 整个类中如果有一个required为true的构造方法那就不能有其他的加了Autowired的构造方法// 若存在required为true的还存在其他的Autowired注解就抛出异常if (requiredConstructor ! null) {throw new BeanCreationException(beanName,Invalid autowire-marked constructor: candidate . Found constructor with required Autowired annotation already: requiredConstructor);}boolean required determineRequiredStatus(ann);if (required) {if (!candidates.isEmpty()) {throw new BeanCreationException(beanName,Invalid autowire-marked constructors: candidates . Found constructor with required Autowired annotation: candidate);}// 记录唯一一个required为true的构造方法requiredConstructor candidate;}// 记录所有加了Autowired的构造方法不管required是true还是false// 如果默认无参的构造方法上也加了Autowired那么也会加到candidates中candidates.add(candidate);// 从上面代码可以得到一个结论在一个类中要么只能有一个required为true的构造方法要么只能有一个或多个required为false的方法} else if (candidate.getParameterCount() 0) {// 记录唯一一个无参的构造方法defaultConstructor candidate;}// 有可能存在有参、并且没有添加Autowired的构造方法}if (!candidates.isEmpty()) {// Add default constructor to list of optional constructors, as fallback.// 如果不存在一个required为true的构造方法则所有required为false的构造方法和无参构造方法都是合格的if (requiredConstructor null) {if (defaultConstructor ! null) {candidates.add(defaultConstructor);} else if (candidates.size() 1 logger.isInfoEnabled()) {logger.info(Inconsistent constructor declaration on bean with name beanName : single autowire-marked constructor flagged as optional - this constructor is effectively required since there is no default constructor to fall back to: candidates.get(0));}}// 如果只存在一个required为true的构造方法那就只有这一个是合格的candidateConstructors candidates.toArray(new Constructor?[0]);}// 没有添加了Autowired注解的构造方法并且类中只有一个构造方法并且是有参的else if (rawCandidates.length 1 rawCandidates[0].getParameterCount() 0) {candidateConstructors new Constructor?[]{rawCandidates[0]};}else {// 如果有多个有参、并且没有添加Autowired的构造方法是会返回空的candidateConstructors new Constructor?[0];}this.candidateConstructorsCache.put(beanClass, candidateConstructors);}}}return (candidateConstructors.length 0 ? candidateConstructors : null);}就是说只有三种情况有可用的构造这里是指会有返回的候选构造方法
使用了 Autowired 注解有且只有一个 required 为 true使用了 Autowired 注解required 都为 false没有使用 Autowired 注解有且只有一个多参构造。
通过这些代码的解析可以知道
含有多个参数多个构造和只有一个无参的都会走 instantiateBean 的逻辑去通过无参构造去实例化如果没有的话就抛异常咯换句话说就是没用Autowired注解就是去找无参没有就抛异常。 有且只有一个 Autowired 注解且required为true有多个 Autowired 注解但是 required 都为 false那么就是通过 autowireConstructor 方法去实现 Spring 的自动构造。
二、autowireConstructor 方法源码解析
太难了看不了一点直接阐述源码流程和上面的接着的。
上面确认候选构造的时候还有三种情况我们需要考虑
使用了 Autowired 注解有且只有一个 required 为 true使用了 Autowired 注解required 都为 false没有使用 Autowired 注解有且只有一个多参构造。
也就是上面这三种情况会进入到 autowireConstructor 方法。 下面阐述一下流程
首先是对构造进行个排序以参数的个数降序排序就是参数个数多的在前面 然后去调用 beanFactory#resolveDependency 方法去给参数进行填充参数如果根据当前构造方法找到了对应的构造方法参数值那么这个构造方法就是可用的但是不一定这个构造方法就是最佳的所以这里会涉及到是否有多个构造方法匹配了同样的值这个时候就会用值和构造方法类型进行匹配程度的打分找到一个最匹配的 也就是说构造方法要满足可用的话必须所有的参数都是Spring容器中拥有的可以注入的。
三、总结
本篇并不是Spring所有推断构造方法的逻辑只是其中的一部分——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors 中推断出来的构造方法是怎么处理的。
主要就是有无 Autowired 注解俩各方面。
当有多个构造 Autowired 注解但是 required 都为 false 的话考虑 autowireConstructor 的逻辑。先是将所候选的构造参数个数降序排序然后逐个去匹配看看参数是否都能在容器中找到找不到就换下一个找到就用该构造。