ConstructorResolver#autowireConstructor
:
这个方法作用是获取被包装后的bean,包装后的对象是BeanWrapper对象,这个对象的实现类是BeanWrapperImpl。其中包含被封装后待处理的bean,和设置bean属性的属性编辑器。
protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { // 此处的this,就是DefaultListableBeanFactory嘛 return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); } // ConstructorResolver#autowireConstructor public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) { //先实例化一个BeanWrapperImpl类对象 BeanWrapperImpl bw = new BeanWrapperImpl(); // initBeanWrapper做了一些事,比如注册解析器、value解析器等等 这是个比较大的概念,后面会有专题再说吧 this.beanFactory.initBeanWrapper(bw); Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; //如果构造参数不为空就直接使用这些参数即可 if (explicitArgs != null) { argsToUse = explicitArgs; } // 否则构造函数的入参,交给Spring处理。它会去容器里拿~~~~~ else { Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { //获取已缓存解析的构造函数或工厂方法(resolvedConstructorOrFactoryMethod----用于缓存已解析的构造函数或工厂方法) constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; 如果缓存不为空,并且构造参数已经解析缓存了,(constructorArgumentsResolved为包可见,用于表示构造参数状态是否已经解析) // 显然首次进来,都是为null并且没有被解析的 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor... argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; } } } // 如果上面没有解析过,显然这里参数就是null了,argsToUse也就还为null Spring下面继续解析 if (argsToResolve != null) { argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); } } //如果缓存的构造器不存在,就说明没有bean进行过解析,需要去关联对应的bean的构造器 if (constructorToUse == null) { // Need to resolve the constructor. // 我们的传值chosenCtors 显然不为null,所以此值为true boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; //若传入的构造参数不为空,那最小参数长度一塔为准 if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // 这里相当于要解析出构造函数的参数了 //解析对应的构造参数然后添加到ConstructorArgumentValues中 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } // Take specified constructors, if any. //如果传入的构造器为空,则获取bean的Class对象,然后根据bean是不是public修饰的来按照不同的方式获取所有的构造器 // 显然,我们这里(大都都会有构造器) // 但是此处我们发现,即使构造器不是public的,这里也能够遭到构造器来进行实例化 Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { //getDeclaredConstructors返回所有的构造器(包括public和private修饰的),getConstructors返回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); } } // 这个构造器排序有点意思 //按照访问方式和数量对构造器进行排序;public>protect>private,在同为public时构造器入参多的排在前面 // 所以排在第一位的,是public的,参数最多的构造器 AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; // 记录下,引起歧义的构造器们。就是记录下来,如果存在这种歧义,抛异常的时候用来告诉调用者 Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; // 开始遍历排序后的构造器了========================== for (Constructor<?> candidate : candidates) { // 拿到构造器参数的类型们 Class<?>[] paramTypes = candidate.getParameterTypes(); // constructorToUse不为null(表示已经找到了合适构造器),但是呢,连参数个数的长度都对应不上,那就直接break,后面的构造器全都不用看了 if (constructorToUse != null && argsToUse.length > paramTypes.length) { // Already found greedy constructor that can be satisfied -> // do not look any further, there are only less greedy constructors left. break; } // 如果参数个数比最小个数还小,那就继续下一个构造器吧。 if (paramTypes.length < minNrOfArgs) { continue; } ArgumentsHolder argsHolder; if (resolvedValues != null) { try { //兼容JDK6提供的@ConstructorProperties这个注解,如果它标注了参数名,那就以它的名字为准 //@ConstructorProperties的作用=======》构造函数上的注解,显示该构造函数的参数如何与构造对象的getter方法相对应 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); // 否则,就自己解析 if (paramNames == null) { // 一般都是Bean工厂默认的DefaultParameterNameDiscoverer 解析出变量名 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { paramNames = pnd.getParameterNames(candidate); } } //根据获取到的参数名和已经查到的构造参数和构造参数类型来创建用户创建构造器用的构造参数数组 //这个数组中包含了原始的参数列表和构造后的参数列表,用来对比用 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring); } catch (UnsatisfiedDependencyException ex) { if (this.beanFactory.logger.isTraceEnabled()) { this.beanFactory.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 { // Explicit arguments given -> arguments length must match exactly. if (paramTypes.length != explicitArgs.length) { continue; } argsHolder = new ArgumentsHolder(explicitArgs); } //lenientConstructorResolution的值ture与false有什么区别: //这个属性默认值是true,在大部分情况下都是使用[宽松模式],即使多个构造函数的参数数量相同、类型存在父子类、接口实现类关系也能正常创建bean。 // false表示严格模式。与上面相反 // typeDiffWeight:返回不同的个数的权重(权重概念?) int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // Choose this constructor if it represents the closest match. // 根据权重,选择一个最为合适的构造器 if (typeDiffWeight < minTypeDiffWeight) { // 大都进这里来,然后是木有ambiguousConstructors 的 constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } 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()) { 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.storeCache(mbd, constructorToUse); } } //下面步骤都是通用的,用上面得到的构造器(无论是从bean对象中获取的还是spring自己构建的) // 和参数来反射创建bean实例,并放到BeanWrapperImpl对象中然后返回 try { // 拿到生成Bean实例化策略,默认值为CglibSubclassingInstantiationStrategy 用CGLIB生成子类的方式 final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy(); Object beanInstance; if (System.getSecurityManager() != null) { final Constructor<?> ctorToUse = constructorToUse; final Object[] argumentsToUse = argsToUse; beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse), beanFactory.getAccessControlContext()); } else { // 主要就是调用了策略器的instantiate,对Bean进行了最终的实例化 // 此方法为重载方法,此处因为不需要代理,所以执行的直接是SimpleInstantiationStrategy#instantiate // 到此处,有一个HelloServiceImpl正式创建 然后继续到doCreateBean方法去吧 beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } bw.setBeanInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean instantiation via constructor failed", ex); } }
populateBean和initializeBean
具体他俩做了什么,参考:【小家Spring】AbstractAutowireCapableBeanFactory#populateBean实现Bean的依赖注入(属性赋值)和initializeBean对Bean的初始化
总结
getBean()方法是Spring IOC容器实例化、初始化Bean的核心方法,里面的逻辑也异常的复杂。
通过阅读源码,感受最深的是:
一个优秀的框架,决不仅仅是说可以通过反射能帮助创建Bean就行了,而是像Spring这样能够考虑到各式各样的情况,有非常好的容错性、有很好的异常处理以及提示调用者报错原因。当然也有一一系列的设计原则的体现:单一职责原则、面向对象的设计原则、对扩展开放对修改关闭的原则(BeanPostProcessor是个非常好的钩子,允许我们参与进Bean的声明周期中来)
阅读优秀的源码,能够在我们更深的理解到:优秀只所以优秀,是因为真的很优秀!!!