在上一篇内容中,介绍了doGetBean方法的源码内容,知道了bean在创建的过程中,有三个范围,单例、多例、Scope,里面都使用到了createBean。下面本篇文章的主要内容,就是围绕createBean来进行展开。

createBean方法

/**
* Create a bean instance for the given merged bean definition (and arguments).
* The bean definition will already have been merged with the parent definition
* in case of a child definition.
* <p>All bean retrieval methods delegate to this method for actual bean creation.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
*/
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException;

在AbstractBeanFactory类中,有createBean接口,具体的创建过程交给了子类进行实现:AbstractAutowireCapableBeanFactory

/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* 创建bean实例、填充bean实例,以及进行一些后置处理
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException { if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd; //将bean类名解析为class引用
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
//如果resolvedClass不为空,且bean定义中没有beanClass,且bean定义拥有beanClassName
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} // Prepare method overrides.
//准备方法覆盖
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
} try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给BeanPostProcessors一个创建代理对象的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
} try {
//创建原生的bean实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

mbdToUse.prepareMethodOverrides()方法的作用,就是验证当前方法是不是被重载了,如果这个方法只重载了一次,那么就设置overloaded为false,来避免参数类型的检查。因为如果这个方法被重载多次,那么在实例化bean实例的时候,就会根据参数类型进行匹配,这一步消耗的时间比较多。

在Spring里面,支持两种方法的覆盖:lookup-method和replace-method,下面简单看下lookup-method的代码示例:

public class User {
public void showUser() {
System.out.println("用户。。。。。。");
}
}
public class Student extends User {

    @Override
public void showUser() {
System.out.println("学生。。。。。。");
}
}
public abstract class DemoTest {

    public void showUser() {
getBean().showUser();
} public abstract User getBean(); public abstract User getBean(String name);
}
<bean id="demoTest" class="edu.demo.spring.instantiate.DemoTest" >
<lookup-method name="getBean" bean="user"></lookup-method>
</bean>
<bean id="student" class="edu.demo.spring.instantiate.Student" />
<bean id="user" class="edu.dongnao.courseware.spring.instantiate.User" />

resolveBeforeInstantiation方法就是通过调用InstantiationAwareBeanPostProcessor里面的方法,在bean实例化的前后进行一些处理,这里是一个扩展点,它会返回bean实例的代理对象,来干涉bean的实例化。

//包可见字段,表示bean实例化前后的处理器已经启动
@Nullable
volatile Boolean beforeInstantiationResolved;
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//如果bean实例化前后的处理器已经启动,就执行下面的代码
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
//在这里要确保bean类已经被实际解析了
//如果bean不是Spring容器自己定义的,并且持有InstantiationAwareBeanPostProcessors
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//确定给定bean定义的目标类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//bean实例化前的处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//bean实例化后的处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

doCreateBean方法

/** Cache of unfinished FactoryBean instances: FactoryBean name to BeanWrapper. */
private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException { //实例化bean定义
BeanWrapper instanceWrapper = null;
//如果bean是单例的,那就先从缓存中获取,然后再进行移除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//这一步就是创建bean实例的主要步骤,里面使用了一些简单的策略,来实例化bean
//工厂方法、构造函数,简单初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//获取包装之后的实例对象
Object bean = instanceWrapper.getWrappedInstance();
//获取包装之后的实例对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
//如果类型不是空bean,就进行赋值
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
}

在bean实例化的时候,把bean封装成了BeanWrapper,BeanWrapper主要有下面的作用:

  • Bean的包装
  • 属性编辑器
  • 属性编辑器注册表
  • 类型转换器

createBeanInstance方法

/** Common lock for the four constructor fields below. */
final Object constructorArgumentLock = new Object(); /** Package-visible field for caching the resolved constructor or factory method. */
//包可见字段,用来缓存解析的构造函数和工厂方法
@Nullable
Executable resolvedConstructorOrFactoryMethod; /** Package-visible field that marks the constructor arguments as resolved. */
//包可见字段,用来标识构造函数的参数已经解析了
boolean constructorArgumentsResolved = false;
/**
* 使用实例化策略,为指定的bean创建一个实例
* 工厂方法、构造器的自动装配、简单实例化
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//解析获得bean对应的class
Class<?> beanClass = resolveBeanClass(mbd, beanName); //如果beanClass不为空,并且beanClass类的修饰符不是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());
} //如果存在Supplier实例化回调接口,那么就使用给定的回调方法来创建一个实例对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
} //如果存在工厂方法,即配置了'factory-method',那么就调用该方法来创建一个实例对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
} // Shortcut when re-creating the same bean...
//在这里,主要就是判断bean定义的构造方法是不是已经解析了
//因为找到匹配的构造方法是一个比较繁琐的过程,所以这里在找到后,会设置到bean定义中
//避免重复的去寻找匹配的构造方法
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
//加锁
synchronized (mbd.constructorArgumentLock) {
//构造方法已经解析出来了
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
//方法有参数的话,这里进行设置一下
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果构造方法或者工厂方法已经解析出来了
if (resolved) {
//如果有参数,就使用下面的方法进行实例化bean
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
//没有参数就使用下面的方法进行实例化bean
return instantiateBean(beanName, mbd);
}
} // Candidate constructors for autowiring?
//如果上面都没有实例化bean,则意味着构造方法或者工厂方法还没有被解析 //通过SmartInstantiationAwareBeanPostProcessor来获取一些构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//如果构造方法不为空,是通过构造器注入的,构造方法持有构造参数,或者定义了一些参数
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);
}

总结一下步骤:

  1. 首先解析获取到beanName对应的beanClass
  2. 然后进行了判断,beanClass不是空的,修饰符不是public,且不允许访问非公共的方法,就抛出异常
  3. 如果存在Supplier实例化回调接口,那么就使用给定的回调方法来创建一个实例对象,里面调用了方法obtainFromSupplier
  4. 如果配置了factory-method,那么就使用该工厂方法来实例化bean,调用了方法instantiateUsingFactoryMethod
  5. 接下来就是一波判断,判断该bean定义的构造方法是不是已经解析出来了,是不是有参数,参数是不是已经解析出来了
  6. 如果构造方法已经解析出来,且有参数的话,就调用autowireConstructor方法来实例化bean,如果没有参数,就调用instantiateBean方法来实例化bean
  7. 如果上面都没有实例化bean,就获取bean定义的一些构造方法,如果获取到的构造方法不是空的,并且是通过构造器注入的,且构造方法定义了一些参数,或者通过getBean外部传进来了一些参数,就调用autowireConstructor方法来实例化bean
  8. 如果还是没有实例化,就获取优先的构造方法,如果获取到了,就调用autowireConstructor方法来实例化bean
  9. 最后,上面都没有实例化bean,就使用默认的构造方法,即无参构造函数来进行实例化bean,调用了instantiateBean方法

obtainFromSupplier方法

/**
* The name of the currently created bean, for implicit dependency registration
* on getBean etc invocations triggered from a user-specified Supplier callback.
*/
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
/**
* 从给定的供应商来获取一个bean实例
* @param instanceSupplier the configured supplier
* @param beanName the corresponding bean name
* @return a BeanWrapper for the new instance
* @since 5.0
* @see #getObjectForBeanInstance
*/
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance; //获取当前线程创建的bean的名称
String outerBean = this.currentlyCreatedBean.get();
//设置当前线程创建的bean的名称
this.currentlyCreatedBean.set(beanName);
try {
//通过调用Supplier的get方法,返回一个bean实例
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
//设置当前线程创建的bean的名称
this.currentlyCreatedBean.set(outerBean);
}
else {
//移除
this.currentlyCreatedBean.remove();
}
} //如果instance为空,就创建NullBean 空对象
if (instance == null) {
instance = new NullBean();
}
//把实例化的bean封装成BeanWrapper
BeanWrapper bw = new BeanWrapperImpl(instance);
//初始化BeanWrapper对象
initBeanWrapper(bw);
//最后返回出去
return bw;
}

总结步骤:

  1. 调用Supplier的get方法返回一个bean实例对象
  2. 使用BeanWrapper对bean实例对象进行包装
  3. 初始化BeanWrapper对象

Supplier接口也是用来创建对象的,这里可以替代bean工厂,简单的使用例子如下:

public class SupplierBean {

    public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(People.class);
definition.setInstanceSupplier(SupplierBean::getPeople);
context.registerBeanDefinition("user2", definition);
context.refresh();
} private static People getPeople() {
return new People("翠花");
} static class People { private String name; public People(String name) {
this.name = name;
} }
}

instantiateUsingFactoryMethod方法

protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

创建ConstructorResolver对象,然后调用了instantiateUsingFactoryMethod方法:

public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
}

上面的方法比较长,下面按照顺序分段进行。

//创建BeanWrapperImpl对象
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化BeanWrapperImpl,设置ConversionService类型转换器
//并且注册了自定义的属性编辑器
this.beanFactory.initBeanWrapper(bw); //工厂bean
Object factoryBean;
//工厂方法所在的类
Class<?> factoryClass;
//是不是静态工厂
boolean isStatic; //获取工厂bean的名称
String factoryBeanName = mbd.getFactoryBeanName();
//如果工厂bean的名称不为空,即没有配置factory-bean,
//意味着这是一个非静态工厂
if (factoryBeanName != null) {
//如果bean定义里面获取的bean匹配上正在创建的bean,则抛异常
//工厂bean引用指向了相同的bean定义
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
//获取工厂bean,即工厂方法所在类的bean,不然的话没办法调用工厂方法
factoryBean = this.beanFactory.getBean(factoryBeanName);
//如果bean定义是单例的,并且bean工厂中存在了这个bean,则抛异常,重复创建
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
//获取工厂的类
factoryClass = factoryBean.getClass();
//标记为非静态工厂
isStatic = false;
}
else {
// It's a static factory method on the bean class.
//这是一个静态工厂,如果找不到对应的beanClass,那么就无法调用方法,抛出异常
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
//静态工厂不需要工厂bean,这里设置为null
factoryBean = null;
//获取到工厂类beanClass
factoryClass = mbd.getBeanClass();
//标记为静态工厂
isStatic = true;
}

上面一部分代码的作用,主要就是用来获取工厂方法相关的信息,继续往下查看:

//包可见字段,标志着构造函数已经被解析
boolean constructorArgumentsResolved = false; //包可见字段,缓存中已经完全解析的参数字段
@Nullable
Object[] resolvedConstructorArguments; //包可见字段,缓存中准备解析的参数字段
@Nullable
Object[] preparedConstructorArguments;
//工厂方法对象
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
//相关的参数
Object[] argsToUse = null; //如果是通过getBean方法指定了参数,那么就直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
//否则,就通过bean定义来获取工厂方法和参数
else {
Object[] argsToResolve = null;
//加锁
synchronized (mbd.constructorArgumentLock) {
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) {
//处理参数值,进行一些类型转换,比如把配置的String类型转为Int类型:A("1")转为A(1)
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.
//获取工厂方法所在类的实例class,因为它可能是cglib包装过的类
factoryClass = ClassUtils.getUserClass(factoryClass); List<Method> candidates = null;
//
if (mbd.isFactoryMethodUnique) {
//获取工厂方法
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
//获取所有候选的工厂方法
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
//如果候选的工厂方法为空
if (candidates == null) {
candidates = new ArrayList<>();
//获取工厂方法所在的类中所有的方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
//遍历进行过滤
for (Method candidate : rawCandidates) {
//是不是和上面的isStatic进行匹配
//是不是和定义的工厂方法名称一样,是的话就加入到候选方法的集合
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
} //如果只找到一个匹配的方法,并且getBean里面传进来的参数explicitArgs是空的,
//并且bean定义里面也没有参数,就直接调用这个方法进行实例化,然后返回
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}

通过上面的代码,找到了所有匹配的工厂方法,那么到底哪个方法是真正匹配上的呢,继续往下看:

//如果找到的工厂方法大于1,先进行排序
if (candidates.size() > 1) { // explicitly skip immutable singletonList
//public修饰的构造函数优先,然后根据参数数量降序
//非public的构造函数根据参数数量降序
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
} //用来存放解析后的方法的参数值
ConstructorArgumentValues resolvedValues = null;
//是否是构造器注入的
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
//匹配方法的集合
Set<Method> ambiguousFactoryMethods = null; //确定方法参数的入参数量,匹配的方法的参数要等于或者多余它 //方法的参数数量的最小值
int minNrOfArgs;
//如果getBean里面指定了参数,那直接使用它作为参数数量的最小值
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
//否则,从bean定义中获取参数的最小值
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.
//如果bean定义中有参数值
if (mbd.hasConstructorArgumentValues()) {
//获取到方法的参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//解析定义的参数值,并返回参数数量
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
//无参,参数最小值为0
minNrOfArgs = 0;
}
} //记录UnsatisfiedDependencyException异常的集合
LinkedList<UnsatisfiedDependencyException> causes = null;

上面一段代码,首先对找到的工厂方法进行了排序,然后确定方法参数的入参数量,后面要找匹配的方法,就是根据参数数量及其类型进行匹配了。

//遍历候选的方法
for (Method candidate : candidates) {
//获取到方法参数的数量
int parameterCount = candidate.getParameterCount(); //方法参数的数量必须要大于或者等于最小参数值
if (parameterCount >= minNrOfArgs) {
//保存参数的对象
ArgumentsHolder argsHolder; //获取方法参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//如果通过getBean指定了参数,直接使用
if (explicitArgs != null) {
// Explicit arguments given -> arguments length must match exactly.
//指定的参数,参数长度必须完全匹配
if (paramTypes.length != explicitArgs.length) {
continue;
}
//创建ArgumentsHolder对象
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);
}
//在给定解析参数的情况下,创建一个ArgumentsHolder对象
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;
}
} //根据权重来获取最匹配的方法
//判断是在宽松模式还是在严格模式下进行解析
//宽松模式:使用具有“最接近的模式”来进行匹配
//严格模式:解析构造函数时,必须所有的都要进行匹配,否则抛出异常
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;
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).
//如果具有相同参数数量的方法具有相同类型的差异权重,那么就把它加入到ambiguousFactoryMethods中
//但是,只能在非宽容的构造函数解析模式下执行该检查
//并显式忽略被覆盖的方法(具有相同的参数签名)
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);
}
}
}

上面一段代码很长,首先遍历了所有的候选方法,然后解析出方法的入参,最后再获取最佳的匹配方法。

if (factoryMethodToUse == null || argsToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
//。。。。。。省略的代码 //把解析出来的工厂方法和参数进行缓存,防止下次使用时再次解析
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}

最后执行下面的代码:

//调用工厂方法创建实例,并设置到bw中,然后返回
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;

最后的调用在SimpleInstantiationStrategy类中的instantiate方法:

Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
//调用工厂方法
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}

可以看到,上面使用到了invoke来进行工厂方法的调用。上面整个流程特别长,下面来总结一下步骤。

总结步骤:

  1. 创建了BeanWrapperImpl对象,然后进行了初始化,设置ConversionService类型转换器,并且注册了自定义的属性编辑器
  2. 然后根据factoryBeanName来判断,这个工厂方法是不是静态工厂
  3. 尝试获取工厂方法和对应的参数,这一步是从缓存中获取
  4. 上面一步获取不到,就去找所有匹配的工厂方法,然后根据方法的参数数量进行匹配
  5. 最后使用反射调用工厂方法进行实例化bean

总而言之,就是要获取到最匹配的工厂方法,然后获取到相关的参数,最后调用该工厂方法进行实例化bean。

autowireConstructor方法

autowireConstructor方法本质上和instantiateUsingFactoryMethod方法类似,一个是找工厂方法,一个是找构造函数,代码里面有很多相似的地方,接下来看一下代码:

protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

创建ConstructorResolver对象,然后调用了autowireConstructor方法:

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {}

这里的代码也比较长,下面进行分段。

//创建BeanWrapperImpl对象
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化BeanWrapperImpl,设置ConversionService类型转换器
//并且注册了自定义的属性编辑器
this.beanFactory.initBeanWrapper(bw); //构造方法
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
//构造方法的参数
Object[] argsToUse = null; //如果getBean中设置了参数,就直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
//否则,从bean定义中尝试获取已经解析的构造方法和参数
else {
//这里是为了防止再次进行解析,因为前面可能已经解析过了
Object[] argsToResolve = null;
//加锁
synchronized (mbd.constructorArgumentLock) {
//获取已经解析的构造方法
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
//如果解析后的构造方法不为空,并且参数也被解析过了
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
//如果获取到的解析过的构造参数是空的,那么就尝试从bean定义中获取未被解析的构造参数
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
//如果获取到了未被解析的构造参数,那就调用下面的方法进行解析
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}

上面的代码,首先是尝试获取构造方法和参数,如果获取不到就走下面的代码:

//如果上一步没有找到对应的构造方法和参数,就开始寻找匹配的构造方法
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
//获取所有的构造方法,如果指定了构造方法的集合,就使用这个集合chosenCtors
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
//获取到beanClass
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);
}
} //如果只找到了一个构造方法,并且getBean传过来的参数是空的
//并且bean定义也没有参数,那么就直接调用这个构造方法来返回一个bean实例
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;
//如果getBean传来的参数不为空,就直接使用它的长度作为参数值的最小数量
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
//否则,从bean定义中获取
else {
//获取构造参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//解析构造参数,并返回参数的数量
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//进行排序,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) {
continue;
} //用来保存参数的对象
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
//获取构造方法的参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
//如果没有获取到,再使用ParameterNameDiscoverer来获取
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 {
// Explicit arguments given -> arguments length must match exactly.
//给出的显式参数->参数长度必须完全匹配
if (parameterCount != explicitArgs.length) {
continue;
}
//创建ArgumentsHolder对象
argsHolder = new ArgumentsHolder对象(explicitArgs);
} //根据权重来获取最匹配的方法
//判断是在宽松模式还是在严格模式下进行解析
//宽松模式:使用具有“最接近的模式”来进行匹配
//严格模式:解析构造函数时,必须所有的都要进行匹配,否则抛出异常
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 (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
//调用构造方法创建实例,并设置到bw中,然后返回
Assert.state(argsToUse != null, "Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;

然后进入到InstantiationStrategy类中,查看调用的接口:

//通过指定的构造函数实例化bean对象
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) throws BeansException;

看下具体的实现:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) { //bean是否存在方法重写,如果不存在就使用newInstance实例化
//否则使用cglib实例化
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;
});
}
return BeanUtils.instantiateClass(ctor, args);
}
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}

来看下BeanUtils.instantiateClass方法:

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);
}
}

如果使用cglib会进入CglibSubclassingInstantiationStrategy类中:

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);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;

总结步骤:

  1. 创建了BeanWrapperImpl对象,然后进行了初始化,设置ConversionService类型转换器,并且注册了自定义的属性编辑器
  2. 尝试获取构造方法和参数,如果getBean指定了参数就直接使用,否则从bean定义中取获取。从bean定义首先获取已经解析的构造方法和参数,如果获取到了尚未被解析的参数,那么就进行解析
  3. 获取所有匹配的构造方法,如果直接指定了构造方法的集合chosenCtors,就直接使用。如果当前获取到的构造方法只有一个,并且getBean没有指定参数,而且从bean定义中也获取不到,那么就调用这个构造方法进行实例的创建
  4. 上面一步如果没有实例化,就开始确定参数的最小数量,要找的构造方法的参数的数量要大于等于它,然后使用权重找到最匹配的构造方法
  5. 最后使用newInstance或者cglib实例化出一个bean实例

总而言之,就是要找到匹配的构造方法,如果有参数,就要进行注入,然后调用这个构造函数来实例化一个bean

instantiateBean方法

使用默认的无参构造函数进行实例化,来看下代码:

/**
* 使用默认的无参构造函数实例化bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return a BeanWrapper for the new instance
*/
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
//权限验证
if (System.getSecurityManager() != null) {
//获取InstantiationStrategy对象,调用instantiate方法来创建实例对象
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
//获取InstantiationStrategy对象,调用instantiate方法来创建实例对象
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
//保存实例化的bean
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
//初始化BeanWrapper
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}

看下SimpleInstantiationStrategy类中instantiate方法:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
//如果没有方法覆盖,就使用反射来进行实例化
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
//加锁
synchronized (bd.constructorArgumentLock) {
//尝试从bean定义中获取已经解析的构造函数
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
//如果为空,就使用默认的构造函数
if (constructorToUse == null) {
//获取class
final Class<?> clazz = bd.getBeanClass();
//如果这个类是接口,抛出异常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
//从clazz中获取构造方法
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
//获取默认的构造方法
constructorToUse = clazz.getDeclaredConstructor();
}
//设置resolvedConstructorOrFactoryMethod,即这个构造方法已经被解析了
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//通过反射实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
//通过CGLIB生成一个子类对象
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

总结步骤:

  1. 首先看是否有方法覆盖,如果没有就使用反射进行实例化
  2. 如果没有找到已经解析出来的构造函数,就使用默认的构造函数
  3. 通过这个默认的构造函数实例化bean对象
  4. 如果存在方法覆盖,就使用CGLIB生成一个子类对象

好了,到此整个bean的创建过程源码,就已经看的差不多了,如有错误请指正,多谢!

Spring源码浅析之bean实例的创建过程(二)的更多相关文章

  1. Spring源码浅析之bean实例的创建过程(一)

    在之前的文章内容中,简单介绍了bean定义的加载过程,下面这篇的主要内容就是bean实例的创建过程. bean实例的创建方式 ApplicationContext context = new Clas ...

  2. spring源码学习之bean的加载(二)

    这是接着上篇继续写bean的加载过程,好像是有点太多了,因为bean的加载过程是很复杂的,要处理的情况有很多,继续... 7.创建bean 常规的bean的创建时通过doCreateBean方法来实现 ...

  3. spring源码浅析——IOC

    =========================================== 原文链接: spring源码浅析--IOC   转载请注明出处! ======================= ...

  4. Spring 源码分析之 bean 依赖注入原理(注入属性)

         最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...

  5. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  6. Spring源码-IOC部分-Bean实例化过程【5】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  7. 【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

  8. Spring 源码分析之 bean 实例化原理

    本次主要想写spring bean的实例化相关的内容.创建spring bean 实例是spring bean 生命周期的第一阶段.bean 的生命周期主要有如下几个步骤: 创建bean的实例 给实例 ...

  9. 【Spring源码分析】Bean加载流程概览(转)

    转载自:https://www.cnblogs.com/xrq730/p/6285358.html 代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. ...

随机推荐

  1. odoo14里面的消息机制

    odoo里面 字段追踪.消息通知机制:  一.使用方式:1.在定义模型的py文件里继承mail模型 class DemoModle(models.Model): """ ...

  2. 浏览器WEB Browser 常识

    浏览器WEB Browser 浏览器发展史 浏览器诞生与发展 浏览器的诞生 早期浏览器 Netscape Internet Explorer 与浏览器战争 chrome的崛起 时代之泪 IE浏览器终成 ...

  3. TS中 使用deprecated 实现对方法的迭代弃用

    在日常开发中,我们会定义大量方法函数来提供给业务调用,可随着时间与业务的推进, 有些方法可能不切合当下需求, 或将被逐步废弃并替换到新的方法中, 例如 框架中 部分生命周期的废弃. 此时作为开发者就很 ...

  4. 软件安装管理(RPM)

    目录 一.linux应用程序 1.1 应用程序与系统命令关系 1.2 典型应用程序的目录结构 1.3 常见的软件包封装工具 二.RPM软件包管理工具 2.1RPM软件包管理器Red-Hat Packa ...

  5. ElasticSearch入门检索

    前面简介说到 elsatic是通过RestFul API接口操作数据的,可以通过postman模拟接口请求测试一下 一._cat 1.GET /_cat/nodes:查看所有节点 2.GET /_ca ...

  6. RHCSA_DAY02

    Linux:一切皆文件 分区:/boot:做引导盘 /swap:虚拟内存----最大20gb /data:自己放文件用 /:根分区 - 图形界面:   - Ctrl+Shift +号   //调整命令 ...

  7. 常见的嵌入式linux学习和如何选择ARM芯片问答

    常见的ARM嵌入式学习问答,设计者和学习者最关心的11个问题: 1.          ARM嵌入式是学习硬件好还是学习软件好? 2.          嵌入式软件和硬件,哪一种职位待遇更高?或者说, ...

  8. chromium调试技巧

    调试技巧: 1.多进程不方便跟踪渲染进程,单渲染进程的设置方法     command_line->AppendSwitchWithValue("--renderer-process- ...

  9. Apache虚拟web主机构建

    目录 一.构建虚拟web主机 1.1.虚拟web主机概述 二.搭建虚拟web主机步骤 2.1.基于域名搭建虚拟主机 ①为虚拟主机提供域名解析 ②为虚拟主机准备网页文档 ③添加虚拟主机配置 ④设置访问路 ...

  10. [WPF] 使用 MVVM Toolkit 构建 MVVM 程序

    1. 什么是 MVVM Toolkit 模型-视图-视图模型 (MVVM) 是用于解耦 UI 代码和非 UI 代码的 UI 体系结构设计模式. 借助 MVVM,可以在 XAML 中以声明方式定义 UI ...