《手写Spring渐进式源码实践》-第四章 注入属性和依赖对象

目的:通过模板模式细分拆解Bean对象的实例化过程,将PropertyValues引入BeanDefinition定义中,在对象实例化完成后,填充Bean对象的属性。

BeanReference是类引用

public class BeanReference {
    private final String beanName;

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

    public String getBeanName() {
        return beanName;
    }
}

属性值类

public class PropertyValue {
    private final String name;

    private final Object value;

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }
}

属性集合

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

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

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

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

在BeanDefinition中的构造函数中对PropertyValues属性进行了判断处理,如果值为空,则进行实例化并创建一个PropertyValue类,将其填充到BeanDefinition的propertyValues属性上。

public class BeanDefinition {
    private Class bean;

    private PropertyValues propertyValues;

    public BeanDefinition(Class bean) {
        this.bean = bean;
        this.propertyValues = new PropertyValues();
    }

    public BeanDefinition(Class bean, PropertyValues propertyValues) {
        this.bean = bean;
        this.propertyValues = Objects.nonNull(propertyValues)?propertyValues: new PropertyValues();
    }

    public Class getBean() {
        return bean;
    }

    public void setBean(Class bean) {
        this.bean = bean;
    }

    public PropertyValues getPropertyValues() {
        return propertyValues;
    }

    public void setPropertyValues(PropertyValues propertyValues) {
        this.propertyValues = propertyValues;
    }
}

在AbstractAutowireCapableBeanFactory中主要包括3个方法:createBean、createBeanInstance、applyPropertyValues,这里主要关注在createBean方法中调用applyPropertyValues方法。
在applyPropertyValues方法中,通过获取beanDefinition.getPropertyValues()来循环执行属性填充。如果遇到BeanReference引用类型,则需要通过递归获取Bean对象实例,调用getBean方法。
当完成Bean对象创建和依赖后,则可以通过递归调用的方式来完成属性的填充。这里需要注意,并没有处理循环依赖的问题,
BeanUtil.setFieldValue是hutool-all工具类中提供的属性信息设置方法。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractoryBeanFactory {
    //实例化cblib的实例化策略
    InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiation();
    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition,Object[] args) throws BeansException {
        Object bean;
        try {
            bean = createBeanInstance(beanDefinition,beanName,args);
            //给bean对象填充属性
            applyPropertyValues(beanName,bean,beanDefinition);
        } catch (Exception e) {
            throw  new BeansException("Instantiation of bean failed", e);
        }
        super.registrySingletonBean(beanName,bean);
        return bean;
    }

    /**
     * bean对象属性填充
     * @param beanName
     * @param bean
     * @param beanDefinition
     */
    protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition){
        try {
            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 = super.getBean(beanReference.getBeanName());
                 }
                 //属性填充
                BeanUtil.setFieldValue(bean,name,value);
            }
        } catch (BeansException e) {
            throw new BeansException( "Error setting property values:" + beanName,e);
        }
    }

    protected Object createBeanInstance(BeanDefinition beanDefinition,String beanName,Object[] args){
        Constructor constructorToUse = null;
        Class<?> beanClass = beanDefinition.getBean();
        Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            if(Objects.nonNull(args) && declaredConstructor.getParameterTypes().length ==args.length){
                constructorToUse = declaredConstructor;
                break;
            }
        }
        return getInstantiationStrategy().instantiate(beanDefinition,beanName,constructorToUse,args);
    }

    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }
}

以下是测试代码:

public class UserDao {
    private static Map<String,String> hashMap = new HashMap<>();
    static {
        hashMap.put("10001","小傅哥");
        hashMap.put("10002","八杯水");
         hashMap.put("10003","阿毛");
    }

    public String queryUserName(String uId){
        return hashMap.get(uId);
    }
}
public class UserService {

    private String uId;

    private UserDao userDao;

    public void queryUserInfo(){
        System.out.println("查询用户信息:"+userDao.queryUserName(uId));
    }

    public String getuId() {
        return uId;
    }

    public void setuId(String uId) {
        this.uId = uId;
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
@SpringBootTest(classes = MyApplication.class)
public class ApiTest {
    @Test
    public void test_BeanFactory(){
        //1、初始化BeanFactory对象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //2、注册UserDao
        beanFactory.registryBeanDefinition("userDao", new BeanDefinition(UserDao.class));
        //3、 使用UserService填充属性(uId、userDao)
        PropertyValues propertyValues = new PropertyValues();
        propertyValues.addPropertyValue(new PropertyValue("uId","10001"));
        propertyValues.addPropertyValue(new PropertyValue("userDao",new BeanReference("userDao")));

        //4、使用UserService注册Bean对象
        beanFactory.registryBeanDefinition("userService",new BeanDefinition(UserService.class,propertyValues));

        //5、使用UserService获取Bean对象
        UserService userService = (UserService)beanFactory.getBean("userService");
        userService.queryUserInfo();
    }
}

源码地址:https://github.com/fuzhengwei/book-small-spring/tree/master/spring-step-04

posted @ 2025-06-03 22:49  Charlie-Pang  阅读(15)  评论(0)    收藏  举报