这一步,我们想要为bean注入属性。我们选择将属性注入信息保存成PropertyValue对象,并且保存到BeanDefinition中。这样在初始化bean的时候,我们就可以根据PropertyValue来进行bean属性的注入。Spring本身使用了setter来进行注入,这里为了代码简洁,我们使用Field的形式来注入。
-------------------------------------------------------------
注意:Field类位于java.lang.reflect包下。
在Java反射中Field类描述的是:类的属性信息。简而言之,通过Field类的一些常用方法,可以设置类的属性值等。详细情况请参考java api。
-------------------------------------------------------------
类图:
时序图:
代码:
1·BeanFactory接口:
package us.codecraft.tinyioc.factory;/**
* Created by 贾丽敏 on 2017/5/29.
*/
import us.codecraft.tinyioc.BeanDefinition;
/**
* @author
* @create 2017-05-29 15:14
**/
public interface BeanFactory {
//获取bean
Object getBean(String name);
//注册bean
void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception;
}
2·AbstractBeanFactory抽象类:
package us.codecraft.tinyioc.factory;/**
* Created by 贾丽敏 on 2017/5/29.
*/
import us.codecraft.tinyioc.BeanDefinition;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* @author
* @create 2017-05-29 15:17
**/
public abstract class AbstractBeanFactory implements BeanFactory {
private Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
Object bean = doCreateBean(beanDefinition);
beanDefinition.setBean(bean);
beanDefinitionMap.put(name,beanDefinition);
}
//初始化bean
protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception;
}
3·子类AutowireCapableBeanFactory:
package us.codecraft.tinyioc.factory;/**
* Created by 贾丽敏 on 2017/5/29.
*/
import us.codecraft.tinyioc.BeanDefinition;
import us.codecraft.tinyioc.PropertyValue;
import java.lang.reflect.Field;
/**
* 自动初始化bean
* @author
* @create 2017-05-29 15:23
**/
public class AutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
Object bean = createBeanInstance(beanDefinition);
applyPropertyValues(bean,beanDefinition);
return bean;
}
protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception{
return beanDefinition.getBeanClass().newInstance();
}
protected void applyPropertyValues(Object bean,BeanDefinition beanDefinition) throws Exception{
for(PropertyValue propertyValue:beanDefinition.getPropertyValues().getPropertyValueList()){
//Field类:描述类的属性信息,在这里,将对应的属性绑定(设置)到相应的object对象中
Field declaredField=bean.getClass().getDeclaredField(propertyValue.getName());
declaredField.setAccessible(true);
declaredField.set(bean,propertyValue.getValue());
}
}
}
4·bean对象封装类BeanDefinition:
package us.codecraft.tinyioc;/**
* Created by 贾丽敏 on 2017/5/29.
*/
/**
*
* @author
* @create 2017-05-29 15:08
**/
public class BeanDefinition {
private Object bean;
private Class beanClass;
private String beanClassName;
private PropertyValues propertyValues;
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
public Object getBean() {
return bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
//TODO:Class.forName?
this.beanClass=Class.forName(beanClassName);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
5·属性类PropertyValue:
package us.codecraft.tinyioc;/**
* Created by 贾丽敏 on 2017/5/29.
*/
/**
*
* @author
* @create 2017-05-29 16:12
**/
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;
}
}
6·属性复合类PropertyValues:
package us.codecraft.tinyioc;/**
* Created by 贾丽敏 on 2017/5/29.
*/
import com.sun.javafx.scene.control.skin.VirtualFlow;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author
* @create 2017-05-29 16:14
**/
public class PropertyValues {
private final List<PropertyValue> propertyValueList=new ArrayList<PropertyValue>();
public void addPropertyValue(PropertyValue pv){
this.propertyValueList.add(pv);
}
public List<PropertyValue> getPropertyValueList(){
return this.propertyValueList;
}
}
7·bean对象类HelloWorldService:
package us.codecraft.tinyioc;
/**
* Created by 贾丽敏 on 2017/5/29.
*/
/**
*
* @author
* @create 2017-05-29 10:58
**/
public class HelloWorldService {
private String text;
public void setText(String text) {
this.text = text;
}
public void printHelloWorld(){
System.out.println("hello world "+text);
}
}
8·测试类BeanFactoryTest:
package us.codecraft.tinyioc; /**
* Created by 贾丽敏 on 2017/5/29.
*/
import org.junit.Test;
import us.codecraft.tinyioc.factory.AutowireCapableBeanFactory;
import us.codecraft.tinyioc.factory.BeanFactory;
/**
*
* @author
* @create 2017-05-29 10:59
**/
public class BeanFactoryTest {
@Test
public void test() throws Exception{
//1·初始化beanFactory
BeanFactory beanFactory = new AutowireCapableBeanFactory();
//2` bean定义
BeanDefinition beanDefinition= new BeanDefinition();
beanDefinition.setBeanClassName("us.codecraft.tinyioc.HelloWorldService");
//3` 属性设置
PropertyValues pvs =new PropertyValues();
pvs.addPropertyValue(new PropertyValue("text","jimmy"));
beanDefinition.setPropertyValues(pvs);
//4 注册bean
beanFactory.registerBeanDefinition("helloWorldService",beanDefinition);
//3·获取bean
HelloWorldService helloWorldService=(HelloWorldService)beanFactory.getBean("helloWorldService");
helloWorldService.printHelloWorld();
}
}
最终执行效果:
为bean注入属性到此基本结束,下面是针对于属性注入的代码简单分析:
与step2中不同的地方就是在HelloWorldService的bean对象中加入属性,然后通过Field形式来注入。具体代码体现在:AutowireCapableBeanFactory类。在step2中,该类的工作就是根据动态加载的类完成了bean对象的实例化工作;在step3中,该类不仅仅是bean对象的实例化工作,同时也加入的bean对象的属性注入,通过方法Class类的getDeclaredField(Stringname)方法,该方法是获取该Class中属性为name的Field类对象,然后通过Field.set(Object bean,Object Value)方法,为该属性赋值,这就完成了bean类中属性的注入过程。