前言:
通过Spring源码分析之Bean的创建过程(createBean)-CSDN博客我们可以知道如果没有动态代理以及循环依赖的前提之下的话那么一个普通的单例Bean的创建后就是实例化,属性填充,初始化这三个步骤那么这篇文章的话我们就先说一下实例化也就是doCreateBean方法里面的createBeanInstance()
createBeanInstance():
这个方法的代码如下所示
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 确保在此点已经解析了bean类
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());
}
if (args == null) {
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
// 如果bean定义中提供了实例供应者,则从供应者获取实例
return obtainFromSupplier(instanceSupplier, beanName, mbd);
}
}
if (mbd.getFactoryMethodName() != null) {
// 如果bean定义中指定了工厂方法,则使用工厂方法创建实例
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) {
// 如果需要自动装配,则调用autowireConstructor方法
return autowireConstructor(beanName, mbd, null, null);
} else {
// 否则,直接实例化bean使用的就是默认的无参构造方法
return instantiateBean(beanName, mbd);
}
}
// 确定可用于自动装配的候选构造器因为是第一次进行加载的
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 如果有候选构造器或需要自动装配构造器,则调用autowireConstructor方法
return autowireConstructor(beanName, mbd, ctors, args);
}
// 获取首选构造器存在多个构造器的话
//那么就会进行挑选选择哪个进行实例话选择最优的方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
//构造方法的自动注入
return autowireConstructor(beanName, mbd, ctors, null);
}
// 默认情况下,使用无参构造器
return instantiateBean(beanName, mbd);
}
1.调用supplier接口:
若 RootBeanDefinition 中设置了 Supplier 则使用 Supplier 提供的bean替代Spring要生成的bean
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
// 从当前已经创建的Bean中获得一个其的名字
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
// 从 Supplier 接口中获取 bean实例
instance = instanceSupplier.get();
}
finally {
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;
}
2.instantiateUsingFactoryMethod():
这个主要就是说通过工厂方法进行创建Bean对象
测试一下毕竟实践出真知:
//这个就是配置类
@Configuration
@ComponentScan("com.example") // 确保这里是你的包路径
public class AppConfig {
@Bean
public BeanFactory myFactory() {
return new BeanFactory();
}
@Bean
public TestBean myBean(BeanFactory beanFactory) {
// 调用工厂对象的实例方法创建 Bean
return beanFactory.createBean("testBean");
}
}
//这个就是工厂类
public class BeanFactory {
public TestBean createBean(String name){
return new TestBean(name);
}
}
//这个就是普通的一个类
public class TestBean {
private String BeanName;
public TestBean(String beanName){
this.BeanName=beanName;
}
@Override
public String toString() {
return "这个的bean的名字为{" + "name='" + BeanName + '\'' + '}';
}
}
最后结果的展示:
3.构造函数的缓存判断:
这个就是说涉及到一个优化的手段了,也就是说这个时候Bean的创建需要使用构造方法进行创建但是Bean的构造方法就有可能会有多个(由于方法重载的出现)那么如果进行判断的话那么这个时候Spring就会将已经判断成功的构造方法放到RootDefinition进行一个缓存的处理
/** Package-visible field for caching the resolved constructor or factory method. */
//缓存以及解析的构造方法以及工厂方法
@Nullable
Executable resolvedConstructorOrFactoryMethod;
/** Package-visible field for caching fully resolved constructor arguments. */
//用于缓存以及解析的构造器的参数
@Nullable
Object[] resolvedConstructorArguments;
/** Package-visible field that marks the constructor arguments as resolved. */
//表示这个构造器的参数以及解析了
//是否需要通过构造注入(autowireConstructor) 的方式加载
boolean constructorArgumentsResolved = false;
// 当重新创建相同的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) {
// 如果需要自动装配,则调用autowireConstructor方法进行依赖注入
return autowireConstructor(beanName, mbd, null, null);
} else {
// 否则,直接实例化bean使用的就是默认的无参构造方法
return instantiateBean(beanName, mbd);
}
}
4.autowireConstructor():
对于一个对象的创建我们就是分为有参构造方法以及无参构造方法,那么对于有参构造方法进行创建的时候就会使用这个方法这个里面进行仔细研究的话其实就是特别复杂但是使用一句话进行概括的话那么就是说就是根据传入的参数列表,来匹配到合适的构造函数进行bean 的创建。
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//explicitArgs这个就是说通过getBean方法传入的参数
//chosenCtors这个就是说是选择的候选的构造方法我的理解就是所有的有参数的构造放啊
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
//变量的初始化
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//如果getBean传入的参数不为空的话那么就直接使用这个参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
//检查是否有以及缓存的构造函数以及构造参数
synchronized (mbd.constructorArgumentLock) {
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) {
//如果存在没有解析的参数那么就会进行准备解析以及准备的参数
//这个已经准备好了
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
//如果还是没有找到能够使用的构造器以及参数的话
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
//获得候选的构造器
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);
}
}
//如果是一个无参构造函数的话那么就会直接进行使用
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;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//对候选构造函数进行排序,优先选择参数更多的构造函数
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
Deque<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 = null;
if (resolvedValues.containsNamedArgument()) {
paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
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, 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 ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
//如果有显式给的参数的话那么参数的数目一定式完全匹配的
if (parameterCount != explicitArgs.length) {
continue;
}
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 (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 on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities. " +
"You should also check the consistency of arguments when mixing indexed and named arguments, " +
"especially in case of bean definition inheritance)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//缓存解析结果,以便后续使用
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
// 使用解析后的构造函数和参数创建 Bean 实例
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
方法总结:
4.1.解析构造函数中的参数 :如果是getBean传入的参数那么就直接进行使用如果没有的话那么就会抓直接从缓存中得到如果参数完全解析成功的话那么直接使用resolvePreparedArguments
进行解析以及准备好的参数
4.2.获得所有的候选的构造函数 (我的理解就是说是所有的有参构造方法):这个就是看有没有传入chosenCtors如果没有的话那么就会通过反射进行获得如果构造函数只有一个 & getBean 没有传参 & 构造参数无参,则直接使用这唯一一个构造函数并返回
4.3.解析构造函数的参数的个数:因为传入的参数不一定就是说是构造方法的参数
4.4.寻找最匹配的构造函数:这个就是根据参数的数目以及类型进行挑选构造函数然后选择完成之后就会调用instantiate(beanName, mbd, constructorToUse, argsToUse)
方法来创建bean实例。
4.5.构造函数的筛选: 这个就是通过构造函数参数的数目以及参数类型之间的差距(优先选择参数数目比较多的构造函数)
4.6.instantiate():进行Bean的创建
获取当前 Bean 工厂的 InstantiationStrategy 实例然后这个进行创建
5. instantiateBean()——无参数构造方法实例化Bean:
这个方法就是说有没有方法进行重写的如果没有的话那么就是进行反射获得器的无参构造方法进行创建否则的话那么就是通过CGLB重写目标类的方法进行实例化
//主要就是这个逻辑
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果 Bean 定义中没有方法覆盖(即没有方法注入
// 则不使用 CGLIB 进行子类生成。
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 尝试从缓存中获取已经解析的构造函数或工厂方法。
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
// 如果没有缓存的构造函数就是获得这个Class
if (constructorToUse == null) {
Class<?> clazz = bd.getBeanClass();
// 5. 如果目标类是一个接口,则抛出异常。
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
// 查找默认构造函数(无参构造函数)。
constructorToUse = clazz.getDeclaredConstructor();
// 7. 将找到的构造函数缓存到 Bean 定义中,以便后续使用。
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//通过反射调用构造函数,创建并返回 Bean 实例。
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 如果 Bean 定义中包含方法覆盖(即有方法注入),则必须使用 CGLIB 生成子类。
// 通过 CGLIB 子类可以动态地重写目标类的方法,从而实现方法注入。
return instantiateWithMethodInjection(bd, beanName, owner);
}
6.第一次进行创建:
如果是第一次进行创建的化那么不会存在缓存构造方法以及参数的那么就进行下面的这个逻辑.
进行简单概括来说激就是说: 如何有构造函数参数或者自动注入有候选的构造函数那么就会调用
autowireConstructor方法也就是我们刚刚在上面说的有参构造函数的放啊
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 如果有候选构造器或需要自动装配构造器,则调用autowireConstructor方法
return autowireConstructor(beanName, mbd, ctors, args);
}
// 获取首选构造器存在多个构造器的话
//那么就会进行挑选选择哪个进行实例话
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 如果有首选构造器,则调用autowireConstructor方法
//这个也就是说添加了@autowire注解的构造方法
return autowireConstructor(beanName, mbd, ctors, null);
}
getPreferredConstructors():
这个方法就是说寻找优先级高的构造方法然后就会进行使用就是还是会进查看是有多个构造方法还是说只有一个构造方法然后不是默认的构造方法的话那么就会使用autowireConstructor()在这个中主要就是说通过@atowire注解表明实际上使用的构造方法当需要进行自动装配的时候,在旧的版本需要在xml文件中进行属性的配置(atowire属性)
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
// 创建一个ConstructorResolver实例,用于处理构造器的解析和自动装配
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
总结:
AbstractAutowireCapableBeanFactory中的CreateInstance就是创建Bean实例的入口我们可以通过实现一些拓展接口来创建Bean实例如(Supplier、factory-method)如果都没有的话那么就是说通过GetBean方法当中参数以及在所有的构造方法挑选出合适的构造方法:如果是在缓存中获得已经解析过的构造方法以及工厂方法那么就是如果需要进行自动注入的话那么就是会使用autowireConstruct进行实例的创建反之就是instantiateBean进行创建(也就是说是默认的),大部分情况都是第一次进行加载那么这个时候就会进行构造方法以及参数的解析(如优先通过使用@autowire注解的构造方法进行创建 当然也可以通过一个类实现SmartInstantiationAwareBeanPostProcessor接口然后根据不同的情况进行选择一个类的不同的构造方法)然后将其进行缓存起来不然的话默认就是会选择无参构造方法进行实例化