小编给大家分享一下Spring源码解析之推断构造方法的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
贴个测试代码直接开干,这只是个样例,其他情况自行分析
@Component public class OrderService { public OrderService() { System.out.println("无参构造方法"); } @Autowired(required = false) public OrderService(UserService userService) { System.out.println("一个参数的构造方法"); } @Autowired(required = false) public OrderService(String userName, String passWord) { System.out.println("两个参数的构造方法"); } }
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 加载类 // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); // 确保class不为空,并且访问权限为public if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } // 配置的一种特殊的callback回调方法,通过这个callback创建bean // 检查BeanDefinition是否包含了一个Supplier Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { // 如果有就直接调用Supplier的get方法得到一个对象直接返回 return obtainFromSupplier(instanceSupplier, beanName); } // 通过工厂方法创建 if (mbd.getFactoryMethodName() != null) { // 如果BeanDefinition中存在FactoryMethodName,那么调用工厂方法得到一个bean对象并返回 return instantiateUsingFactoryMethod(beanName, mbd, args); } // 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器 // 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析 // Shortcut when re-creating the same bean... boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { // 已经解析过class的构造器 resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { // 已经解析过class的构造器,使用已经解析好的构造器 if (autowireNecessary) { // 如果BeanDefinition中已经构造过 // 构造函数自动注入 // 自动装配构造函数,俗称推断构造方法 return autowireConstructor(beanName, mbd, null, null); } else { // 使用默认构造器 return instantiateBean(beanName, mbd); } } // TODO 推断构造方法 // 需要根据参数解析、确定构造函数 // 寻找当前实例化的bean中构造器是否有@Autowire注解 // Candidate constructors for autowiring? Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); // 解析的构造器不为空 || 注入类型为构造函数自动注入 || beanDefinition指定了构造方法参数值 || getBean时指定了构造方法参数 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 到这里可能找到了多个构造方法,还要决定到底用哪个进行反射初始化 return autowireConstructor(beanName, mbd, ctors, args); } // 默认构造的首选构造函数? // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // 无需特殊处理:只需使用默认的无参构造函数 // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName) throws BeansException { // 装配beanPostProcessor的时候会判断其类型并设置 hasInstantiationAwareBeanPostProcessors 属性, 符合条件才去找构造函数 if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { // getBeanPostProcessors拿到beanFactory中的所有BeanPostProcessor接口,找到一个合格的构造函数 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; // 获取有autowire注解的构造函数 找到合格的构造函数 // AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null) { return ctors; } } } } return null; }
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException { // @Lookup标识的属性每次调用都会被重新初始化, // 有些场景下原型类型的Bean就需要这样做,否则每个Bean只会在spring容器初始化的时候创建一次, // 但是如果在一个单例的Bean中注入了一个原型的Bean,这样的话原本原型的Bean就相当于变成了一个单例的Bean失去了原有的意义, // 这时就需要@Lookup来解决,或者是每次都从新从spring容器中通过getBean来获取Bean // Let's check for lookup methods here... if (!this.lookupMethodsChecked.contains(beanName)) { if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) { try { Class<?> targetClass = beanClass; do { ReflectionUtils.doWithLocalMethods(targetClass, method -> { Lookup lookup = method.getAnnotation(Lookup.class); if (lookup != null) { Assert.state(this.beanFactory != null, "No BeanFactory available"); LookupOverride override = new LookupOverride(method, lookup.value()); try { RootBeanDefinition mbd = (RootBeanDefinition)this.beanFactory.getMergedBeanDefinition(beanName); mbd.getMethodOverrides().addOverride(override); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(beanName, "Cannot apply @Lookup to beans without corresponding bean definition"); } } }); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Lookup method resolution failed", ex); } } this.lookupMethodsChecked.add(beanName); } // 一般只有原型的bean才会创建多次 // 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); } // 定义要选举的构造方法集合 List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length); // 加了@AutoWire()并且是require=true的构造方法 Constructor<?> requiredConstructor = null; // 默认构造发给方法 Constructor<?> defaultConstructor = null; // 返回与 Kotlin 主构造函数相对应的 Java 构造函数, 否则,特别是对于非 Kotlin 类,这只会返回 {@code null}。 Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass); // 记录合成的构造方法数量,理解为可用的构造方法个数吧 int nonSyntheticConstructors = 0; // 遍历所有的构造方法 for (Constructor<?> candidate : rawCandidates) { if (!candidate.isSynthetic()) { nonSyntheticConstructors++; } else if (primaryConstructor != null) { continue; } // 加了@Autowired的构造方法 MergedAnnotation<?> ann = findAutowiredAnnotation(candidate); if (ann == null) { Class<?> userClass = ClassUtils.getUserClass(beanClass); if (userClass != beanClass) { try { Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes()); // 在父类中找@Autowired的构造方法 ann = findAutowiredAnnotation(superCtor); } catch (NoSuchMethodException ex) { // Simply proceed, no equivalent superclass constructor found... } } } if (ann != null) { // 如果找到加了@Autowired注解的构造方法,再判断required属性 // 加了@AutoWire()并且是require=true的构造方法 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); } requiredConstructor = candidate; } candidates.add(candidate); } else if (candidate.getParameterCount() == 0) { // 否则如果构造函数参数个数为0,把它赋值给变量defaultConstructor defaultConstructor = candidate; } } // 处理上面遍历后的结果 if (!candidates.isEmpty()) { // Add default constructor to list of optional constructors, as fallback. if (requiredConstructor == null) { // 如果加了@Autowired、并且没有指定required为true、并且存在默认的构造方法 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)); } } candidateConstructors = candidates.toArray(new Constructor<?>[0]); } // 如果只有一个构造方法,并且构造数的参数大于0 else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { candidateConstructors = new Constructor<?>[] {rawCandidates[0]}; } // primaryConstructor 做java开发一般都是null else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; } // primaryConstructor 做java开发一般都是null else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { candidateConstructors = new Constructor<?>[] {primaryConstructor}; } else { candidateConstructors = new Constructor<?>[0]; } // 把推断的构造方法数组放到缓存map中 this.candidateConstructorsCache.put(beanClass, candidateConstructors); } } } return (candidateConstructors.length > 0 ? candidateConstructors : null);
推断构造方法第一步,先找出可用的构造方法,步骤如下:
1、先找出所有的构造方法。
2、遍历所有构造方法,找出加了@Autowire的构造方法,如果没找到就在父类中找,父类中还找不到,但是存在一个构造方法的参数的个数为0,就作为默认的构造方法;如果找到了加了@Autowire的构造方法,并且require都为true则直接报错。
3、再次过滤上面筛选过的构造方法,如果有默认构造方法就加入候选者的集合;如果上面筛选过后没有合适的构造方法,但是又只有参数个数大于0的构造方法,就把他加入到候选者的列表中。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor
protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { // 带有参数情况的实例化 return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); }
org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { //实例化BeanWrapper,是包装bean的容器 BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; // 1、首先判断是否通过getBean方法指定了构造方法参数值 // 如果getBean中传入的参数不为空,那么就使用传入的参数 if (explicitArgs != null) { argsToUse = explicitArgs; } // 否则就需要解析配置文件中的参数 else { Object[] argsToResolve = null; // 先尝试从缓存中获取 synchronized (mbd.constructorArgumentLock) { // 缓存中的构造器 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; // 2、针对当前BeanDefinition是否缓存了构造方法和构造方法参数值 if (constructorToUse != null && mbd.constructorArgumentsResolved) { // 在缓存中找到了构造器,就继续从缓存中寻找缓存的构造器参数 // Found a cached constructor... argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 没有缓存的参数,就需要获取配置文件中配置的参数 argsToResolve = mbd.preparedConstructorArguments; } } } // 如果缓存中没有缓存的参数的话,即argsToResolve不为空,就需要解析配置的参数 if (argsToResolve != null) { // 解析参数类型,比如将配置的String类型转换成int、boolean等类型 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); } } // 3、如果两者任意一个为空,则继续进行下面的步骤 // 如果没有缓存,就需要从构造函数开始解析 if (constructorToUse == null || argsToUse == null) { // 如果传入的构造器数组不为空,就使用传入的构造器参数,否则通过反射获取class中定义的构造器 // Take specified constructors, if any. Constructor<?>[] candidates = chosenCtors; // 3.1 如果没有传入构造方法,那么则获取当前BeanDefinition对应的BeanClass中所有的构造方法作为候选者 if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { // 使用public的构造器或者所有构造器 candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors()); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } } // 3.2 判断候选者构造方法是不是只有一个,并且没有指定构造方法参数 if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) { Constructor<?> uniqueCandidate = candidates[0]; if (uniqueCandidate.getParameterCount() == 0) { synchronized (mbd.constructorArgumentLock) { mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate; mbd.constructorArgumentsResolved = true; mbd.resolvedConstructorArguments = EMPTY_ARGS; } // 初始化并设置构造器参数 bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS)); return bw; } } // 是否需要解析构造器,在配置文件中指定注入方式为构造器注入 // Need to resolve the constructor. boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); // 存放解析后的构造方法参数值 ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; if (explicitArgs != null) { // getBean方法传入的参数 minNrOfArgs = explicitArgs.length; } else { // 配置文件中的配置的参数 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); // 用于承载解析后的构造函数参数的值 resolvedValues = new ConstructorArgumentValues(); // 解析配置文件中的参数,并且返回参数个数 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } // 3.3 对候选者构造函数排序,public构造函数优先、参数数量降序排序 AutowireUtils.sortConstructors(candidates); // 计算构造方法参数个数最少个数 // 意思是如果指定了构造方法参数个数,所以当前BeanDefinition对应的BeanClass中所有构造方法参数个数至少满足手动指定的参数值个数 int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; // 3.4 遍历所有的构造方法 for (Constructor<?> candidate : candidates) { int parameterCount = candidate.getParameterCount(); if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) { // Already found greedy constructor that can be satisfied -> // do not look any further, there are only less greedy constructors left. break; } // 如果候选者参数个数 < minNrOfArgs,则不匹配,继续下一个 if (parameterCount < minNrOfArgs) { continue; } // 封装解析到的参数信息 ArgumentsHolder argsHolder; Class<?>[] paramTypes = candidate.getParameterTypes(); // 解析配置文件得到的构造方法参数值 if (resolvedValues != null) { try { // 3.5 判断通过getBean方法指定构造方法参数 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount); if (paramNames == null) { ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { paramNames = pnd.getParameterNames(candidate); } } // 参数个数匹配的情况下把所有参数封装为一个ArgumentsHolder对象,不匹配就直接报错了 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1); } catch (UnsatisfiedDependencyException ex) { if (logger.isTraceEnabled()) { logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex); } // Swallow and try next constructor. if (causes == null) { causes = new LinkedList<>(); } causes.add(ex); continue; } } else { // 处理参数由getBean方法传入的情况 // Explicit arguments given -> arguments length must match exactly. if (parameterCount != explicitArgs.length) { continue; } argsHolder = new ArgumentsHolder(explicitArgs); } // 3.7 计算得到的构造方法参数值和参数的匹配程度 // 因为不同构造函数的参数个数相同,而且参数类型为父子关系,所以需要找出类型最符合的一个构造函数 // Spring用一种权重的形式来表示类型差异程度,差异权重越小越优先 // 如果是以宽松的方式解析,默认为true,所以执行getTypeDifferenceWeight int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // 当前构造函数最为匹配的话,清空先前ambiguousConstructors列表 // Choose this constructor if it represents the closest match. if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } // 存在相同权重的构造器,将构造器添加到一个ambiguousConstructors列表变量中 // 注意,这时候constructorToUse 指向的仍是第一个匹配的构造函数 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } /*******************************************************************************************************/ if (constructorToUse == null) { // 如果没有匹配的构造函数,抛出异常。略 if (causes != null) { UnsatisfiedDependencyException ex = causes.removeLast(); for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause); } throw ex; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Could not resolve matching constructor " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { // 如果存在多个构造函数匹配程度相同,并且BeanDefinition中设置isLenientConstructorResolution为false(默认值为true), // 表示构造器创建为严格模式的话,会抛出异常。异常代码略 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Ambiguous constructor matches found in bean '" + beanName + "' " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors); } if (explicitArgs == null && argsHolderToUse != null) { argsHolderToUse.storeCache(mbd, constructorToUse); } } Assert.state(argsToUse != null, "Unresolved constructor arguments"); // 初始化 bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); return bw; }
1、只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化 candidates.length == 1
2、有多个构造方法或者bean需要通过构造方法自动进行注入 ResolvedAutowireMode() == 3
3、根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数 minNrOfArgs
4、对所有的构造方法进行排序,参数个数多的在前面 AutowireUtils.sortConstructors
5、遍历所有的构造方法
6、如果当前构造方法参数个数小于minNrOfArgs则不匹配,继续判断下一个构造方法
7、如果是调用getBean方法指定的参数就直接利用这些值,如果不是就根据构造方法参数类型找值(先byType再byName),匹配的话则封装成一个ArgumentsHolder对象
8、这里可能会匹配到多个构造方法,然后就需要那值和构造方法匹配程度计算一个权重,值越小优先级越高(因为如果是父子类的话子类匹配成功更高)
9、计算权重分为宽松型(默认)和严格型,严格型的情况下如果有多个匹配就报错
以上是“Spring源码解析之推断构造方法的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。