TintySpring构建过程 Step3-属性注入
在上一步中,我们实现了通过类名来创建一个没有参数的对并进行管理,现在我们进一步的,来添加一个能够注入属性值的工厂。我们暂时不支持在属性中注入其他Bean,现在做的只是对简单的属性进行注入,我们依然通过反射机制来完成这点。
-
我们需要对我们的
BeanDefinition
进行属性的注入,那么我们自然会想到使用一个对象来描述所有的属性值。我们定义一个对象PropertyValue
来描述。(问题1:这里为什么不用一个MAP来解决问题,类似于Map<name,objecy>或者Map<name,PropertyValue>解答末尾)因为一个对象的属性不止一个,所以我们要建立一个List来存储这些PropertyValue
,我们建立一个PropertyValues
来存储PropertyValue
。PropertyValue
public class PropertyValue { private String name; private Object value; public PropertyValue(String name, Object value) { this.name = name; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } }
PropertyValues
public class PropertyValues { private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>(); public PropertyValues() { } public boolean addPropertyValue(PropertyValue propertyValue){ //判断是否会有重复的Value for (PropertyValue propertyValueTemp : propertyValueList){ if (propertyValueTemp.getName().equals(propertyValue.getName())) return false; } propertyValueList.add(propertyValue); return true; } public List<PropertyValue> getPropertyValueList() { return propertyValueList; } }
-
在
BeanDefinition
中添加private PropertyValues propertyValues;
以及相应的get set
方法,并初始化PropertyValues
(防止null) -
重写
AutowireCapableBeanFactory
中的doCreateBean
方法,使其支持属性注入的方式生成Bean。public class AutowireCapableBeanFactory extends AbstractBeanFactory { @Override public Object doCreateBean(BeanDefinition beanDefinition) throws InstantiationException, IllegalAccessException, NoSuchFieldException { Object bean = createBeanInstance(beanDefinition); //bean作为引用直接传入,会在方法里修改Bean的数值 applyPropertys(bean,beanDefinition); return bean; } private Object createBeanInstance(BeanDefinition beanDefinition) throws IllegalAccessException, InstantiationException { return beanDefinition.getBeanClass().newInstance(); } private void applyPropertys(Object bean,BeanDefinition beanDefinition) throws NoSuchFieldException, IllegalAccessException { //bean是严格实例化的对象 而BeanDefinition是一个Bean的形容性类 for(PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValueList()){ Field delclaredFiled = bean.getClass().getDeclaredField(propertyValue.getName()); delclaredFiled.setAccessible(true); delclaredFiled.set(bean,propertyValue.getValue()); } }
-
测试
@Test public void test() throws IllegalAccessException, NoSuchFieldException, InstantiationException { BeanFactory beanFactory = new AutowireCapableBeanFactory(); //初始化BeanDefinition BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setClassName("com.arthur.HelloService"); //设置相应的属性值 PropertyValues propertyValues = new PropertyValues(); propertyValues.addPropertyValue(new PropertyValue("name","big arthur")); propertyValues.addPropertyValue(new PropertyValue("favouriteFood","火鸡面")); propertyValues.addPropertyValue(new PropertyValue("age",new Integer(20))); beanDefinition.setPropertyValues(propertyValues); beanFactory.registerBeanDefinition("hello",beanDefinition); HelloService helloService = (HelloService) beanFactory.getBean("hello"); helloService.hello(); helloService.instroduce(); }
-
总结:在Step-2的基础上添加了简单的属性注入功能,对所有设置的属性进行遍历然后根据其属性名设置属性。
问题1:为什么不用一个MAP来解决PropertyValue
和PropertyValues
,类似于Map<name,objecy>
或者Map<name,PropertyValue>
解答末尾
问题1分析:在之后Spring的进一步扩展中,我们需要进一步的扩展PropertyValue
和PropertyValues
这两个类的方法,使其适应后续的功能升级。在这里我们设计这两个类,就是要为我们后续能够添加新的功能做准备。