spring bean生命周期之推测构造方法

推测构造方法

推测构造方法在bean的生命周期的第二次后置处理器

调用链

AbstractApplicationContext#refresh
AbstractApplicationContext#finishBeanFactoryInitialization
DefaultListableBeanFactory#preInstantiateSingletons
AbstractBeanFactory#getBean(String)
AbstractBeanFactory#doGetBean
DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory)
ObjectFactory(singletonFactory)#getObject
AbstractBeanFactory#doGetBean(lambda doGetBean 0)
AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#createBeanInstance
AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

示例代码

package com.constructors;
@Component
public class B {
}

package com.constructors;
public class C {
}

package com.constructors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Component
public class A {
    public A(){
        System.out.println("A");
    }
    private A(C b){
        System.out.println("C");
    }
    @Autowired( required = false)
    public A(B b){
        System.out.println("b");
    }
    @Autowired( required = false)
    public A(B b,C c){
        System.out.println("BC");
    }
}

package com.constructors;
@Configuration
@ComponentScan("com.constructors")
public class ConstructorAppConfig {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext an =
                new AnnotationConfigApplicationContext(ConstructorAppConfig.class );
        an.getBean( "a" );
    }
}


package com.constructors;
//AutowireMode自动注入示例代码
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition( "a");
        beanDefinition.setAutowireMode(3);
        System.out.println(beanDefinition.getAutowireMode());
    }
}

determineCandidateConstructors()方法

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors方法

public Constructor[] determineCandidateConstructors(Class beanClass, final String beanName)
            throws BeanCreationException {

        // Let's check for lookup methods here..
        if (!this.lookupMethodsChecked.contains(beanName)) {
            try {
                ReflectionUtils.doWithMethods(beanClass, 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");
                        }
                    }
                });
            }
            catch (IllegalStateException ex) {
                throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
            }
            this.lookupMethodsChecked.add(beanName);
        }

        // 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);
                    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;
                        }
                        AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                        if (ann == null) {
                            Class userClass = ClassUtils.getUserClass(beanClass);
                            if (userClass != beanClass) {
                                try {
                                    Constructor superCtor =
                                            userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                    ann = findAutowiredAnnotation(superCtor);
                                }
                                catch (NoSuchMethodException ex) {
                                    // Simply proceed, no equivalent superclass constructor found...
                                }
                            }
                        }
                        if (ann != null) {
                            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) {
                            defaultConstructor = candidate;
                        }
                    }
                    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.isWarnEnabled()) {
                                logger.warn("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);
                }
            }
        }
        return (candidateConstructors.length > 0 ? candidateConstructors : null);
    }
determineCandidateConstructors方法debug分析

1、查看是否有Lookup注解
2、从candidateConstructorsCache声明构造器缓存查找是否存在(只有原型才有意义)
3、rawCandidates 存储所有的声明的构造方法(包括私有方法)

获取rawCandidates 声明的构造方法
rawCandidates.png

4、primaryConstructor 主要构造方法
kotlin实现的方法,忽略
/**
* Return the primary constructor of the provided class. For Kotlin classes, this
* returns the Java constructor corresponding to the Kotlin primary constructor
* (as defined in the Kotlin specification). Otherwise, in particular for non-Kotlin
* classes, this simply returns {@code null}.
* @param clazz the class to check
* @since 5.0
* @see Kotlin docs
*/
对于kotlin类返回与Kotlin主构造函数对应的Java构造函数(在Kotlin规范中定义)。除此之外,特别是对于非kotlin类(java),这只是返回null。所以对于java程序恒返回null
5、对rawCandidates 得到的构造器进行循环
6、查看构造方法是否含有注解(Autowired或Value,如果含有则得到required值)


findAutowiredAnnotation.png

7、注解不为空


anno.png

8、requiredConstructor
requiredConstructor存储required为true,如果多个带有true将会报错,只能有一个true或多个false
9、candidates
candidates存储required无论是true或false
10、defaultConstructor
defaultConstructor存储注解为null 参数个数为0
candidates.png

11、candidateConstructors
最终得到的构造器方法
candidateConstructors.png

12、candidates不为null分析
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.isWarnEnabled()) {
                                logger.warn("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);
                }
            }

1)根据前面primaryConstructor 表示kotlin形式,primaryConstructor 恒是null。
所以primaryConstructor != null不成立所以带primaryConstructor 的都不成立
2)rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0
声明的构造方法只有1个且构造方法参数的数量大于0,所以仅有一个带参的构造方法,则返回1个
3)带注解
n个都是false且含有默认的则candidates多添加一个默认的构造方法,返回n+1个
n个都是false没有默认的,则返回n个
只有一个false且没有默认的,则返回1个
4)不带注解
只有一个构造方法,且参数个数大于0,则返回1个
只有默认的构造方法则返回null
5)用到的变量
requiredConstructor:构造方法带注解值required是true
defaultConstructor:默认构造方法
primaryConstructor:null
candidates:带注解(无论true或false)

实例化

autowireConstructor()方法

再次推断------通过推测构造器推测结果返回数量不为0或AutowireMode自动注入模型是
AUTOWIRE_CONSTRUCTOR

方法使用变量意义:

1、nonPublicAccessAllowed 允许访问非公开方法、构造方法通过反射 默认是true
beanClass.getDeclaredConstructors()获取所有构造方法,否则只能获取public修饰的
2、minNrOfArgs变量表示构造方法需要使用的参数列表的最小长度。
(例如通过BeanDefinition添加两个构造参数,那么默认构造方法和只有一个参数的将永不会满足)
minNrOfArgs=resolveConstructorArguments()这个方法对添加的构造器参数遍历每次+1。默认是0
3、lenientConstructorResolution 表示调用构造方法是否采用宽松匹配,默认true。

Debug分析

sortConstructors()对构造器排序
for循环对构造器遍历处理
1、第一个构造器处理


sortConstructors.png

2、参数类型paramTypes


paramTypes.png

3、查看是否含有ConstructorProperties注解
ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length)
查看构造器方法上是否有ConstructorProperties注解
evaluate.png

4、参数名字paramNames
ParameterNameDiscoverer默认new DefaultParameterNameDiscoverer()


paramNames.png

5、argsHolder
argsHolder.png

6、赋值替换
constructorToUse.png

7、对下一个构造器处理
candidates2.png

for循环退出条件:
1、第一次遍历后 第一次参数比第二次多
处理第一次构造方法时constructorToUse不为null,且paramTypes的参数数量比前一次少,所以退出for。使用三个参数的
(参考例子两个public构造方法,一个三个参数,一个二个参数)
2、经过第一步,参数相同,接下来比较类型差异值。如果当前得到typeDiffWeight 差异值更小,继续赋值。使用具体实现类

(参考例子两个public构造方法,都是只有一个参数,一个接口,一个具体实现类)
3、经过第二步,差异值相同,将会放到ambiguousConstructors,使用第一个
(参考例子,两个public构造方法,都只有一个参数。且都是具体实现类)
lenientConstructorResolution 表示调用构造方法是否采用宽松匹配,默认true。如果设置false且ambiguousConstructors不为null将会报异常
8、storeCache


storeCache.png

9、InstantiationStrategy实例化策略CglibSubclassingInstantiationStrategy
InstantiationStrategy.png

10、实例化
instantiate.png

11、根据构造器实例化
KotlinDetector.isKotlinType(ctor.getDeclaringClass())
构造器声明的类不是kotlin类
instantiateClass.png

12、Constructor#newInstance
newInstancebyConstructors.png

13、代理构造存取器DelegatingConstructorAccessorImpl
DelegatingConstructorAccessorImpl.png

14、NativeConstructorAccessorImpl
NativeConstructorAccessorImpl.png

15、调用native方法
newInstance0.png

instantiateBean

通过后置处理器推测构造器数量返回0,使用默认无参构造器
1、instantiateBean


instantiateBean.png

2、根据实例化策略实例化


instantiateBeanBy0.png

3、获取构造器
constructorToUseBy0.png

4、工具类实例化
instantiateClassBy0.png

5、构造器实例化


BeanUtilinstantiateClassBy0.png

(接下来的步骤与autowireConstructor的实例化步骤创建对象相同)
12~15

总结:

推断构造方法:

带注解返回(手动注入)
1、有且仅有一个true的,返回这个
2、多个false(或有默认),返回多个
不带注解
1、只有一个构造方法且参数个数大于0---返回这个
2、其余返回null
AutowireMode自动注入

实例化对象

构造方法排序
1、public在private前面
2、参数数量多的在前
根据返回构造器的数量使用不同的方式
1、返回数量0。默认构造方法
2、有。对构造方法排序后使用根据退出条件得到
实例化原理
根据ConstructorAccessorImpl(构造存取器)的DelegatingConstructorAccessorImpl(代理)实现类,并根据inflation策略对代理类赋值,使用NativeConstructorAccessorImpl(调用navite)或asm创建字节码文件创建类对象

你可能感兴趣的:(spring bean生命周期之推测构造方法)