chapter04_PropertyValues属性初始化

一、为什么需要PropertyValues

  • Bean中可能会有多个属性,这些属性需要初始化
  • 使用PropertyValues记录所有属性的值,并放入BeanDefinition中
  • 便于实例化Bean后,填充属性的值

二、单个属性的值PropertyValue

新建PropertyValue类,保存一个属性的值,简称pv

@Data
@AllArgsConstructor
public class PropertyValue {
    private final String name;
    private final Object value;
}

三、多个属性的值PropertyValues

新建PropertyValues类,保存多个属性的值,简称pvs

public class PropertyValues {
    private final List<PropertyValue> propertyValueList = new ArrayList<>();

    public void addPropertyValue(PropertyValue pv) {
        this.propertyValueList.add(pv);
    }

    public PropertyValue getPropertyValue(String propertyName) {
        for (PropertyValue pv : propertyValueList) {
            if (pv.getName().equals(propertyName)) {
                return pv;
            }
        }
        return null;
    }

    public PropertyValue[] getPropertyValues() {
        return propertyValueList.toArray(new PropertyValue[0]);
    }
}

四、新增引用类型BeanReference

表示一个Bean对另一个Bean的引用,例如Controller会用到Service

  • 记录引用到的Bean的名称,即可从工厂中获取
/**
 * 一个bean对另一个bean的引用
 *
 * @Author 孤风雪影
 * @Email gitee.com/efairy520
 * @Date 2025/1/2 4:29
 * @Version 1.0
 */
public class BeanReference {
    private final String beanName;

    public BeanReference(String beanName) {
        this.beanName = beanName;
    }

    public String getBeanName() {
        return beanName;
    }
}

五、创建Bean后填充属性值

给BeanDefinition类,加上pvs属性,保存多个属性的值

@Data
public class BeanDefinition {

    private Class<?> beanClass;

    private PropertyValues propertyValues;

    public BeanDefinition(Class<?> beanClass) {
        this.beanClass = beanClass;
        this.propertyValues = new PropertyValues();
    }

    public BeanDefinition(Class<?> beanClass, PropertyValues propertyValues) {
        this.beanClass = beanClass;
        this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
    }
}

六、修改AbstractAutowireCapableBeanFactory类

首先修改createBean的业务逻辑,增加一个方法调用populateBean

@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {
    Object bean = doCreateBean(beanName, beanDefinition, args);
    populateBean(beanName, bean, beanDefinition);
    addSingleton(beanName, bean);
    return bean;
}

新增填充Bean属性值的方法populateBean

  • 如果属性是引用类型,那么就立即从工厂中获取,调用getBean方法
  • 此处先不考虑循环引用
protected void populateBean(String beanName, Object bean, BeanDefinition beanDefinition) {
    PropertyValues propertyValues = beanDefinition.getPropertyValues();
    for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
        String name = propertyValue.getName();
        Object value = propertyValue.getValue();
        if (value instanceof BeanReference) {
            //A依赖B,先实例化B,先不考虑循环引用
            BeanReference beanReference = (BeanReference) value;
            value = getBean(beanReference.getBeanName());
        }
        BeanUtil.setFieldValue(bean, name, value);
    }
}

七、测试

新建Cat类

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Cat {
    private String name;
    private int weight;
}

新建Person类

  • 注意Person有一个Cat属性
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Person {
    private String name;
    private int age;
    private Cat cat;
}

新建测试类

public class ApiTest {

    @Test
    public void test_BeanFactory(){
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //注册cat
        PropertyValues propertyValuesCat = new PropertyValues();
        propertyValuesCat.addPropertyValue(new PropertyValue("name", "tomcat"));
        propertyValuesCat.addPropertyValue(new PropertyValue("weight", 2000));
        beanFactory.registerBeanDefinition("cat", new BeanDefinition(Cat.class, propertyValuesCat));

        //注册person
        PropertyValues propertyValuesPerson = new PropertyValues();
        propertyValuesPerson.addPropertyValue(new PropertyValue("name", "jack"));
        propertyValuesPerson.addPropertyValue(new PropertyValue("age", 35));
        propertyValuesPerson.addPropertyValue(new PropertyValue("cat", new BeanReference("cat")));
        beanFactory.registerBeanDefinition("person", new BeanDefinition(Person.class, propertyValuesPerson));

        Person person = (Person) beanFactory.getBean("person");
        System.out.println("person = " + person);
    }
}

打印输出

person = Person(name=jack, age=35, cat=Cat(name=tomcat, weight=2000))

八、总结

  • 我们可以在创建BeanDefinition的时候,传入PropertyValues,便于初始化属性
  • 在调用getBean带args参数方法,使用的是构造器注入,PropertyValues则是使用set方法注入
  • 后续会通过XML简化Bean的注册,但是底层仍然是BeanDefinition与PropertyValues
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值