- createBeanInstance
- 实例化Bean的方式
- 回调函数实例化Bean
- 配置回调函数的示例
- 工厂方法实例化Bean
- 参数解析
- 参数类型转换
- 执行工厂方法,实例化Bean
- 指定构造函数实例化Bean
- 参数解析和参数类型转换
- 执行构造函数,实例化Bean
- 默认无参构造函数实例化Bean
说明:我的源码是 v5.2.4.RELEASE 版本,因为几年前看过,有一些相关的注释在上面,所以就没有拉取最新的源码,有可能最新的代码与这个版本有一些差异,但是整体思路应该不差多吧。
实例化是Bean生命周期的第一步,关于Bean生命周期及其源码可以参考 Spring Bean的生命周期 。
Spring实例化Bean的入口是AbstractAutowireCapableBeanFactory.createBeanInstance()
,该方法在AbstractAutowireCapableBeanFactory.doCreateBean()
中被调用。doCreateBean
方法的部分源码如下:
// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); // 从FactoryBean缓存列表中移除
}
/*
* 第一步:实例化Bean。
* 使用合适的实例化策略来实例化新的Bean:回调函数、工厂方法、带参的构造函数、无参构造函数。默认调用无参构造器实例化Bean。
* 构造函数自动注入发生在这一步
*/
if (instanceWrapper == null) { // 为null,说明不是FactoryBean,那么调用工厂或者构造函数实例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 省略掉大量代码,这些代码用于初始化Bean、属性赋值、循环依赖处理等
return exposedObject;
}
createBeanInstance
// AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 从bean定义中解析出当前bean的class对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 检测类的访问权限。对于非public类,默认是允许访问的;若被设置为禁止访问非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());
}
/*
* 这是Spring5提供的一种替换工厂方法的方式,提供一个回调函数实例化Bean
* 自己创建BeanDefinition对象,然后注册到IoC容器中时,有可能使用到这种方式
*/
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
// 这里的代码很简单,就是执行回调函数获取Bean的实例
return obtainFromSupplier(instanceSupplier, beanName);
}
/*
* 判断是不是使用工厂实例化Bean,工厂方法名称不为空,即表示使用工厂方法进行实例化。
* 无论是静态工厂还是实例工厂,都是走这一步
* 通过Java配置类配置的Bean,实例化方式采用的是实例工厂方法,工厂实例就是Java配置类的代理对象
*/
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false; // 判断Bean定义中的构造函数或者工厂方法是否已被解析过
boolean autowireNecessary = false; // 有没有必要进行依赖注入
if (args == null) { // getBean方法传入的参数为null
synchronized (mbd.constructorArgumentLock) {
/*
* 判断bean定义中的resolvedConstructorOrFactoryMethod属性是否有值
* 该属性用来缓存构造函数或者工厂方法,Bean在第一次被实例化的时候,会将解析得到的构造函数或者工厂方法赋值给这个属性
* 对于非单例模式的Bean来说,只需要解析一次Bean定义中的构造函数或工厂方法即可,后续可以直接从Bean定义中拿来使用
*/
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true; // 标记构造函数已被解析过了,原型等非单例模式的Bean,从第二次实例化开始就会进入这里
// 构造函数参数是否被解析过?当使用有参构造函数或者工厂方法实例化Bean时,该属性会被设置为true
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) { // 已经解析过了,直接实例化Bean即可
if (autowireNecessary) {
// 使用有参构造函数实例化对象
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用无参构造函数实例化对象
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
/*
* 调用Bean后置处理器(AutowiredAnnotationBeanPostProcessor),获取用于实例化Bean的构造函数
* 如果有多个构造函数,构造函数上都有@Autowired注解,无论required属性为何值,都会抛出异常,如果仅有一个构造函数有注解,则使用这个
* 如果只有xml配置,这里一般都是返回null
*/
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
/*
* 1. 上一行后置处理器解析出的构造函数不为null
* 2. bean定义中指定自动注入模式是构造器注入
* 这种方式定义的Bean即是构造函数自动注入
* 在构造函数上使用了@Autowire注解,也是构造函数自动注入
* 通过Java配置类定义的Bean,无论方法参数是否有值,都会被解析为构造函数自动注入
* 在Bean定义时,显示指定了构造函数参数(constructor-arg),则不是构造函数自动注入(注意,这里指的自动注入模式)
* 静态工厂和实例工厂定义的Bean,不是构造函数自动注入
* 3. bean定义中指定了构造函数,无论参数是通过名称、类型、下标配置,都是走这一步
* 4. 在外层,调用getBean方法传入的构造器函数参数类型不为null
* 四个条件有一个满足,就使用指定的构造函数进行实例化Bean
*/
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 使用指定的构造函数实例化对象,构造函数自动注入在这里完成
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
/*
* bean定义中的首选构造器
* 目前只有 GenericApplicationContext#ClassDerivedBeanDefinition类的这个方法有返回值,其它都是返回null
* 所以,Bean的实例化,基本不会走这一步
*/
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 实例化Bean
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 如果前面的条件都不匹配,则使用无参构造函数实例化对象
return instantiateBean(beanName, mbd);
}
从上面的源码可以看出,Spring提供了三种实例化Bean的方式:
- Supplier回调函数。这是从Spring5开始提供的一种实例化方式。通过工厂、构造函数实例化对象时,Spring使用的都是反射,而反射的性能相对较差。Supplier回调函数可以自定义实例化过程,无须通过反射调用,直接执行函数即可。
- 工厂方法。又分为静态工厂和实例工厂。
- 构造函数。有参构造函数、无参构造函数。当没有配置使用哪个构造函数时,默认使用无参构造函数实例化。
还有一种实例化方式是FactoryBean
,例如Spring Cloud中实例化FeignClient对象,使用的是FeignClientFactoryBean
。这种方式的流程相对长一些、麻烦一些,这篇文档没有对这种方式进行分析。
在Java配置类中配置的Bean,使用的是实例工厂实例化,实例工厂是Java配置类的代理对象,这个代理对象是在Spring解析Java配置类时创建的。
实例化Bean的方式 回调函数实例化Bean对于非单例模式的Bean,Spring做了一些性能优化,只有第一次实例化Bean时,才需要解析Bean定义的构造函数、工厂方法、参数值等,解析完成之后会将这些数据回写到Bean定义对象的对应属性。下次再创建时,直接从Bean定义中获取即可,无须再次解析。
通过回调函数实例化Bean的代码非常简单,直接执行Bean定义中的回调函数,无须解析参数,也不需要进行反射调用。源码如下:
// AbstractAutowireCapableBeanFactory
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
// 设置当前正在实例化的Bean的名称到ThreadLocal
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
instance = instanceSupplier.get(); // 调用函数,拿到Bean实例
}
finally {
// 重置ThreadLocal
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
// BeanWrapper接口提供了一些 *** 作目标对象属性值的方法
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
配置回调函数的示例
提供一个简单的回调函数配置示例
public class MemberRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition bd = new RootBeanDefinition();
bd.setBeanClass(Member.class);
bd.setInstanceSupplier(Member::new); // 这里注册一个回调函数
registry.registerBeanDefinition("member", bd);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
工厂方法实例化Bean
使用工厂方法实例化Bean的主要代码在ConstructorResolver.instantiateUsingFactoryMethod()
方法中,AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod()
方法仅仅只有一行代码。具体源码如下:
// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
// ConstructorResolver
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 实例工厂Bean对象,如果是静态工厂,值为null
Object factoryBean;
// 工厂的类型
Class<?> factoryClass;
// 是否静态工厂
boolean isStatic;
// 实例工厂的BeanName,如果是静态工厂,则值为null
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
// 如果是实例工厂,进入这个分支
// 实例工厂的Bean名称和需要使用工厂实例化的Bean对象的名称相同,则抛出异常
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 从IoC容器中获取实例工厂对象
factoryBean = this.beanFactory.getBean(factoryBeanName);
// 单例Bean,并且在IoC容器的一级缓存中已存在,说明这个Bean已经被创建过了,不能再次创建,抛出异常
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass(); // 实例工厂的类名,这里可能得到CGLIB生成的子类名称
isStatic = false;
}
else {
// It's a static factory method on the bean class.
// 如果是静态工厂,则进入这个分支
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass(); // 静态工厂的类名
isStatic = true;
}
Method factoryMethodToUse = null; // 用于实例化Bean的工厂方法
ArgumentsHolder argsHolderToUse = null; // 持有 用于实例化Bean的参数 对象
Object[] argsToUse = null; // 用于实例化Bean的参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
/*
* 工厂方法是否已经被解析过
* 第一次实例化Bean时,解析Bean定义,找到实例化Bean的工厂方法,
* 然后会将工厂方法回写到Bean定义中的resolvedConstructorOrFactoryMethod属性,并且constructorArgumentsResolved属性也会被设置为true。
* 当下次再需要实例化这个Bean时,就无须再次解析,直接从Bean定义中获取即可,这是对非单例作用域的Bean实例化过程的优化
*/
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
if (factoryMethodToUse == null || argsToUse == null) {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
// 获取工厂的实际类型,如果是CGLIB生成的子类,则返回原始类;否则返回的就是参数值
factoryClass = ClassUtils.getUserClass(factoryClass);
List<Method> candidates = null; // 可用于实例化Bean的工厂方法
if (mbd.isFactoryMethodUnique) { // 如果是宰Java配置类中配置的Bean,会走这块代码
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) { // 如果是静态工厂或者实例工厂,会走块代码
candidates = new ArrayList<>();
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd); // 获取工厂类的所有方法
/*
* 遍历工厂的所有方法,找出实例化Bean的方法,
* 如果是静态工厂,则方法必须是静态的,且方法名称与Bean定义中的相同;
* 如果是实例工厂,则方法不能是静态的,且方法名称与Bean定义中的相同。
*/
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
/*
* 只有一个符合条件的工厂方法,并且方法没有显示配置参数(工厂方法显示配置参数使用的是构造函数参数标签 constructor-arg)
* 关于Java配置类中定义的Bean的规则说明:
* 无论方法上有没有参数,
* 参数是否使用了@Autowired注解,
* 还是方法内部调用了其它生成Bean的方法,
* 实例化Bean的构造函数是否有参,
* 其在Bean定义中都是没有构造参数/方法的。
*/
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0); // 唯一可以用来实例化Bean的工厂方法
if (uniqueCandidate.getParameterCount() == 0) { // 方法的参数个数为0,这里指的是方法实际的参数,而不是显示配置的参数
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
/*
* 将用于实例化Bean的工厂方法回写到Bean定义的resolvedConstructorOrFactoryMethod属性
* 设置构造函数参数(方法参数)已解析标识为true
* 回写构造函数或工厂方法参数
* 后续如果需要再次实例化Bean,则无需解析。
* 这是对非单例模式Bean实例化的优化手段,只需要第一次实例化时解析,后续实例化Bean就可以直接从Bean定义中拿来用
*/
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 通过反射的方式执行工厂方法实例化Bean,Method.invoke()
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
/*
* 扎到多个名字相同的工厂方法,则先进行排序,排序规则如下:
* 先根据限定符(public\private等)进行排序,public排在最前面,
* 限定符相同,则再根据方法参数数量进行排序,参数多的排在前面
*/
if (candidates.size() > 1) { // explicitly skip immutable singletonList
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}
/*
* 用于保存方法参数值的对象
* 如果是通过索引配置的参数,则使用一个Map保存参数,key是下标值,value是参数值
* 如果是类型、参数名称等其他配置方式,则使用一各List保存参数
*/
ConstructorArgumentValues resolvedValues = null;
/*
* 是否是构造函数自动注入
* 通过Java配置类定义的Bean,无论方法参数是否有值,都会被认为是构造函数自动注入
* 静态工厂和实例工厂定义的Bean,不是构造函数注入
*/
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs; // 方法最小的参数数量
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
if (mbd.hasConstructorArgumentValues()) { // 是否显示配置了参数
// 获取Bean定义中的参数信息,例如有多少个参数,参数是什么类型、名称等,就是Bean定义的参数信息
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
/*
* 解析方法的参数值,如果在方法的配置中指定的其它Bean还没有创建,此处会将需要的Bean创建出来。
* 通过索引配置的参数是单独一种解析方法,解析的结果保存在一个Map中,key是索引,value是值对象。
* 通过默认(只配置了值)、类型、名称配置的参数是同一种解析方法,解析结果保存在一个List中。
* 通过构造器注入,没有显示配置参数时,这一段代码什么都不做。
* 返回值是配置的参数数量,方法的参数数量必须大于等于这个值。
*/
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
// 解析方法参数过程中出现的异常,方法可能被重载,当被解析的方法与Bean定义中的方法无法匹配时,就会抛出异常
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Method candidate : candidates) {
int parameterCount = candidate.getParameterCount(); // 方法的参数数量
if (parameterCount >= minNrOfArgs) { // 方法的参数数量必须大于等于配置的参数数量
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes(); // 方法的参数类型
if (explicitArgs != null) { // explicitArgs是调用getBean方式时传入的参数
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// Resolved constructor arguments: type conversion and/or autowiring necessary.
try {
String[] paramNames = null; // 方法参数的名称
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate); // 解析方法参数的名称
}
/*
* 解析方法的参数,这里会找出方法依赖的Bean
* 配置的参数与方法需要的参数是否匹配,如果不匹配,会抛出异常,然后再解析下一个方法,如果所有的方法都不匹配,才会向外层抛出异常
*/
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
}
catch (UnsatisfiedDependencyException ex) { // 出现异常时,先缓存起来
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
/*
* 根据宽松模式还是严格模式,使用不同的方法计算参数值类型与方法参数类型之间的差异。
* 值类型与参数类型之间的差异越小(计算结果越小),优先级越高。
* 例如对于 Integer 类型的参数,构造函数 (Integer) 将优于构造函数 (Number),而后者又将优于构造函数 (Object)
*/
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) { // 使用优先级更高的方法
factoryMethodToUse = candidate; // 实例化Bean的工厂方法
argsHolderToUse = argsHolder; // 持有工厂方法参数的对象
argsToUse = argsHolder.arguments; // 工厂方法需要的参数
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
// 添加到模糊工厂方法列表,如果是严格模式,且又找到多个匹配的工厂方法,则会抛出异常。默认是宽松模式
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
// 找不到与Bean定义匹配的方法,则抛出异常
if (factoryMethodToUse == null || argsToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
}
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"No matching factory method found: " +
(mbd.getFactoryBeanName() != null ?
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
// 如果工厂方法的返回值是void,则抛出异常
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() +
"': needs to have a non-void return type!");
}
// 严格解析模式,找到了多个模糊匹配的方法,则抛出异常
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse; // 回写工厂方法到Bean定义的属性
// 回写相关信息到Bean定义中,例如上面提到的resolvedConstructorOrFactoryMethod、constructorArgumentsResolved等属性
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
// 通过反射实例化Bean,Method.invoke()
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
使用工厂方法实例化Bean,主要有如下几个步骤:
- 如果是实例工厂,则先获取实例工厂对象。
- 找出可用于实例化Bean的方法,方法可能被重载,那么就会找到多个,此时需要根据方法的参数进行匹配查找。
- 解析配置的参数值,根据索引、类型、名称等解析出配置的方法参数,如果是一个Bean,又还没有创建,则此处会创建这个Bean。
- 将参数值与方法实际参数类型做匹配,找出最终用于实例化的方法,如果找不到,则实例化失败。
- 将方法、参数等数据回写到Bean定义对象的相关属性上,再次创建相同的Bean时,就无需解析,直接从Bean定义中取即可。
- 使用反射的方式执行方法
Method.invoke()
,实例化Bean。
工厂方法参数和构造函数参数的解析都是这个方法。
// ConstructorResolver
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter(); // 自定义的参数类型解析器,默认为null
TypeConverter converter = (customConverter != null ? customConverter : bw); // 如果没有自定义,使用BeanWrapper
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); // Bean定义值解析器
int minNrOfArgs = cargs.getArgumentCount(); // 参数的数量
// 通过索引位置配置的参数,走这里
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
int index = entry.getKey(); // 索引
if (index < 0) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
if (index > minNrOfArgs) {
minNrOfArgs = index + 1;
}
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); // 参数值
if (valueHolder.isConverted()) { // 参数值是否已经转换,例如参数引用了一个Bean,这个Bean是否已经被创建出来
resolvedValues.addIndexedArgumentValue(index, valueHolder); // 回写方法参数
}
else {
// 参数转换后的值,例如参数是一个Bean,则此处会将Bean创建出来,如果Bean已经创建了,则直接从IoC容器中拿到这个Bean。
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
// 保存参数值的对象
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
// 回写方法参数值,索引是key,value是参数值
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
// 默认、类型、名称配置的参数,走这里
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
if (valueHolder.isConverted()) {
resolvedValues.addGenericArgumentValue(valueHolder);
}
else {
// 参数值解析,如果引用了其它Bean,这里会将Bean创建出来
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
resolvedValue, valueHolder.getType(), valueHolder.getName()); // 保存参数值的对象
resolvedValueHolder.setSource(valueHolder);
// 回写方法参数值,保存在一个list中
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
return minNrOfArgs;
}
定义Bean时,配置方法需要的参数,可以仅设值(默认),也可以使用索引位置、参数类型、参数名称多种方式配置。
- 通过索引位置配置的参数,有独立的解析方式,解析结果保存在一个Map中,key是索引位置,value是值对象。
- 其它方式配置的参数,解析方式是一样的,解析结果保存在一个List中。
注意:如果我们在定义Bean时,没有显示的配置参数,则参数不会在这里解析,这个方法相当于什么事都没做,这种情况下 ConstructorArgumentValues resolvedValues
中的Map和List都是空。
上一步解析得到的参数值,其类型并不一定与方法的参数类型匹配,所以需要对参数值做一次类型转换,转换失败则说明不能使用这个方法。
什么情况下会转换失败?
当通过索引、名称进行配置时,得到的参数值的类型就有可能与实际需要的参数类型不匹配,此时就会转换失败,抛出异常。
// ConstructorResolver
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
// 自定义的类型转换器,如果没有自定义,则为null
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
// 如果没有自定义类型转换器,则使用BeanWrapper对象
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length); // 用于保存参数值的对象
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length); // 用于保存参数值的集合
Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // 注入的Bean名称集合,用于注册依赖关系
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { // 遍历方法/构造函数的参数类型
// 当前索引位置的参数类型(方法/构造函数上的参数类型)
Class<?> paramType = paramTypes[paramIndex];
// 当前索引位置的参数名称(方法/构造函数上的参数名称)
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null; // 参数值
// resolvedValues保存的是已经转换过的、显示配置的参数值。如果是构造器自动注入,这个对象中是没有值的
if (resolvedValues != null) {
// 根据Bean定义配置,通过参数索引 -> 参数名称 -> 参数类型 查找参数值
// 如果是构造函数注入,则这里返回的是null
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
// 如果我们找不到直接匹配并且不是自动装配,让我们尝试下一个通用的、无类型的参数值作为后备:它可以在类型转换后匹配(例如,String -> int)。
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
if (valueHolder != null) { // 构造函数注入时,valueHolder为null,所以不会走这个分支
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
// 找到了参数值,则尝试将值转成方法/构造函数需要的类型。
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue(); // 参数转换前的值
Object convertedValue; // 参数转换后的值
if (valueHolder.isConverted()) { // 参数值是否已经转换过了,则无需再次转换
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); // 方法的参数信息
try {
/*
* 参数类型转换,将参数值转换成构造函数上的参数类型,如果无法转换,则抛出异常。
* 当通过索引、名称等方式配置是,可能会转换失败
* BeanWrapperImpl.convertIfNecessary,实际调用的是父类TypeConverterSupport.convertIfNecessary,
* 而真正的转换是TypeConverterDelegate.convertIfNecessary完成的,
* 例如需要一个数组,就创建一个数组,将值放入数组中返回,String换枚举,数字之间的转换等等,
* 这个方法的代码相对比较简单,就不列出来了
*/
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) { // 参数值在转换类型是出现了异常
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
else { // 进入这一步,说明是构造函数自动注入
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex); // 方法参数信息
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
// 不是构造函数自动注入,则抛出异常
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
// 解析自动注入参数,如果依赖的Bean还没有被创建,此处会进行创建BeanFactory.getBean()
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName); // 注册Bean之间的依赖关系
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
参数转换的过程还是相对比较简单的:
- 首先,以下标的方式变量参数类型。这样就能得到当前方法参数的索引、类型、名称,这样无论是通过哪种方式显示配置的参数,都能获取到参数值。
- 然后,获取配置的参数值,首先通过下标获取(Map的key),下标获取不到,则通过名称匹配,类型匹配。
- 最后,将找到的参数值转换成方法需要的类型,这里就可能转换失败了。
获取参数值的源码如下:
// ConstructorArgumentValues
public ValueHolder getArgumentValue(int index, @Nullable Class<?> requiredType, @Nullable String requiredName, @Nullable Set<ValueHolder> usedValueHolders) {
Assert.isTrue(index >= 0, "Index must not be negative");
/*
* 通过索引从Map(indexedArgumentValues)中获取参数值
* 如果还配置了类型,则参数值的类型必须与 requiredType 匹配;没有配置在无须比对
* 如果还配置了名称,则参数值的名称必须与 requiredName 匹配;没有配置在无须比对
*/
ValueHolder valueHolder = getIndexedArgumentValue(index, requiredType, requiredName);
// 通过索引获取不到参数值,则遍历 genericArgumentValues 集合,逐个匹配,先匹配参数名称 -> 再匹配参数类型
if (valueHolder == null) {
valueHolder = getGenericArgumentValue(requiredType, requiredName, usedValueHolders);
}
return valueHolder;
}
// 通过索引取值
public ValueHolder getIndexedArgumentValue(int index, @Nullable Class<?> requiredType, @Nullable String requiredName) {
Assert.isTrue(index >= 0, "Index must not be negative");
ValueHolder valueHolder = this.indexedArgumentValues.get(index);
if (valueHolder != null &&
(valueHolder.getType() == null ||
(requiredType != null && ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) &&
(valueHolder.getName() == null || "".equals(requiredName) ||
(requiredName != null && requiredName.equals(valueHolder.getName())))) {
return valueHolder;
}
return null;
}
// 通过名称、类型取值
public ValueHolder getGenericArgumentValue(@Nullable Class<?> requiredType, @Nullable String requiredName, @Nullable Set<ValueHolder> usedValueHolders) {
for (ValueHolder valueHolder : this.genericArgumentValues) {
if (usedValueHolders != null && usedValueHolders.contains(valueHolder)) {
continue;
}
// 如果配置了名称,则名称必须与 requiredName 匹配
if (valueHolder.getName() != null && !"".equals(requiredName) &&
(requiredName == null || !valueHolder.getName().equals(requiredName))) {
continue;
}
// 如果配置了类型,则类型必须与 requiredType 匹配
if (valueHolder.getType() != null &&
(requiredType == null || !ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) {
continue;
}
// 配置中的类型为空,名称为空(默认 ),则判断参数类型与 requiredType 是否匹配
if (requiredType != null && valueHolder.getType() == null && valueHolder.getName() == null &&
!ClassUtils.isAssignableValue(requiredType, valueHolder.getValue())) {
continue;
}
return valueHolder;
}
return null;
}
执行工厂方法,实例化Bean
// ConstructorResolver
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
this.beanFactory.getAccessControlContext());
}
else {
// 通过反射的方式执行工厂方法(Method.invoke())实例化Bean
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex);
}
}
// SimpleInstantiationStrategy
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
});
}
else {
// 设置工厂方法的访问属性为 true
ReflectionUtils.makeAccessible(factoryMethod);
}
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
// 将当前工厂方法存入ThreadLocal对象
currentlyInvokedFactoryMethod.set(factoryMethod);
// 通过反射执行工厂方法,实例化Bean
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
// ThreadLocal中的值重置
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
// 异常处理代码,省略......
}
别看代码有这么多,实际实例化Bean的就一行代码:通过反射的方式执行工厂方法factoryMethod.invoke(factoryBean, args)
,实例化Bean。
使用构造函数实例化Bean的代码结构、处理步骤,与工厂方法实例化Bean极为相似。
// AbstractAutowireCapableBeanFactory
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
/*
* 用于实例化Bean的构造函数
* 如果有多个符合条件的构造函数,则根据参数类型计算权重,类型越匹配,优先级越高。
* 如果优先级一样,并且构造函数解析模式是宽松模式,则会使用排在前面的构造函数。
* 如果是严格模式,存在优先级一样的构造函数,会抛出异常。这主要发生在根据索引或名称匹配的时候。
* 构造函数的解析模式,默认是宽松模式。
*/
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null; // 保存构造函数参数值的对象
Object[] argsToUse = null; // 构造函数的参数值
if (explicitArgs != null) { // explicitArgs是从getBean方法传入的参数值
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
/*
* 构造函数是否已经被解析过
* 第一次实例化Bean时,解析Bean定义,找到实例化Bean的构造函数,
* 然后会将构造函数回写到Bean定义中的resolvedConstructorOrFactoryMethod属性,
* 如果是有参构造函数,将constructorArgumentsResolved属性设置为true。
* 当下次再需要实例化这个Bean时,就无须再次解析,直接从Bean定义中获取即可,这是对非单例作用域的Bean实例化过程的优化
*/
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// 解析缓存在 bean 定义中的参数
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// chosenCtors是AutowiredAnnotationBeanPostProcessor解析得到的构造函数,如果仅使用xml配置,这个值为null
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass(); // Bean的类型
try {
// 获取Bean class中的所有构造函数
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);
}
}
// 只有一个构造函数,并且Bean定义中没有显示的配置构造函数参数,才执行这块代码
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) { // Bean的class中只要无参构造函数时,才走这一块代码
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 通过反射的方式执行构造函数,实例Bean
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
/*
* 是否是构造函数自动注入,注意:说的是自动注入
* 通过AutowiredAnnotationBeanPostProcessor解析得到的构造函数,当做构造函数自动注入
* 这种方式定义的Bean,使用构造函数自动注入
* 在构造函数上使用了@Autowire注解,也是构造函数自动注入
* 通过Java配置类定义的Bean,无论方法参数是否有值,都会被认为是构造函数自动注入
* 静态工厂和实例工厂定义的Bean,不是构造函数自动注入
* 在Bean定义时,显示指定了构造函数参数(constructor-arg),不是构造函数自动注入
*/
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
/*
* 用于保存构造函数参数值的对象
* 如果是通过索引配置的参数,则使用一个Map保存参数,key是下标值,value是参数值
* 如果是类型、参数名称等其他配置方式,则使用一各List保存参数
*/
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs; // 构造函数最少的参数数量
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 获取Bean定义中显示配置的构造函数参数信息
// Bean定义中的参数可能只是一个引用,而不是我们需要的对象,所以下面的方法根据引用找到对应的实例对象
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 用于存储已经转换过的参数值,在 resolveConstructorArguments 方法中会给这个对象回写值
resolvedValues = new ConstructorArgumentValues();
/*
* 解析构造函数的参数值,如果在构造函数的配置中指定的其它Bean还没有创建,此处会将需要的Bean创建出来。
* 通过索引配置的参数是单独一种解析方法,解析的结果保存在一个Map中,key是索引,value是值对象。
* 通过默认(只配置了值)、类型、名称配置的参数是同一种解析方法,解析结果保存在一个List中。
* 通过构造器注入,没有显示配置参数时,这一段代码什么都不做。
* 返回值是配置的参数数量,构造函数的参数数量必须大于等于这个值。
*/
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 构造函数排序,先根据限定符(public、private等)排序,public修饰的排在前面,限定符相同,再根据参数数量排序,参数多的排在前面
AutowireUtils.sortConstructors(candidates);
// 构造函数的权重,表示参数值的类型与构造函数参数类型之间的匹配度,类型越接近,值越小,优先级越高
int minTypeDiffWeight = Integer.MAX_VALUE;
// 模糊构造函数集合,即能够找到多个符合条件的构造函数,如果是严格模式,会抛出异常
Set<Constructor<?>> ambiguousConstructors = null;
// 用于缓存参数解析异常的对象,如果所有的构造函数都解析失败了,才会在最后抛出异常,只要有一个构造函数能与参数匹配成功,则无需抛出异常
LinkedList<UnsatisfiedDependencyException> causes = null;
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;
}
if (parameterCount < minNrOfArgs) { // 构造函数的参数值数量,不能小于 constructor-arg 配置的参数数量
continue;
}
ArgumentsHolder argsHolder; // 用于保存构造函数需要的参数值
Class<?>[] paramTypes = candidate.getParameterTypes(); // 构造函数的参数类型
// 从上面的代码可以看出,只要调用getBean方法时,没有传入用于创建Bean的参数,resolvedValues就不会为null,最多为empty
if (resolvedValues != null) {
try {
// 构造函数参数的名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
// 使用参数名称解析器 DefaultParameterNameDiscoverer 解析参数名称
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate); // 遍历各种解析策略,解析参数名称
}
}
/*
* 解析构造函数的参数
* 配置的参数与构造函数需要的参数是否匹配,如果不匹配,会抛出异常,然后再解析下一个构造函数,如果所有的构造函数都不匹配,才会向外层抛出异常
* 构造函数自动注入的参数就是在这里进行获取的
*/
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 {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
/*
* 根据宽松模式还是严格模式,使用不同的方法计算参数值与构造参数类型之间的差异。
* 值类型与参数类型之间的差异越小(计算结果越小),优先级越高。
* 例如对于 Integer 类型的参数,构造函数 (Integer) 将优于构造函数 (Number),而后者又将优于构造函数 (Object)
*/
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
/*
* 当前构造函数的优先级是否比上一次的高,如果是,则替换
* 优先级一样,不做替换,从这里可以看出,排在前面的构造函数优先级又高一些
* 优先级比前面的低,那就更不要替换了
*/
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);
}
// 将解析结果回写到Bean定义对象的相关属性,再次创建Bean时,就不需要这么麻烦的解析了
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
// 通过反射的方式执行构造函数实例化Bean。构造函数依赖注入的Bean在上面被解析、找到,在这里用来实例化
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
使用构造函数实例化Bean,主要有以下几个步骤:
- 找出可用于实例化Bean的构造函数,可能找到多个,此时需要根据参数进行匹配查找。
- 解析配置的参数值,根据索引、类型、名称等解析出配置的参数,如果是一个Bean,又还没有创建,则此处会创建这个Bean。
- 将配置参数与构造函数的实际参数类型做匹配,找出最终用于实例化的构造函数,如果找不到,则实例化失败。
- 将构造函数、参数等数据回写到Bean定义对象的相关属性上,再次创建相同的Bean时,就无需解析,直接从Bean定义中取即可。
- 使用反射的方式实例化Bean。
执行构造函数,实例化Bean构造函数的参数解析、参数类型转换与工厂方法参数的解析、转换调用的相同的方法。
具体的代码可以查看上面的内容。
// ConstructorResolver
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
// 通过反射的方式实例化Bean,Constructor.newInstance(args)
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
// SimpleInstantiationStrategy
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
// 使用反射创建Bean实例
return BeanUtils.instantiateClass(ctor, args);
}
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
// BeanUtils
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor); // 将构造函数设置为可访问
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];
}
}
return ctor.newInstance(argsWithDefaultValues); // 使用构造函数创建Bean实例
}
}
// 省略掉所有异常处理的代码
}
别看代码量比较多,实际也就是一行代码的事情,就是通过反射调用构造函数 Constructor.newInstance(args)
。
默认无参构造函数实例化Bean当我们需要使用反射创建一个对象的是,也可以使用Spring的工具类方法
BeanUtils.instantiateClass(Constructor
ctor, Object... args)
// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this; // IoC容器
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
// 通过反射,执行构造函数实例化Bean
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);
}
}
// SimpleInstantiationStrategy
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果不存在方法覆写(lookup-method 和 replaced-method),那就使用 java 反射进行实例化,否则使用 CGLIB
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 构造函数或工厂方法是否有被解析过,第一次解析时会将构造函数或工厂方法回写到Bean定义中
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass(); // Bean的类型
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 {
// 获取class的默认构造函数
constructorToUse = clazz.getDeclaredConstructor();
}
// 将构造函数回写到Bean定义中,下次再创建实例时,无须再次解析
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 使用反射的方式创建Bean实例
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)