本文作者:chenssy
出处:http://cmsblogs.com/?p=2850
在学习Spring源码
的过程中发现的好站+好贴,感谢作者。Spring版本:Spring 5.0.6.RELEASE
createBeanInstance()
用于实例化 bean,它会根据不同情况选择不同的实例化策略来完成 bean 的初始化,主要包括:
- Supplier 回调:
obtainFromSupplier()
- 工厂方法初始化:
instantiateUsingFactoryMethod()
- 构造函数自动注入初始化:
autowireConstructor()
- 默认构造函数注入:
instantiateBean()
在( IOC 之 Factory 实例化 bean) 中分析了 Supplier 回调和工厂方法初始化,这篇分析两个构造函数注入。
autowireConstructor()
这个初始化方法我们可以简单理解为是带有参数的初始化 bean 。代码段如下:
public BeanWrapper autowireConstructor( final String beanName, final RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null;
if (explicitArgs != null) { argsToUse = explicitArgs; } else {
Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; } } }
if (argsToResolve != null) { argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); } }
if (constructorToUse == null) { boolean autowiring = ( chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); }
Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { 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); } }
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) { Class<?>[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse.length > paramTypes.length) { break; } if (paramTypes.length < minNrOfArgs) { continue; }
ArgumentsHolder argsHolder; if (resolvedValues != null) { try { String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); if (paramNames == null) { 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); } if (causes == null) { causes = new LinkedList<>(); } causes.add(ex); continue; } } else { if (paramTypes.length != explicitArgs.length) { continue; } argsHolder = new ArgumentsHolder(explicitArgs); }
int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
if (typeDiffWeight < minTypeDiffWeight) { 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); } }
try { 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 { 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); } }
|
代码与 instantiateUsingFactoryMethod()
一样,又长又难懂,但是如果理解了 instantiateUsingFactoryMethod()
初始化 bean 的过程,那么 autowireConstructor()
也不存在什么难的地方了,一句话概括:首先确定构造函数参数、构造函数,然后调用相应的初始化策略进行 bean 的初始化。关于如何确定构造函数、构造参数,该部分逻辑和 instantiateUsingFactoryMethod()
基本一致,所以这里不再重复阐述了,具体过程请移步IOC 之 Factory 实例化 bean,这里我们重点分析初始化策略。 对于初始化策略,首先是获取实例化 bean 的策略,如下:
final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
|
然后是调用其 instantiate()
方法,该方法在 SimpleInstantiationStrategy 中实现,如下:
public Object instantiate( RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { 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); } } }
return BeanUtils.instantiateClass(constructorToUse); } else { return instantiateWithMethodInjection(bd, beanName, owner); } }
|
如果该 bean 没有配置 lookup-method、replaced-method 标签或者 @Lookup 注解,则直接通过反射的方式实例化 bean 即可,方便快捷,但是如果存在需要覆盖的方法或者动态替换的方法则需要使用 CGLIB 进行动态代理,因为可以在创建代理的同时将动态方法织入类中。 反射 调用工具类 BeanUtils 的 instantiateClass()
方法完成反射工作:
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { ReflectionUtils.makeAccessible(ctor); return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ? KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args)); } }
|
CGLIB
protected Object instantiateWithMethodInjection( RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { throw new UnsupportedOperationException( "Method Injection not supported in SimpleInstantiationStrategy"); }
|
方法默认是没有实现的,具体过程由其子类 CglibSubclassingInstantiationStrategy 实现:
protected Object instantiateWithMethodInjection( RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { return instantiateWithMethodInjection(bd, beanName, owner, null); }
protected Object instantiateWithMethodInjection (RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Constructor<?> ctor, @Nullable Object... args) {
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args); }
|
创建一个 CglibSubclassCreator 对象,调用其 instantiate()
方法生成其子类对象:
public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) { Class<?> subclass = createEnhancedSubclass(this.beanDefinition); Object instance; if (ctor == null) { instance = BeanUtils.instantiateClass(subclass); } else { try { Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); instance = enhancedSubclassConstructor.newInstance(args); } catch (Exception ex) { throw new BeanInstantiationException( this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex); } }
Factory factory = (Factory) instance; factory.setCallbacks(new Callback[] { NoOp.INSTANCE, new CglibSubclassingInstantiationStrategy .LookupOverrideMethodInterceptor( this.beanDefinition, this.owner), new CglibSubclassingInstantiationStrategy .ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)}); return instance; }
|
到这类 CGLIB 的方式分析完毕了,当然这里还没有具体分析 CGLIB 生成子类的详细过程,具体的过程等后续分析 AOP 的时候再详细地介绍。
instantiateBean()
protected BeanWrapper instantiateBean( final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController .doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy() .instantiate(mbd, beanName, parent), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
|
这个方法相比于 instantiateUsingFactoryMethod()
、 autowireConstructor()
方法实在是太简单了,因为它没有参数,所以不需要确认经过复杂的过来来确定构造器、构造参数,所以这里就不过多阐述了。
对于 createBeanInstance()
而言,他就是选择合适实例化策略来为 bean 创建实例对象,具体的策略有:Supplier 回调方式、工厂方法初始化、构造函数自动注入初始化、默认构造函数注入。
其中工厂方法初始化和构造函数自动注入初始化两种方式最为复杂,主要是因为构造函数和构造参数的不确定性,Spring 需要花大量的精力来确定构造函数和构造参数,如果确定了则好办,直接选择实例化策略即可。当然在实例化的时候会根据是否有需要覆盖或者动态替换掉的方法,因为存在覆盖或者织入的话需要创建动态代理将方法织入,这个时候就只能选择 CGLIB 的方式来实例化,否则直接利用反射的方式即可,方便快捷。 到这里 createBeanInstance()
的过程就已经分析完毕了。