16. Spring源码篇之指定构造方法参数
简介
为什么讲这个,是因为在spring使用构造方法注入的时候会有大量的判断,是不是指定了参数。如果指定了参数就可以使用不同的构造方法去实例化Bean,本文将介绍如何指定参数
使用
首先看一个例子
// 定义三个构造函数
public class UserBean implements UserGenerics {
public UserBean() {
System.out.println("无参构造函数");
}
public UserBean(String name) {
System.out.println("一个参数 name=" + name);
}
public UserBean(String name, int age) {
System.out.printf("两个参数 name=%s,age=%s", name, age);
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
// 注册一个userBean1,指定有一个参数
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("shura");
beanDefinition.setBeanClass(UserBean.class);
context.registerBeanDefinition("userBean1", beanDefinition);
// 注册一个userBean2,指定有两个参数
GenericBeanDefinition beanDefinition2 = new GenericBeanDefinition();
beanDefinition2.getConstructorArgumentValues().addIndexedArgumentValue(0, "shura");
beanDefinition2.getConstructorArgumentValues().addIndexedArgumentValue(1, 20);
beanDefinition2.setBeanClass(UserBean.class);
context.registerBeanDefinition("userBean2", beanDefinition2);
context.refresh();
}
执行上面代码输出
一个参数 name=shura
两个参数 name=shura,age=20
可见,源码肯定是有这些判断逻辑,我们要先了解有这种使用方式,在看源码才会清晰
先记住 ConstructorArgumentValues 类,后面源码会看到
private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<>();// 保存
private final List<ValueHolder> genericArgumentValues = new ArrayList<>();// 保存
public void addGenericArgumentValue(Object value) {
this.genericArgumentValues.add(new ValueHolder(value));
}
public void addIndexedArgumentValue(int index, @Nullable Object value) {
addIndexedArgumentValue(index, new ValueHolder(value));
}
public void addIndexedArgumentValue(int index, ValueHolder newValue) {
Assert.isTrue(index >= 0, "Index must not be negative");
addOrMergeIndexedArgumentValue(index, newValue);
}
private void addOrMergeIndexedArgumentValue(Integer key, ValueHolder newValue) {
ValueHolder currentValue = this.indexedArgumentValues.get(key);
if (currentValue != null && newValue.getValue() instanceof Mergeable) {
Mergeable mergeable = (Mergeable) newValue.getValue();
if (mergeable.isMergeEnabled()) {
newValue.setValue(mergeable.merge(currentValue.getValue()));
}
}
this.indexedArgumentValues.put(key, newValue);
}
指定构造参数的代码如上,就是保存到了indexedArgumentValues和genericArgumentValues,后面实例化Bean的时候就会用到,实例化Bean的源码后面文章分析
欢迎关注,学习不迷路!