推测构造方法
推测构造方法在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<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;
}
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 声明的构造方法

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 <a href="https://kotlinlang.org/docs/reference/classes.html#constructors">Kotlin docs</a>
*/
对于kotlin类返回与Kotlin主构造函数对应的Java构造函数(在Kotlin规范中定义)。除此之外,特别是对于非kotlin类(java),这只是返回null。所以对于java程序恒返回null
5、对rawCandidates 得到的构造器进行循环
6、查看构造方法是否含有注解(Autowired或Value,如果含有则得到required值)

7、注解不为空

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

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

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、第一个构造器处理

2、参数类型paramTypes

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

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

5、argsHolder

6、赋值替换

7、对下一个构造器处理

for循环退出条件:
1、第一次遍历后 第一次参数比第二次多
处理第一次构造方法时constructorToUse不为null,且paramTypes的参数数量比前一次少,所以退出for。使用三个参数的
(参考例子两个public构造方法,一个三个参数,一个二个参数)
2、经过第一步,参数相同,接下来比较类型差异值。如果当前得到typeDiffWeight 差异值更小,继续赋值。使用具体实现类
(参考例子两个public构造方法,都是只有一个参数,一个接口,一个具体实现类)
3、经过第二步,差异值相同,将会放到ambiguousConstructors,使用第一个
(参考例子,两个public构造方法,都只有一个参数。且都是具体实现类)
lenientConstructorResolution 表示调用构造方法是否采用宽松匹配,默认true。如果设置false且ambiguousConstructors不为null将会报异常
8、storeCache

9、InstantiationStrategy实例化策略CglibSubclassingInstantiationStrategy

10、实例化

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

12、Constructor#newInstance

13、代理构造存取器DelegatingConstructorAccessorImpl

14、NativeConstructorAccessorImpl

15、调用native方法

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

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

3、获取构造器

4、工具类实例化

5、构造器实例化

(接下来的步骤与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创建字节码文件创建类对象
网友评论