spring手撸05: Bean属性注入 Bean依赖注入基本原理

前面说的只是根据有参构造方法的Bean创建, 今天则是来进行属性注入和依赖注入.

比如常见的@Vale属性注入和@Resource依赖注入,不过我们还没那么快跳到注解,而是先讲一下基本的注入.

之前就曾说过, BeanDefinition 没有那么简单,上次改成了Class,这次加入属性.

主要是用于记录Bean需要的属性名,和属性值.

PropertyValue

所以建立一个PropertyValue对象.

@Data
public class PropertyValue {

    private final String name;

    private final Object value;


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

PropertyValues

当然一个类不止一个属性,所以需要一个集合来填入,这里简单封装一下.

public class PropertyValues {

    private final List<PropertyValue> propertyValueList = new ArrayList<>();

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

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

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

}

BeanDefinition

然后就可以改造BeanDefinition

@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;
    }
}

AbstractAutowireCapableBeanFactory

在原本的实例化bean中注入属性

@Getter
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{

    private InstantiationStrategy instantiationStrategy =new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String name, BeanDefinition beanDefinition,Object[] args) throws BeansException {
        Object bean;
        bean = createBeanInstance(beanDefinition,args);
        //补充属性
        applyPropertyValues(bean,beanDefinition);

        addSingletonBean(name,bean);
        return bean;
    }


    protected Object createBeanInstance( BeanDefinition beanDefinition,Object[] args){
        Constructor constructor =null;
        Class beanClass = beanDefinition.getBeanClass();
        //获取所有的构造方法
        Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();
        //简单对比 spring还会对比类型
        for (Constructor ctor : declaredConstructors) {
            if (null!=args && ctor.getParameterTypes().length ==args.length){
                constructor=ctor;
                break;
            }
        }
        //创建
        return getInstantiationStrategy().instantiate(beanDefinition,constructor,args);
    }

    //手撸05新增
    protected void applyPropertyValues(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){
                BeanReference  beanReference=(BeanReference)value;
                //通过bean名去获取bean 跳过循环依赖 后面再补充
                value = getBean(beanReference.getBeanName());
            }
            //通过名称注入属性
            BeanUtil.setFieldValue(bean,name,value);
        }
    }

}

然后是业务类 在service中加了个dao

public class UserService {

    private String uId;

    private UserDao userDao;

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

在UserDao中简单模拟一下

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);
    }
}

然后模拟一下属性注入,以后这些事会用注解来做

@Test
public void applyProperty(){
    //初始化 beanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //注册 Bean
    beanFactory.registerBeanDefinition("userDao",new BeanDefinition(UserDao.class));
     //模拟属性注入
    PropertyValues properties = new PropertyValues();
    properties.addPropertyValue(new PropertyValue("uId","10001"));
    properties.addPropertyValue(new PropertyValue("userDao", (BeanReference) () -> "userDao"));

    BeanDefinition beanDefinition = new BeanDefinition(UserService.class,properties);
    beanFactory.registerBeanDefinition("userService",beanDefinition);
    UserService userService = (UserService) beanFactory.getBean("userService");
    userService.queryUserInfo();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值