依赖注入:如何给Bean注入值并解决循环依赖问题?

值的注入
要理清这个问题,我们要先来看看Spring是如何解析 标签。

我们以下面的XML配置为基准进行学习。

<?xml version="1.0" encoding="UTF-8" ?>

和上面的配置属性对应,在测试类AServiceImpl中,要有相应的name、level、property1、property2字段来建立映射关系,这些实现体现在构造函数以及settter、getter等方法中。

public class AServiceImpl implements AService {
private String name;
private int level;
private String property1;
private String property2;

public AServiceImpl() {
}
public AServiceImpl(String name, int level) {
this.name = name;
this.level = level;
System.out.println(this.name + "," + this.level);
}
public void sayHello() {
System.out.println(this.property1 + "," + this.property2);
}
// 在此省略property1和property2的setter、getter方法
}
接着,简化ArgumentValues类,移除暂时未用到的方法。

public class ArgumentValues {
private final List argumentValueList = new ArrayList<>();
public ArgumentValues() {
}
public void addArgumentValue(ArgumentValue argumentValue) {
this.argumentValueList.add(argumentValue);
}
public ArgumentValue getIndexedArgumentValue(int index) {
ArgumentValue argumentValue = this.argumentValueList.get(index);
return argumentValue;
}
public int getArgumentCount() {
return (this.argumentValueList.size());
}
public boolean isEmpty() {
return (this.argumentValueList.isEmpty());
}
}
做完准备工作之后,我们重点来看核心工作:解析 两个标签。我们要在XmlBeanDefinitionReader类中处理这两个标签。

public void loadBeanDefinitions(Resource resource) {
while (resource.hasNext()) {
Element element = (Element) resource.next();
String beanID = element.attributeValue("id");
String beanClassName = element.attributeValue("class");
BeanDefinition beanDefinition = new BeanDefinition(beanID,
beanClassName);
//处理属性
List propertyElements = element.elements("property");
PropertyValues PVS = new PropertyValues();
for (Element e : propertyElements) {
String pType = e.attributeValue("type");
String pName = e.attributeValue("name");
String pValue = e.attributeValue("value");
PVS.addPropertyValue(new PropertyValue(pType, pName, pValue));
}
beanDefinition.setPropertyValues(PVS);

        //处理构造器参数
        List<Element> constructorElements = element.elements("constructor-

arg");
ArgumentValues AVS = new ArgumentValues();
for (Element e : constructorElements) {
String aType = e.attributeValue("type");
String aName = e.attributeValue("name");
String aValue = e.attributeValue("value");
AVS.addArgumentValue(new ArgumentValue(aType, aName, aValue));
}
beanDefinition.setConstructorArgumentValues(AVS);

        this.simpleBeanFactory.registerBeanDefinition(beanID, 

beanDefinition);
}
}
}
从上述代码可以看出,程序在加载Bean的定义时要获取 ,只要循环处理它们对应标签的属性:type、name、value即可。随后,我们通过addPropertyValue和addArgumentValue两个方法就能将注入的配置读取进内存。

那么,将这些配置的值读取进内存之后,我们怎么把它作为Bean的属性注入进去呢?这要求我们在创建Bean的时候就要做相应的处理,给属性赋值。针对XML配置的Value值,我们要按照数据类型分别将它们解析为字符串、整型、浮点型等基本类型。在SimpleBeanFactory类中,调整核心的createBean方法,我们修改一下。

private Object createBean(BeanDefinition beanDefinition) {
    Class<?> clz = null;
    Object obj = null;
    Constructor<?> con = null;
    try {
        clz = Class.forName(beanDefinition.getClassName());
        // 处理构造器参数
        ArgumentValues argumentValues = 

beanDefinition.getConstructorArgumentValues();
//如果有参数
if (!argumentValues.isEmpty()) {
Class<?>[] paramTypes = new Class<?>
[argumentValues.getArgumentCount()];
Object[] paramValues = new
Object

关键词:

<< 上一篇

让GPT成为你的提效助手!

下一篇 >>

IoC容器