依照前面的代码,我们将其中一个类先不加入构造方法,然后条件断点:
package test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DaoImpl implements Dao {
// public DaoImpl() {
// }
//
// public DaoImpl(String s) {
// }
@Override
public void query() {
System.out.println("DaoImpl");
}
}
package test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DaoImpl implements Dao {
// public DaoImpl() {
// }
//
public DaoImpl(String s) {
}
@Override
public void query() {
System.out.println("DaoImpl");
}
}
package test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DaoImpl implements Dao {
public DaoImpl() {
}
public DaoImpl(String s) {
}
@Override
public void query() {
System.out.println("DaoImpl");
}
}
又为null了?为什么提供2个构造方法反而返回null呢?继续往下看.
package test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DaoImpl implements Dao {
public DaoImpl() {
}
@Autowired
public DaoImpl(String s) {
}
@Override
public void query() {
System.out.println("DaoImpl");
}
}
package test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DaoImpl implements Dao {
public DaoImpl() {
}
@Autowired(required = false)
public DaoImpl(String s) {
}
@Override
public void query() {
System.out.println("DaoImpl");
}
}
返回了2个构造方法!
这个为什么会这样呢?
这里因为存在后置处理器调用链非常复杂,我也调试了很久才找到关键代码。下面就贴关键代码。至于调试就自行根据注释调试。org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors这个方法中。关键代码如下:
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here...
//@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);
}
// Quick check on the concurrent map first, with minimal locking.
//缓存中拿构造器,一般为null
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 {//反射拿到class中的所有构造方法
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存储构造器
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;
}
//查找是否有@Autowired或者@Value注解,如果有就拿到这个注解,没有就返回null
MergedAnnotation<?> 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.
//如果required为false这个条件就成立,就会添加默认的构造方法,因此可能返回2个构造方法。
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]);
}
//候选的构造方法只有一个且参数大于0
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//如果不是混合构造方法有2个且存在主要的构造方法且默认构造方法不为空且primaryConstructor != defaultConstructor
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//如果不是混合构造方法有1个且存在主要的构造方法
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//new一个空的Constructor
else {
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
那么程序员可不可以手动改变构造方法呢?
通过源码可以知道spring允许程序员去插手,方式是通过实现SmartInstantiationAwareBeanPostProcessor方法实现。测试的代码及注释如下,此外前面的@Autowired也去掉:
package test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DaoImpl implements Dao {
public DaoImpl() {
}
public DaoImpl(String s) {
}
@Override
public void query() {
System.out.println("DaoImpl");
}
}
package test.mypostprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
import test.dao.Dao;
import test.dao.DaoImpl;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
@Component
public class MYSmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
//预测最终从这个处理器的回调返回的bean的类型。
@Override
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
// return String.class;
if(beanName.equals("daoImpl"))
System.out.println("predictBeanType");
return null;
}
//第二次调用
//确定要用于给定bean的候选构造函数。
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
if(beanName.equals("daoImpl")) {
System.out.println("determineCandidateConstructors");
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
List<Constructor<?>> constructors = new ArrayList<>(declaredConstructors.length);
for (java.lang.reflect.Constructor<?> declaredConstructor : declaredConstructors) {
constructors.add(declaredConstructor);
}
List<Constructor<?>> constructor=new ArrayList<>();
Constructor<?> temp = constructors.get(1);
constructor.add(temp);
return constructor.toArray(new Constructor<?>[0]);
// Constructor>[] declaredConstructor =declaredConstructors[0];
}
return null;
}
/**
*获取对指定bean的早期访问的引用,通常用于解析循环引用。
* 这个回调函数将会给后置处理器一个早点暴露一个wrapper的机会,也就是说,在目标的bean实例完全初始化之前。
*所暴露的对象在某些方面应该等价于postProcessBeforeInitialization和postProcessAfterInitialization这个对象。
* 注意被方法返回的对象将会被用于bean的引用除非从被定义的post-processor调用返回了不一样的wrapper,换句话说,
*这些post-processor调用可能最终使用了相同的引用或者从那些后来的回调中返回了原生的bean实例
* (如果受影响bean的wrapper已经为调用此方法而构建,默认情况下会被当成最终的暴露bean引用)
* @param bean the raw bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
if(beanName.equals("daoImpl"))
System.out.println("getEarlyBeanReference");
return null;
}
}
如果按照spring的处理方式,这里应该返回为null。但这里我们通过实现了SmartInstantiationAwareBeanPostProcessor去指定了我们的构造方法。这就是后置处理器强大的地方,它允许我们程序员介入这个过程。