【Spring IOC】【三】容器源码解析- 创建原始Bean
1 前言
上一文,我们讲解了getBean里的一些过程,这节我们详细来讲一讲创建bean,也就是createBean。createBean默认的实现类是AbstractAutowireCapableBeanFactory,createBean会调用doCreateBean和createBeanInstance,从这三个方法里大概总结出创建bean的集中方式:
- 自定义
BeanPostProcessor
,生成代理对象InstantiationAwareBeanPostProcessor
createBean()
->resolveBeforeInstantiation()
- 通过
supplier
创建对象 createBean()
->doCreateBean()
->createBeanInstance()
->obtainFromSupplier()
- 通过
FactoryMethod
创建对象 createBean()
->doCreateBean()
->createBeanInstance()
->instantiateUsingFactoryMethod()
- 通过构造方法创建对象
createBean()
->doCreateBean()
->createBeanInstance()
->autowireConstructor()
- 通过
FactoryBean
创建对象
2 源码分析
2.1 方法通读
针对createBeanInstance,我们来通读一下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 根据beanName以及bean定义信息得到beanClass 里边会涉及SPEL表达式的解析 Class<?> beanClass = resolveBeanClass(mbd, beanName); // 权限校验什么的 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()); } // 如果bean定义文件mbd提供了Supplier 这样的函数接口 就通过函数接口去创建bean Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 如果bean描述文件mbd中提供了FactoryMethod工厂方法 那么就通过FactoryMethod创建bean if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } /* * 加锁 多次构建同一个bean时, 无需再次推断应该使用哪种方式构造实例 */ boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { // 通过构造方法创建bean return autowireConstructor(beanName, mbd, null, null); } else { // 通过默认的构造方法反射创建bean return instantiateBean(beanName, mbd); } } // 由后置处理器决定返回哪些构造方法,这里不深入分析了 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); /* * 下面的条件分支条件用于判断使用什么方式构造 bean 实例, * 有两种方式可选 - 构造方法自动注入和默认构造方法。判断的条件由4部分综合而成,如下: * 条件1:ctors != null -> 后置处理器返回构造方法数组是否为空 * 条件2:mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR * -> bean 配置中的 autowire 属性是否为 constructor * 条件3:mbd.hasConstructorArgumentValues() * -> constructorArgumentValues 是否存在元素,即 bean 配置文件中 * 是否配置了 <construct-arg/> * 条件4:!ObjectUtils.isEmpty(args) * -> args 数组是否存在元素,args 是由用户调用 * getBean(String name, Object... args) 传入的 * 上面4个条件,只要有一个为 true,就会通过构造方法自动注入的方式构造 bean 实例 */ if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 通过“构造方法自动注入”的方式构造 bean 对象 return autowireConstructor(beanName, mbd, ctors, args); } ctors = mbd.getPreferredConstructors(); if (ctors != null) { // 通过“构造方法自动注入”的方式构造 bean 对象 return autowireConstructor(beanName, mbd, ctors, null); } // 通过“默认构造方法”的方式构造 bean 对象 return instantiateBean(beanName, mbd); }
看着这个方法表面的东西不多,实际上很多很多,他的方法调用一层一层调的好多,不打几个断点,多debug几次根本看不懂都是干啥的= =,所以看的时候要写个测试类测一测,打打断点自己调试调试,看变量、参数的变化,那么总结一下这个方法的执行流程,如下:
- 解析bean的定义信息
- 访问权限检查,若禁止访问,则抛出异常
- 如果bean定义文件mbd提供了Supplier 这样的函数接口 就通过函数接口去创建bean
- 如果bean描述文件mbd中提供了FactoryMethod工厂方法 那么就通过FactoryMethod创建bean
- 若构造方式已解析过,则走快捷路径构建 bean 对象,并返回结果
- 组合条件决定使用哪种方式构建 bean 对象
接下来我们大概分析一下每个创建的实现源码。
2.2 autowireConstructor-通过构造方法创建 bean 实例
根据你提供的构造方法,参数列表,寻找一个合适的构造器的过程:
1 public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, 2 @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { 3 4 // 创建bean最后都会返回一个BeanWrapper类型的结果 5 BeanWrapperImpl bw = new BeanWrapperImpl(); 6 this.beanFactory.initBeanWrapper(bw); 7 8 Constructor<?> constructorToUse = null; 9 ArgumentsHolder argsHolderToUse = null; 10 Object[] argsToUse = null; 11 12 if (explicitArgs != null) { 13 argsToUse = explicitArgs; 14 } 15 else { 16 Object[] argsToResolve = null; 17 synchronized (mbd.constructorArgumentLock) { 18 // 获取bean定义信息中有没有解析过的用于构造bean的方法 第一次创建肯定是空的 19 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; 20 if (constructorToUse != null && mbd.constructorArgumentsResolved) { 21 // 获取解析过的构造方法参数列表 22 argsToUse = mbd.resolvedConstructorArguments; 23 if (argsToUse == null) { 24 argsToResolve = mbd.preparedConstructorArguments; 25 } 26 } 27 } 28 if (argsToResolve != null) { 29 // 解析参数列表 30 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); 31 } 32 } 33 34 if (constructorToUse == null || argsToUse == null) { 35 //获取当前bean的构造方法 36 Constructor<?>[] candidates = chosenCtors; 37 if (candidates == null) { 38 Class<?> beanClass = mbd.getBeanClass(); 39 try { 40 candidates = (mbd.isNonPublicAccessAllowed() ? 41 beanClass.getDeclaredConstructors() : beanClass.getConstructors()); 42 } 43 catch (Throwable ex) { 44 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 45 "Resolution of declared constructors on bean Class [" + beanClass.getName() + 46 "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); 47 } 48 } 49 /* 50 当发现构造方法只有一个,且参数为空 那么就调用默认构造方法返回 51 */ 52 if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) { 53 Constructor<?> uniqueCandidate = candidates[0]; 54 if (uniqueCandidate.getParameterCount() == 0) { 55 synchronized (mbd.constructorArgumentLock) { 56 mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate; 57 mbd.constructorArgumentsResolved = true; 58 mbd.resolvedConstructorArguments = EMPTY_ARGS; 59 } 60 bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS)); 61 return bw; 62 } 63 } 64 65 // 下边就需要解析每个构造器,选一个最优的构造器 66 boolean autowiring = (chosenCtors != null || 67 mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); 68 ConstructorArgumentValues resolvedValues = null; 69 70 int minNrOfArgs; 71 if (explicitArgs != null) { 72 minNrOfArgs = explicitArgs.length; 73 } 74 else { 75 // 解析构造参数 minNrOfArgs参数个数 76 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); 77 resolvedValues = new ConstructorArgumentValues(); 78 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); 79 } 80 // 排序 81 AutowireUtils.sortConstructors(candidates); 82 int minTypeDiffWeight = Integer.MAX_VALUE; 83 Set<Constructor<?>> ambiguousConstructors = null; 84 Deque<UnsatisfiedDependencyException> causes = null; 85 // 这里就要遍历每一个构造器 进行匹配选择 86 // 原则就是访问权限最高的 参数匹配的上的 87 for (Constructor<?> candidate : candidates) { 88 int parameterCount = candidate.getParameterCount(); 89 90 if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) { 91 break; 92 } 93 94 if (parameterCount < minNrOfArgs) { 95 continue; 96 } 97 98 ArgumentsHolder argsHolder; 99 Class<?>[] paramTypes = candidate.getParameterTypes(); 100 if (resolvedValues != null) { 101 try { 102 // 构造方法的ConstructorProperties注解 103 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount); 104 if (paramNames == null) { 105 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); 106 if (pnd != null) { 107 // 构造方法参数名字列表 108 paramNames = pnd.getParameterNames(candidate); 109 } 110 } 111 // 构造方法参数值的解析 112 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, 113 getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1); 114 } 115 catch (UnsatisfiedDependencyException ex) { 116 if (logger.isTraceEnabled()) { 117 logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex); 118 } 119 if (causes == null) { 120 causes = new ArrayDeque<>(1); 121 } 122 causes.add(ex); 123 continue; 124 } 125 } 126 else { 127 if (parameterCount != explicitArgs.length) { 128 continue; 129 } 130 argsHolder = new ArgumentsHolder(explicitArgs); 131 } 132 133 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? 134 argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); 135 if (typeDiffWeight < minTypeDiffWeight) { 136 constructorToUse = candidate; 137 argsHolderToUse = argsHolder; 138 argsToUse = argsHolder.arguments; 139 minTypeDiffWeight = typeDiffWeight; 140 ambiguousConstructors = null; 141 } 142 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { 143 if (ambiguousConstructors == null) { 144 ambiguousConstructors = new LinkedHashSet<>(); 145 ambiguousConstructors.add(constructorToUse); 146 } 147 ambiguousConstructors.add(candidate); 148 } 149 } 150 151 // 没有找到构造器或者找到两个出现歧义的都会抛异常 152 if (constructorToUse == null) { 153 if (causes != null) { 154 UnsatisfiedDependencyException ex = causes.removeLast(); 155 for (Exception cause : causes) { 156 this.beanFactory.onSuppressedException(cause); 157 } 158 throw ex; 159 } 160 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 161 "Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " + 162 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); 163 } 164 else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { 165 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 166 "Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " + 167 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + 168 ambiguousConstructors); 169 } 170 171 if (explicitArgs == null && argsHolderToUse != null) { 172 argsHolderToUse.storeCache(mbd, constructorToUse); 173 } 174 } 175 176 // 匹配到合适的构造器了,进行创建bean 177 Assert.state(argsToUse != null, "Unresolved constructor arguments"); 178 bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); 179 return bw; 180 }
东西多不多= =看麻了,他要解析你的类有多少个构造方法,每个构造方法有哪些参数,参数的类型以及你参数的值,解析出来,进行一个匹配的过程,只有一个默认的构造或者匹配到一个合适的构造方法就会调用instantiate,进行创建并返回。
- 创建返回值BeanWrapperImpl 对象
- 判断是不是只有一个默认构造方法,是的话就调用默认构造方法创建并返回
- 获取构造方法,并排序
- 遍历每个构造方法,进行参数解析 参数值解析,筛选出一个合适的构造方法
- 缓存这些解析信息
- 创建bean
- 将bean放进BeanWrapperImpl 对象并返回
Spring基本上每个基础的类的信息都会有缓存,变量很多,自己看的时候可以创建几个bean,多搞几个构造方法结合着看。
2.3 instantiateBean-通过默认构造方法创建 bean 实例
这个是使用默认的构造方法去创建bean,他最终也会调到instantiate方法,所谓殊途同归嘛,那么我们来看看:
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; // 安全检查,咱也不是很懂,可以略过 if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged( (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext()); } else { /* * 这里又出现一个初始化策略。 * 如果 bean 的配置信息中包含 lookup-method 和 replace-method,则通过 CGLIB 创建 bean 对象 */ beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // 检测 bean 配置中是否配置了 lookup-method 或 replace-method,若配置了,则需使用 CGLIB 构建 bean 对象 if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { // 获取默认构造方法 constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } // 通过无参构造方法创建 bean 对象 return BeanUtils.instantiateClass(constructorToUse); } else { // 使用 GCLIG 创建 bean 对象 return instantiateWithMethodInjection(bd, beanName, owner); } }
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { // 设置构造方法为可访问 ReflectionUtils.makeAccessible(ctor); // Kotlin是个啥= = 有个Kotlin的判断 if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) { return KotlinDelegate.instantiateClass(ctor, args); } else { Class<?>[] parameterTypes = ctor.getParameterTypes(); Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters"); Object[] argsWithDefaultValues = new Object[args.length]; for (int i = 0 ; i < args.length; i++) { if (args[i] == null) { Class<?> parameterType = parameterTypes[i]; argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null); } else { argsWithDefaultValues[i] = args[i]; } } // 通过反射创建 bean 实例,这里的 args 是一个没有元素的空数组 return ctor.newInstance(argsWithDefaultValues); } } catch (InstantiationException ex) { throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex); } catch (IllegalAccessException ex) { throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex); } catch (IllegalArgumentException ex) { throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex); } catch (InvocationTargetException ex) { throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); } }
铁子们,这bean创建的过程真是不容小觑,分的情况很多,创建对象就是根据构造方法来创建,构造方法Spring又做了增强比如lookup,Spring又要根据增强和构造方法根据策略生成自己的代理对象出来,一层套一层其中还涉及解析缓存,结果缓存,真的复杂,休息一下。
2.4 obtainFromSupplier-根据定义信息中的Supplier创建
supplier其实也就是一个函数接口,类似FactoryBean都是直接提供对象出来,源码如下:
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) { Object instance; String outerBean = this.currentlyCreatedBean.get(); this.currentlyCreatedBean.set(beanName); try { // 根据你提供的Supplier其实也就是方法 返回 instance = instanceSupplier.get(); } finally { if (outerBean != null) { this.currentlyCreatedBean.set(outerBean); } else { this.currentlyCreatedBean.remove(); } } if (instance == null) { instance = new NullBean(); } BeanWrapper bw = new BeanWrapperImpl(instance); initBeanWrapper(bw); return bw; }
2.4 resolveBeforeInstantiation-勾子处理器InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。
解释两个单词Instantiation 这个是实例化,表示对象还没创建出来,Initialization这个是初始化,对象已经创建完,只是还没初始化属性也就是BeanPostProcessor的前后处理都是针对初始化的,InstantiationAwareBeanPostProcessor自身的方法,是针对创建的过程,直接做干预。
FactoryBean就不说了,它跟构造方法有点像,从方法里边去挑选,去解析筛选。
3 小结
小结就是累了,你仔细去看看构造方法创建bean,那家伙简直调的太多了,有哪里不对的地方,也请评论指出来,互相学习。