文章目录
- 前言
- 思考
- 目标
- 一、bean的实例化入口-createBeanInstance
- 1、源码逻辑思路**核心点,主要做了几件事情**
- 2、instantiateBean-默认无参实例化
- 3、instantiate-实例化
- 4、instantiateClass-实例化类
- 二、获取构造函数候选数组-determineConstructorsFromBeanPostProcessors
- 1、确定构造方法的核心方法-determineCandidateConstructors
- 主要做了几件事情
- 2、推断构造方法简易流程图
- 三、确定最终构造函数并实例化-autowireConstructor
- 主要做了几件事情
- 结论
前言
Spring中的一个bean,需要实例化得到一个对象,而实例化就需要用到构造方法。
默认是采用无参的构造方法去进行实例化,那如果一个类有多个构造方法,他是怎么选择的?
对要看源码的小伙伴说声,如果要自己去看spring源码,这一块比较绕,最好是有目标的去看,不容易迷失方向
思考
@Component
public class UserService {
// 构造方法0
public UserService(){
System.out.println(0);
}
// 构造方法1
public UserService(OrderService orderService) {
this.orderService = orderService;
System.out.println(1);
}
// 构造方法2
public UserService(OrderService orderService,OrderService orderService1) {
this.orderService = orderService;
System.out.println(2);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userSerivce = (UserService) context.getBean("userService");
}
上面代码
1、多个构造函数下,获取到的bean是采用的哪一个构造方法?答案是构造方法0(采用无参构造方法)
2、如果把上面的无参构造方法注释掉,这时候会采用哪一个构造方法?答案是在没有特殊处理的情况下,会报错
但是如果上面这种情况,添加了@Autowired注解,他会采用带@Autowired注解的构造方法(当然此外还有很多场景,暂不一一描述)
3、如果把构造方法0和构造方法1都注释掉,会采用构造方法2吗?答案是会
目标
先定个小目标,本章尽量说明白上面列出的正常情况下的源码处理解析
一、bean的实例化入口-createBeanInstance
// 使用适当的实例化策略为指定的bean创建一个新实例:工厂方法、构造函数自动装配或简单实例化。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 获取Bean定义的class
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());
}
// BeanDefinition中添加的Supplier,调用Supplier对象来得到对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// @Bean对应的BeanDefiniton的实现
if (mbd.getFactoryMethodName() != null) {
// 核心方法之一
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 一个原型BeanDefinition,会多次创建Bean,所以会把该BeanDefiniton缓存起来使用,避免每次都进行构造方法的推断
boolean resolved = false;
boolean autowireNecessary = false;
// args表示传进来的构造方法的带参的参数
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 缓存构造函数,只能缓存一个,在确认构造函数后缓存的
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// autowireNecessary表示有没有必要注入,比如当前构造方法是无参的,那么autowireNecessary为空
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 如果确定了BeanDefintion的构造方法,那么需要判断是否需要进行有参构造方法的参数的依赖注入
if (autowireNecessary) {
// 方法内会拿到缓存好的构造方法入参
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 构造方法已经找到了,但是没有参数,就认为是无参构造方法,直接进行实例化即可
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 自动装配的候选构造函数? 如果没找到,从这里开始寻找构造方法
// 提供一个扩展点,可以利SmartInstantiationAwareBeanPostProcessor来控制beanClass中的哪些构造方法
// 比如AutowiredAnnotationBeanPostProcessor会把加@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
// 如果没有推断出来构造方法,但是autowiremode 为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法财值,因为不确定是用无参还是有参
// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
// 默认是null
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、源码逻辑思路核心点,主要做了几件事情
1、获取beanClass
2、方法带@bean的构造函数处理
3、如果args入参为空,则看有没有缓存过构造函数
4、如果有缓存过
4.1、则看有没有缓存的入参参数,有的话则执行autowireConstructor去创建bean
4.2、如果没有缓存入参,则直接执行无参构造方法
5、如果没有缓存过构造函数,则通过determineConstructorsFromBeanPostProcessors去寻找类可用的构造函数
6、如果找到了可用的构造函数,则执行autowireConstructor去创建bean
7、如果上述条件都不满则,则执行无参构造函数生成实例
2、instantiateBean-默认无参实例化
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
// 安全检测,所以不会进来
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 进行实例化
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
// 把实例化的对象包装成BeanWrapper ,并进行初始化
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
3、instantiate-实例化
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) {
// 获取构造函数的缓存
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) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
// 拿到类的构造方法
constructorToUse = clazz.getDeclaredConstructor();
}
// 构造方法缓存,方便原型bean的时候,直接走缓存
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
4、instantiateClass-实例化类
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);
}
}
catch (Exception ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
}
二、获取构造函数候选数组-determineConstructorsFromBeanPostProcessors
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 只有AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors有进行实现
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
1、确定构造方法的核心方法-determineCandidateConstructors
调用地址:
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// 1、从method中寻中Lookup
if (!this.lookupMethodsChecked.contains(beanName)) {
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
});
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
}
this.lookupMethodsChecked.add(beanName);
}
// 2、从候选构造缓存中,获取匹配的构造函数数组
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
// 3、获取类下的所有构造函数
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
Constructor<?> requiredConstructor = null;
Constructor<?> defaultConstructor = null;
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
// 4、遍历构造函数上面是否有@Autowired
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
Class<?> userClass = ClassUtils.getUserClass(beanClass);
// 正常情况是相等的, 所以不深究里面if逻辑
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
// 5、有@autowreid或者@value的会进if
if (ann != null) {
// 循环第一次肯定为空 ,不会进,如果有多个@autowreid且required为true的则异常
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
// 6、获取注解的required属性值
boolean required = determineRequiredStatus(ann);
// 7、缓存required的构造函数
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
// 8.1 、指定带@autowreid注解的构造函数
// 8.2 、只有一个构造函数,且带参数
// 8.3 、8.4 用不到的场景
// 8.5 、以上都不满足,就返回空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
// 多个构造函数,或者只有一个无参这里会返回null
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
主要做了几件事情
1、从method中寻中Lookup
2、从候选构造缓存中,获取匹配的构造函数数组
3、获取类下的所有构造函数
4、遍历构造函数上面是否有@Autowired
5、有@autowreid或者@value的会进if(主要判断是否有多个@autowreid)
6、获取注解的required属性值
7、缓存required的构造函数(用于步骤5判断处理)
8、返回构造函数数组 or null
8.1 、指定带@autowreid注解的构造函数
8.2 、只有一个构造函数,且带参数
8.3 、8.4 用不到的场景
8.5 、以上都不满足,就返回空
下面的流程图对应上面的代码
2、推断构造方法简易流程图
三、确定最终构造函数并实例化-autowireConstructor
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// 默认进if
if (constructorToUse == null || argsToUse == null) {
// 获取指定的构造函数
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);
}
}
// 1、如果构造函数只有一个,并且该构造函数的入参为null,直接去实例化
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;
}
}
// 2、获取是否有指定AUTOWIRE_CONSTRUCTOR,
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
// 3、构造函数的入参如果不为空,则获取入参数量
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 4、从bean定义里获取缓存过的构造函数的入参
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 5、构造函数排序(降序,数量越多的最前面),用于后面找到最合适匹配度最高的构造函数
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
// 6、开始遍历构造函数数组
for (Constructor<?> candidate : candidates) {
// 获取构造函数的参数数量
int parameterCount = candidate.getParameterCount();
// 7、如果是之前已经缓存过的构造函数,且传递构造函数入参也不为空,并且传递的参数大于当前构造函数的参数个数,则直接结束循环(因为没必要在循环,因为传递的参数已经大于数组里最多的参数数量了)
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;
}
// 8、小于当前构造函数结束本次循环
if (parameterCount < minNrOfArgs) {
continue;
}
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;
}
主要做了几件事情
1、如果构造函数只有一个,并且该构造函数的入参为null,直接去实例化
2、获取是否有指定AUTOWIRE_CONSTRUCTOR
3、构造函数的入参如果不为空,则获取入参数量
4、从bean定义里获取缓存过的构造函数的入参
5、构造函数排序(降序,数量越多的最前面),用于后面找到最合适匹配度最高的构造函数
6、开始遍历构造函数数组(选出最匹配的构造函数)
7、如果是之前已经缓存过的构造函数,且传递构造函数入参也不为空,并且传递的参数大于当前构造函数的参数个数,则直接结束循环(因为没必要在循环,因为传递的参数已经大于数组里最多的参数数量了)
8、小于当前构造函数结束本次循环
9、把遍历里拿到的构造函数进行实例化
结论
正常情况下(不添加注解等其他因素)
1、如果有无参,默认采用无参构造方法
2、如果有多个构造方法,并且也有无参构造方法,也是采用无参构造方法
3、如果没有无参构造方法,且有多个不同带参构造方法会报错
4、如果没有无参构造方法,且只有一个带参构方法,就会采用唯一构造方法
带@Autowired注解情况下
1、只有一个@Autowired的required为true的,就构造
2、多个@Autowire的required为true,报错
3、多个@Autowire的required为false,就循环遍历,找到构造函数参数最多的那个
4、如果构造函数有相同的,则进行权重打分,分越低 优先级越高