上一节,分析了下,bean的创建,但是没有具体分析一些重要的方法,而是简单的从整体看了下bean实例的创建,大概就是从缓存中获取,
未命中,创建bean实例,解决循环依赖,填充bean属性,到最后的收尾工作
今天这节内容,我们分析第一个比较重要的方法,createBeanInstance,我把他比喻为我们买的毛坯房,还没有装修,只是房子已经盖起来了
那马这个方法做的事情,就是盖房子的事情,废话不多说了,我们直接进入今天的主题
#createBeanInstance
#AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//这个方法会通过先检查bean中是否有bean的全路径名称,有的话,直接返回,如果没有,就通过反射的方式获取bean类
//这个方法,后期有时间咱们可以再看,今天就不解析这个方法了
Class> beanClass = resolveBeanClass(mbd, beanName);
//这里的判断条件是说,如果beanClass不为null的情况下
//1:不是被publc修饰.并且不允许公共访问的话,直接抛出异常
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容器中查询是否存在这个bean实例,存在的话,调用obtainFromSupplier创建bean对象
Supplier> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//判断bean定义中是否存在工厂方法,存在的话,使用instantiateUsingFactoryMethod创建bean对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 这里是说如果是重复实例化一个bean,resolved会被修改为true,不用在判断使用哪个方式创建bean对象
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果resolved被修改为true,则进入到下面这段逻辑
if (resolved) {
if (autowireNecessary) {
//通过构造方法自动注入的方式创建bean对象
return autowireConstructor(beanName, mbd, null, null);
}
else {
//通过通用的方式创建bean对象
return instantiateBean(beanName, mbd);
}
}
//通过后置处理器获取构造器数组,
//1;判断构造器数组是否为空
//2:bean定义中自动注入模式是否被指定为构造器注入
//3:是否存在构造器参数
//4:参数是否为空,
//只要某一项为true,就会使用构造方法自动注入的方式创建对象
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//如果以上都不成立,看看是否指定了bean定义的首选构造函数,指定的话
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
//通过构造方法自动注入的方式创建对象
return autowireConstructor(beanName, mbd, ctors, null);
}
// 通过通用方式创建bean对象
return instantiateBean(beanName, mbd);
}
简单总结下,以上说到了spring通过几种方式创建bean对象
1:判断当前解析的bean是否在Supplier容器中存在,如果存在,通过obtainFromSupplier的方式创建bean对象
2:判断bean定义是否存在工厂方法,存在的话,使用instantiateUsingFactoryMethod工厂方法的方式创建bean对象
3:对于相同的bean,就不会再去判断使用哪种方式创建了,直接使用构造方法自动注入的方式或者通用方法的方式创建对象
4:查看是否配置了指定的默认首选构造方式,指定的话,通过构造方法自动注入的方式创建对象
5:如果以上都不满足,直接通过通用的方式创建bean对象
我们先从通用的方式创建bean对象这个方法开始具体分析instantiateBean
#instantiateBean
#AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
Object beanInstance;
final BeanFactory parent = this;
//1:通过策略模式实例化bean对象
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
//2:创建bean包装对象
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
//3:初始化bean包装对象
initBeanWrapper(bw);
//返回bean包装对象
return bw;
}
#SimpleInstantiationStrategy
#instantiate
#为了看得清楚,我删除了,安全代码,以及异常信息代码,
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
//查看该bean是否被覆盖,因为默认我们的bean都是单例的,但是我们可以指定为原型模式,
//也就是说如果当前bean如果配置了Scope注解,并将值设定为原型,或者在配置文件中指定了该bean为lookup-Method则会走else逻辑
//通过cglib的方式创建bean对象,否则走if逻辑
if (!bd.hasMethodOverrides()) {
Constructor> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class> clazz = bd.getBeanClass();
//如果当前的clazz是接口,直接抛出异常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
//返回类指定的构造函数
constructorToUse = clazz.getDeclaredConstructor();
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
}
//通过beanUtils实例化bean对象
return BeanUtils.instantiateClass(constructorToUse);
}
else {
//通过CGLIB创建bean对象
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
#BeanUtils
#BeanUtils.instantiateClass
public static T instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
//执行权限的设置
ReflectionUtils.makeAccessible(ctor);
//下面是一个三元运算符,
//由于spring增加了对Kotlin的支持,所以这里会有通过Kotlin实例化一个bean对象的处理方式这个我们就不介绍了
//有兴趣的同学可以研究下Kotlin我们主要看ctor.newInstance
//我们终于看到了newInstance,这代表着我们已经生成一个对象了,也就是说通过一系列的操作通过bean的全限定类名最终
//调用newInstance生成了实例
ctor.newInstance(args);
return (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
}
简单总结一下,
默认构造方式:
1:判断当前bean是否设置了lookup-method,如果设置了,就走cglib代理的方式创建bean,否则通过默认的方式创建bean
2:通过BeanUtils.instantiateClass最终调用newInstance的方式返回bean实例,
3:创建bean包装对象
4:初始化bean包装对象
5:返回bean包装对象
我们在简单介绍下通过CGLIB创建bean对象,我上面已经提到过,如果配置了lookup-methd,则会走else分支就是下面这个方法
instantiateWithMethodInjection(bd, beanName, owner);
在BeanFactories中使用的默认对象实例化策略。如果方法需要被容器重写以实现,则使用CGLIB动态生成子类
#CglibSubclassingInstantiationStrategy
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
return instantiateWithMethodInjection(bd, beanName, owner, null);
}
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Constructor> ctor, Object... args) {
// Must generate CGLIB subclass...
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
public Object instantiate(@Nullable Constructor> ctor, Object... args) {
//通过createEnhancedSubclass方法生成一个subclass(增强子类)
Class> subclass = createEnhancedSubclass(this.beanDefinition);
//================================================================
使用CGLIB为提供的bean 定义创建bean类的增强子类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
if (this.owner instanceof ConfigurableBeanFactory) {
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
}
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
//==================================================================
Object instance;
if (ctor == null) {
//这里有看见了熟悉的 BeanUtils.instantiateClass方法
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;
}
cglib我没有具体分析,就是给生成代理类,然后通过代理类调用 BeanUtils.instantiateClass的实例对象,就不做具体的分析了,大家可以看源码哈
以上就是我们通用的创建bean实例的方式
接下来,我们分析通过构造方法自动注入的方式创建bean
autowireConstructor(beanName, mbd, null, null);
#AbstractAutowireCapableBeanFactory
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor>[] ctors, @Nullable Object[] explicitArgs) {
//创建构造解析器对象
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
#ConstructorResolver
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor>[] chosenCtors, @Nullable Object[] explicitArgs) {
//创建bean包装对象,并初始化
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//给参数对象数组赋值
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//获取解析的构造器对象
constructorToUse = (Constructor>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
//获取缓存的构造对象数组
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
//如果缓存中不存在,就从部分准备好的数组对象中获取
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
//解析预处理参数
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
//当构造器对象为null或者参数数组为null的时候进入下面的逻辑
if (constructorToUse == null || argsToUse == null) {
// 从指定的构造函数里获取构造对象
Constructor>[] candidates = chosenCtors;
if (candidates == null) {
//如果没有指定构造器,就从当前bean中的构造器
Class> beanClass = mbd.getBeanClass();
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
//如果只配置了构造器对象,没有配置,参数,则会走这段逻辑,我们看源码也会最终看到BeanUtils.instantiateClass
//就不做过多的解释了,这段代码比较简单,
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);
}
//对构造器执行排序,因为可能我们在一个类中不止一个构造器,可能有多个构造器
//如下所示,我定义了两个构造器
//============================================
public Dog(String names, int age, String sex) {
this.names = names;
this.age = age;
this.sex = sex;
}
public Dog(String names, int age) {
this.names = names;
this.age = age;
}
//配置文件:
运行后的结果是:
Dog{names='小黄', age=12, sex='雄性'}
Dog{names='小五', age=10, sex='null'}
//==============================================
//简单说一下排序.参数多的会排在前面,public修饰的会排在前面
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set> ambiguousConstructors = null;
LinkedList causes = null;
for (Constructor> candidate : candidates) {
Class>[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
if (paramTypes.length < minNrOfArgs) {
continue;
}
//判断是否存在ConstructorProperties 注解,如果有注解,则是取注解的值执行赋值
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
//类型转换.我们的参数都是按照字符串注入的,所以,这里会按照原来的属性执行类型转换
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, 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 (paramTypes.length != 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 " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
以上就是创建bean实例的过程,下一节.我们来分析下,填充属性,既然bean实例创建完成了,就该装修了!