determineConstructorsFromBeanPostProcessors
前面讲了工厂方法的实例化,现在可以讲一般的构造方法实例化了,首先会进行处理器处理,找出合适的构造方法:
@Nullable
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;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors
主要是这个处理器做的事,开始检查Lookup
注解,然后处理,添加方法覆盖。主要还是后面的构造函数获取,首先获取缓存,如果没有的话就获取所有的构造函数,然后每个构造函数都进行遍历,获取注解,如果为空的话,判断是不是代理类,是的话就获取父类,也就是我们自己定义的类,再次获取注解。如果注解存在,就看Autowired
的required
属性,如果有多个是true
或者有一个是true
,其他是false
都会报错,因为他没办法知道该用哪个,如果全是false
,那是可以的。如果只有一个false
,会报一个警告。如果有Autowired
注解的,就优先注解的构造方法,如果没有,就只有一个构造方法且有参数的优先,然后是有优先构造方法,跟Kotlin
有关,所以基本不会优先,然后剩下的就是默认构造方法了。注意如果有多个有参构造方法其实他也不知道要用哪个,实例化的时候会去找默认构造方法,但是没找到,会报异常。
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// 查找lookup
if (!this.lookupMethodsChecked.contains(beanName)) {
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {//遍历当前类以及所有父类,找出Lookup注解的方法进行处理
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);//遍历父类,直到Object
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
}
this.lookupMethodsChecked.add(beanName);//已经检查过
}
//先检查一遍缓存
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);//优先的构造方法,Kotlin的类才有,一般都是空
int nonSyntheticConstructors = 0;
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {//非合成的方法
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);//寻找Autowired和value的注解
if (ann == null) {
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {//如果是有代理的,找到被代理类
try {
Constructor<?> superCtor =//获取构造方法
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);//继续寻找Autowired和value的注解
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
if (ann != null) {
if (requiredConstructor != null) {//有两个Autowired注解,冲突了
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);//是否需要,默认是true
if (required) {
if (!candidates.isEmpty()) {//如果已经有required=false了,又来了一个required=true的方法就报异常了,这样两个可能就不知道用哪个了
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()) {//如果候选不为空,基本就是有Autowired注解的,转换成数组直接返回
// 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 {//大于2个没注解的构造方法就不知道要用什么了,所以就返回null
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
总结下就是:
- 如果有多个
Autowired
,required
有true
,不管有没有默认构造方法,会报异常。 - 如果只有一个
Autowired
,required
是false
,没有默认构造方法,会报警告。 - 如果没有Autowired注解,定义了
2
个及以上有参数的构造方法,没有无参构造方法,就会报错。 - 其他情况都可以,但是以有
Autowired
的构造方法优先,然后才是默认构造方法。
如果构造方法存在且是有参数的,那就会调用autowireConstructor
进行自动装配,如果不存在基本上无参构造方法了,除非有Kotlin
提供优先构造方法。后面来讲自动装配和默认构造方法怎么实例化吧。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。