上一节讲到了无参构造函数的实例化bean,
这节介绍只有一个有参的构造函数的bean实例化,以
@Component("lmqsthird")
public class LmqDao23456 {
public LmqDao23456(LmqDao2 lmq)
{
}
public void updatesecondquery()
{
System.out.println("updateqseonduery .............");
}
}
为例
查看
AbstractAutowireCapableBeanFactory
的
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
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());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same 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) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
其中
由于此时条件满足
进入
autowireConstructor(beanName, mbd, ctors, args);//创建bean
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {
//首先实例化一个beanwrapper,和无参的类似
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;//获取bd的已解析的构造函数
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;//参数解析器
//此时constructorToUse和argsToUse都为空,继续
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
if (constructorToUse == null) {//如果没有已解析的构造函数,需要去解析(毕竟是有参数的,需要解析)
// Need to resolve the constructor.
//判断传过来的构造方法是否为空,且判断是否根据构造方法自动注入
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;//定义了最小参数个数,一般就是实际的构造方法的参数个数
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {//实例化一个对象,用来存放构造方法的参数值,主要存放了参数值和参数值的下标
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//在通过spring内部给了一个值的情况下,表示满足条件的构造方法的最小参数个数为1,2个的话就是2
比如下面的给lmqfor的构造函数通过 mylmqbeanFactory修改其bd,给构造函数添加了默认值"com.lmq.service"
@Component("lmqfor")
public class LmqDaopara {
Class clz;
public LmqDaopara(Class str)
{
this.clz=str;
}
/*public class mylmqbeanFactory implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition bd= (GenericBeanDefinition) beanFactory.getBeanDefinition("lmqfor");
bd.getConstructorArgumentValues().addGenericArgumentValue("com.lmq.service");
}
}*/
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;//把候选构造方法赋值给candidates
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
AutowireUtils.sortConstructors(candidates);//排序,为何?
/* 访问权限,参数个数排序
比如 某个类的有4个带参构造方法,排序后如下所示
public lmqservice(object o1,object o2,object o3)
public lmqservice(object o1,object o2)
protected lmqservice(object o1,object o2)
protected lmqservice(object o1,object o2)
//这里此时只有一个带参数的构造方法
//定义差异变量
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;//歧义的构造方法
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse.length > paramTypes.length) {
//constructorToUse表示bean实例要使用的构造函数,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;
}
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//获取构造方法参数名称列表
paramNames = pnd.getParameterNames(candidate);
}
}
//获取构造方法参数值列表
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring);
}
catch (UnsatisfiedDependencyException ex) {
if (this.beanFactory.logger.isTraceEnabled()) {
this.beanFactory.logger.trace(
"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// 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);
}
//定义差异量,argsHolder.arguments和paramTypes之间的差异,每个参数值得类型与构造方法参数列表的类型直接的差异,比如有多个构造函数都是一个参数,但参数类型不同,通过此差异量来确定选择一个合适的构造方法,for循环为了选出一个更合适的
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.storeCache(mbd, constructorToUse);
}
}
try {
//同样通过反射创建实例
final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
Object beanInstance;
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
beanFactory.getAccessControlContext());
}
else {
beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
bw.setBeanInstance(beanInstance);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
上面有参构造方法实例化完了。