Spring源码解析之推断构造方法

网友投稿 213 2022-10-20


Spring源码解析之推断构造方法

Spring推断构造方法

贴个测试代码直接开干,这只是个样例,其他情况自行分析

@Component

public class OrderService {

public OrderService() {

System.out.println("无参构造方法");

}

@Autowired(required = false)

public OrderService(UserService userService) {

System.out.println("一个参数的构造方法");

}

@Autowired(required = false)

public OrderService(String userName, String passWord) {

System.out.println("两个参数的构造方法");

}

}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

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

// 确保class不为空,并且访问权限为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());

}

// 配置的一种特殊的callback回调方法,通过这个callback创建bean

// 检查BeanDefinition是否包含了一个Supplier

Supplier> instanceSupplier = mbd.getInstanceSupplier();

if (instanceSupplier != null) {

// 如果有就直接调用Supplier的get方法得到一个对象直接返回

return obtainFromSupplier(instanceSupplier, beanName);

}

// 通过工厂方法创建

if (mbd.getFactoryMethodName() != null) {

// 如果BeanDefinition中存在FactoryMethodName,那么调用工厂方法得到一个bean对象并返回

return instantiateUsingFactoryMethod(beanName, mbd, args);

}

// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器

// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析

// Shortcut when re-creating the same bean...

boolean resolved = false;

boolean autowireNecessary = false;

if (args == null) {

synchronized (mbd.constructorArgumentLock) {

if (mbd.resolvedConstructorOrFactoryMethod != null) {

// 已经解析过class的构造器

resolved = true;

autowireNecessary = mbd.constructorArgumentsResolved;

}

}

}

if (resolved) {

// 已经解析过class的构造器,使用已经解析好的构造器

if (autowireNecessary) {

// 如果BeanDefinition中已经构造过

// 构造函数自动注入

// 自动装配构造函数,俗称推断构造方法

return autowireConstructor(beanName, mbd, null, null);

}

else {

// 使用默认构造器

return instantiateBean(beanName, mbd);

}

}

// TODO 推断构造方法

// 需要根据参数解析、确定构造函数

// 寻找当前实例化的bean中构造器是否有@Autowire注解

// Candidate constructors for autowiring?

Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

// 解析的构造器不为空 || 注入类型为构造函数自动注入 || 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?

ctors = mbd.getPreferredConstructors();

if (ctors != null) {

return autowireConstructor(beanName, mbd, ctors, null);

}

// 无需特殊处理:只需使用默认的无参构造函数

// No special handling: simply use no-arg constructor.

return instantiateBean(beanName, mbd);

}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors

protected Constructor>[] determineConstructorsFromBeanPostProcessors(@Nullable Class> beanClass, String beanName)

throws BeansException {

// 装配beanPostProcessor的时候会判断其类型并设置 hasInstantiationAwareBeanPostProcessors 属性, 符合条件才去找构造函数

if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {

// getBeanPostProcessors拿到beanFactory中的所有BeanPostProcessor接口,找到一个合格的构造函数

for (BeanPostProcessor bp : getBeanPostProcessors()) {

if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {

SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;

// 获取有autowire注解的构造函数 找到合格的构造函数

// AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors

Constructor>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);

if (ctors != null) {

return ctors;

}

}

}

}

return null;

}

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

public Constructor>[] determineCandidateConstructors(Class> beanClass, final String beanName)

throws BeanCreationException {

// @Lookup标识的属性每次调用都会被重新初始化,

// 有些场景下原型类型的Bean就需要这样做,否则每个Bean只会在spring容器初始化的时候创建一次,

// 但是如果在一个单例的Bean中注入了一个原型的Bean,这样的话原本原型的Bean就相当于变成了一个单例的Bean失去了原有的意义,

// 这时就需要@Lookup来解决,或者是每次都从新从spring容器中通过getBean来获取Bean

// Let's check for lookup methods here...

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

}

// 一般只有原型的bean才会创建多次

// Quick check on the concurrent map first, with minimal locking.

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 {

// 获取所有构造方法

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> candidates = new ArrayList<>(rawCandidates.length);

// 加了@AutoWire()并且是require=true的构造方法

Constructor> requiredConstructor = null;

// 默认构造发给方法

Constructor> defaultConstructor = null;

// 返回与 Kotlin 主构造函数相对应的 java 构造函数, 否则,特别是对于非 Kotlin 类,这只会返回 {@code null}。

Constructor> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);

// 记录合成的构造方法数量,理解为可用的构造方法个数吧

int nonSyntheticConstructors = 0;

// 遍历所有的构造方法

for (Constructor> candidate : rawCandidates) {

if (!candidate.isSynthetic()) {

nonSyntheticConstructors++;

}

else if (primaryConstructor != null) {

continue;

}

// 加了@Autowired的构造方法

MergedAnnotation> ann = findAutowiredAnnotation(candidate);

if (ann == null) {

Class> userClass = ClassUtils.getUserClass(beanClass);

if (userClass != beanClass) {

try {

Constructor> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes());

// 在父类中找@Autowired的构造方法

ann = findAutowiredAnnotation(superCtor);

}

catch (NoSuchMethodException ex) {

// Simply proceed, no equivalent superclass constructor found...

}

}

}

if (ann != null) {

// 如果找到加了@Autowired注解的构造方法,再判断required属性

// 加了@AutoWire()并且是require=true的构造方法

if (requiredConstructor != null) {

throw new BeanCreationException(beanName,

"Invalid autowire-marked constructor: " + candidate +

". Found constructor with 'required' Autowired annotation already: " +

requiredConstructor);

}

boolean required = determineRequiredStatus(ann);

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) {

// 否则如果构造函数参数个数为0,把它赋值给变量defaultConstructor

defaultConstructor = candidate;

}

}

// 处理上面遍历后的结果

if (!candidates.isEmpty()) {

// Add default constructor to list of optional constructors, as fallback.

if (requiredConstructor == null) {

// 如果加了@Autowired、并且没有指定required为true、并且存在默认的构造方法

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

}

// 如果只有一个构造方法,并且构造数的参数大于0

else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {

candidateConstructors = new Constructor>[] {rawCandidates[0]};

}

// primaryConstructor 做java开发一般都是null

else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&

defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {

candidateConstructors = new Constructor>[] {primaryConstructor, defaultConstructor};

}

// primaryConstructor 做java开发一般都是null

else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {

candidateConstructors = new Constructor>[] {primaryConstructor};

}

else {

candidateConstructors = new Constructor>[0];

}

// 把推断的构造方法数组放到缓存map中

this.candidateConstructorsCache.put(beanClass, candidateConstructors);

}

}

}

return (candidateConstructors.length > 0 ? candidateConstructors : null);

推断构造方法第一步,先找出可用的构造方法,步骤如下:

1、先找出所有的构造方法。

2、遍历所有构造方法,找出加了@Autowire的构造方法,如果没找到就在父类中找,父类中还找不到,但是存在一个构造方法的参数的个数为0,就作为默认的构造方法;如果找到了加了@Autowire的构造方法,并且require都为true则直接报错。

3、再次过滤上面筛选过的构造方法,如果有默认构造方法就加入候选者的集合;如果上面筛选过后没有合适的构造方法,但是又只有参数个数大于0的构造方法,就把他加入到候选者的列表中。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor

protected BeanWrapper autowireConstructor(

String beanName, RootBeanDefinition mbd, @Nullable Constructor>[] ctors, @Nullable Object[] explicitArgs) {

// 带有参数情况的实例化

return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);

}

org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,

@Nullable Constructor>[] chosenCtors, @Nullable Object[] explicitArgs) {

//实例化BeanWrapper,是包装bean的容器

BeanWrapperImpl bw = new BeanWrapperImpl();

this.beanFactory.initBeanWrapper(bw);

Constructor> constructorToUse = null;

ArgumentsHolder argsHolderToUse = null;

Object[] argsToUse = null;

// 1、首先判断是否通过getBean方法指定了构造方法参数值

// 如果getBean中传入的参数不为空,那么就使用传入的参数

if (explicitArgs != null) {

argsToUse = explicitArgs;

}

// 否则就需要解析配置文件中的参数

else {

Object[] argsToResolve = null;

// 先尝试从缓存中获取

synchronized (mbd.constructorArgumentLock) {

// 缓存中的构造器

constructorToUse = (Constructor>) mbd.resolvedConstructorOrFactoryMethod;

// 2、针对当前BeanDefinition是否缓存了构造方法和构造方法参数值

if (constructorToUse != null && mbd.constructorArgumentsResolved) {

// 在缓存中找到了构造器,就继续从缓存中寻找缓存的构造器参数

// Found a cached constructor...

argsToUse = mbd.resolvedConstructorArguments;

if (argsToUse == null) {

// 没有缓存的参数,就需要获取配置文件中配置的参数

argsToResolve = mbd.preparedConstructorArguments;

}

}

}

// 如果缓存中没有缓存的参数的话,即argsToResolve不为空,就需要解析配置的参数

if (argsToResolve != null) {

// 解析参数类型,比如将配置的String类型转换成int、boolean等类型

argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);

}

}

// 3、如果两者任意一个为空,则继续进行下面的步骤

// 如果没有缓存,就需要从构造函数开始解析

if (constructorToUse == null || argsToUse == null) {

// 如果传入的构造器数组不为空,就使用传入的构造器参数,否则通过反射获取class中定义的构造器

// Take specified constructors, if any.

Constructor>[] candidates = chosenCtors;

// 3.1 如果没有传入构造方法,那么则获取当前BeanDefinition对应的BeanClass中所有的构造方法作为候选者

if (candidates == null) {

Class> beanClass = mbd.getBeanClass();

try {

// 使用public的构造器或者所有构造器

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

}

}

// 3.2 判断候选者构造方法是不是只有一个,并且没有指定构造方法参数

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) {

// getBean方法传入的参数

minNrOfArgs = explicitArgs.length;

}

else {

// 配置文件中的配置的参数

ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();

// 用于承载解析后的构造函数参数的值

resolvedValues = new ConstructorArgumentValues();

// 解析配置文件中的参数,并且返回参数个数

minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);

}

// 3.3 对候选者构造函数排序,public构造函数优先、参数数量降序排序

AutowireUtils.sortConstructors(candidates);

// 计算构造方法参数个数最少个数

// 意思是如果指定了构造方法参数个数,所以当前BeanDefinition对应的BeanClass中所有构造方法参数个数至少满足手动指定的参数值个数

int minTypeDiffWeight = Integer.MAX_VALUE;

Set> ambiguousConstructors = null;

LinkedList causes = null;

// 3.4 遍历所有的构造方法

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;

}

// 如果候选者参数个数 < minNrOfArgs,则不匹配,继续下一个

if (parameterCount < minNrOfArgs) {

continue;

}

// 封装解析到的参数信息

ArgumentsHolder argsHolder;

Class>[] paramTypes = candidate.getParameterTypes();

// 解析配置文件得到的构造方法参数值

if (resolvedValues != null) {

try {

// 3.5 判断通过getBean方法指定构造方法参数

String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);

if (paramNames == null) {

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 {

// 处理参数由getBean方法传入的情况

// Explicit arguments given -> arguments length must match exactly.

if (parameterCount != explicitArgs.length) {

continue;

}

argsHolder = new ArgumentsHolder(explicitArgs);

}

// 3.7 计算得到的构造方法参数值和参数的匹配程度

// 因为不同构造函数的参数个数相同,而且参数类型为父子关系,所以需要找出类型最符合的一个构造函数

// Spring用一种权重的形式来表示类型差异程度,差异权重越小越优先

// 如果是以宽松的方式解析,默认为true,所以执行getTypeDifferenceWeight

int typeDiffWeight = (mbd.isLenientConstructorResolution() ?

argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));

// 当前构造函数最为匹配的话,清空先前ambiguousConstructors列表

// Choose this constructor if it represents the closest match.

if (typeDiffWeight < minTypeDiffWeight) {

constructorToUse = candidate;

argsHolderToUse = argsHolder;

argsToUse = argsHolder.arguments;

minTypeDiffWeight = typeDiffWeight;

ambiguousConstructors = null;

}

// 存在相同权重的构造器,将构造器添加到一个ambiguousConstructors列表变量中

// 注意,这时候constructorToUse 指向的仍是第一个匹配的构造函数

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()) {

// 如果存在多个构造函数匹配程度相同,并且BeanDefinition中设置isLenientConstructorResolution为false(默认值为true),

// 表示构造器创建为严格模式的话,会抛出异常。异常代码略

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、只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化 candidates.length == 1

2、有多个构造方法或者bean需要通过构造方法自动进行注入 ResolvedAutowireMode() == 3

3、根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数 minNrOfArgs

4、对所有的构造方法进行排序,参数个数多的在前面 AutowireUtils.sortConstructors

5、遍历所有的构造方法

6、如果当前构造方法参数个数小于minNrOfArgs则不匹配,继续判断下一个构造方法

7、如果是调用getBean方法指定的参数就直接利用这些值,如果不是就根据构造方法参数类型找值(先byType再byName),匹配的话则封装成一个ArgumentsHolder对象

8、这里可能会匹配到多个构造方法,然后就需要那值和构造方法匹配程度计算一个权重,值越小优先级越高(因为如果是父子类的话子类匹配成功更高)

9、计算权重分为宽松型(默认)和严格型,严格型的情况下如果有多个匹配就报错


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:什么是光纤收发器?光纤收发器的两种连接方案你了解吗?
下一篇:web安全入门-搜索引擎信息
相关文章

 发表评论

暂时没有评论,来抢沙发吧~