Spring对bean的实例化,实际上也是调用类的构造方法进行实例化对象的,这篇文章单独针对Spring如何调用类的构造方法来创建对象进行源码分析。
bean实例化的过程我们主要看createBeanInstance这个方法,这里面有个分支逻辑,如果bean配置了factoryMethod方法,factoryMethod里面一定是对bean的实例化,通过factoryMethod方法可以暴露给用户实例化过程的叫做显示实例化;如果没有配置工厂方法,bean实例化的细节不暴露给用户,则是所谓的隐式实例化。
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
如果bean配置了factoryMethod,则看instantiateUsingFactoryMethod这个方法:
// 获取bean的factoryBeanName
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
// bean的factoryBeanName不能是和bean相同,否则会报错
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 获取factoryBean对象
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
// factoryMetho为非静态方法
isStatic = false;
}
else {
// 如果bean没有配置factoryBean,那么必须配置class
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
// factoryMethod需要为静态方法
isStatic = true;
}
在配置文件,bean可以配置以下属性:
<bean id="" class="" factory-bean="" factory-method="">bean>
从上面的分支条件可以总结出有两种情况:
if (candidates == null) {
candidates = new ArrayList<>();
// 得到工厂类的所有方法,包括父类的方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
for (Method candidate : rawCandidates) {
// 判断是否符合上面的分支条件,并且过滤到工厂方法放到candidates中
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
将工厂方法统一放到candidates中,这里就会产生分支条件:
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
这里采取了策略模式,instantiate方法其实很简单,本质上还是采用反射进行实例化。
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
如果bean没有配置工厂方法,那么就要获取bean的有效构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
那我们来看一下具体的细节
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 这里只有AutowiredAnnotationBeanPostProcessor对此进行了处理
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
让我们进入determineCandidateConstructors中:
// 首先获取bean的所有构造方法
rawCandidates = beanClass.getDeclaredConstructors();
// 循环构造方法
for (Constructor<?> candidate : rawCandidates) {
// 返回方法上的@Autowire和@Value注解
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann != null) {
// 注解上面的required属性
boolean required = determineRequiredStatus(ann);
if (required) {
// 如果required为true,则只能有一个注解修饰的构造方法
requiredConstructor = candidate;
}
// 将注解修饰的构造方法放入到candidates中
candidates.add(candidate);
} else if (candidate.getParameterCount() == 0) {
// 判断是否无参构造方法
defaultConstructor = candidate;
}
}
if (!candidates.isEmpty()) {
if (requiredConstructor == null) {
if (defaultConstructor != null) {
// 如果没有required为true的注解修饰的构造方法,
//则把默认构造方法加入到candidates中
candidates.add(defaultConstructor);
}
}
// 集合转换为数组Constructor>[]
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
} else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
//如果只有一个不加注解的有参构造函数
candidateConstructors = new Constructor<?>[] {
rawCandidates[0]};
} else {
// 否则为空数组
candidateConstructors = new Constructor<?>[0];
}
返回构造方法的数组后,这里就有了两种情况:
return instantiateBean(beanName, mbd);
return autowireConstructor(beanName, mbd, ctors, args);
这里主要看数组不为空的情况:
return new ConstructorResolver(this)
.autowireConstructor(beanName, mbd, ctors, explicitArgs);
// 将构造方法进行排序
AutowireUtils.sortConstructors(candidates);
for (Constructor<?> candidate : candidates) {
if (resolvedValues != null) {
try {
// 获取构造函数的参数
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 将构造方法中的参数实例化
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
}
}
遍历出最匹配的构造函数,并把该构造函数的参数实例化之后调用:
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
instantiate中又是怎么操作的呢?
// 构造函数的参数
Class<?>[] parameterTypes = ctor.getParameterTypes();
for (int i = 0 ; i < args.length; i++) {
if (args[i] == null) {
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive()
? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {
argsWithDefaultValues[i] = args[i];
}
}
得到参数的值放到argsWithDefaultValues数组中,之后
return ctor.newInstance(argsWithDefaultValues);
本质上还是利用了构造函数反射出bean实例。
经过源码分析总结出: