spring----构造方法(第二次后置处理器)

构造方法的判断

一、没有构造方法

依照前面的代码,我们将其中一个类先不加入构造方法,然后条件断点:

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

spring----构造方法(第二次后置处理器)_第1张图片可以看到返回是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() {
//	}
//
	public DaoImpl(String s) {
	}

	@Override
	public void query() {
		System.out.println("DaoImpl");
	}
}

spring----构造方法(第二次后置处理器)_第2张图片这里返回了构造方法,预料之中。

三、有两个构造方法

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呢?继续往下看.

四、给其中一个构造方法加上@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() {
	}

	@Autowired
	public DaoImpl(String s) {
	}

	@Override
	public void query() {
		System.out.println("DaoImpl");
	}
}

spring----构造方法(第二次后置处理器)_第3张图片又返回加上了@Autowired的构造方法了。

五、改为@Autowired(required = false)

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

spring----构造方法(第二次后置处理器)_第4张图片返回了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去指定了我们的构造方法。这就是后置处理器强大的地方,它允许我们程序员介入这个过程。

你可能感兴趣的:(spring源码)