Java 杂谈

自己写一个Spring框架: 02 给容器分层次

2018-08-21  本文已影响1人  zhang5788

在上一篇中,我们简单实现了一个基本的IOC容器,只能完成简单的存,取对象,在使用的时候还得自己实例化之后,把对象给放进去,问题实在是太多了,我们一个一个解决

容器管理实例化

为了使框架能够使用,我们需要将类的实例化过程交给容器来进行管理,要不然使用容器的意义就没有了,也没办法做到解耦.
为了实现这个目的,我们需要将上一篇中的类BeanFactory扩展一下.
我们额外定义一个类BeanDefinition来对Bean进行封装,来存储一些Bean必须的属性.

BeanDefinition的代码如下:

public class BeanDefinition {
    
    private Object bean;

    public Object getBean() {
        return bean;
    }

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

由于现在还没有需要保存的额外信息,我们先定义出来.

然后,BeanFactory就不直接管理Bean对象了,而是管理Bean的装饰类BeanDefinition.
代码如下:

public class BeanFactory {
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    
    public Object getBean(String beanName) {
        return beanDefinitionMap.get(beanName).getBean();
    }
    
    public void setBean(String beanName, Object bean) {
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBean(bean);
        beanDefinitionMap.put(beanName, beanDefinition);
    }
}

这样,我们为了将对象的实例化交给容器管理的准备工作就完成了.

对象的实例化

使用容器对对象进行实例化,我们就需要使用反射来生成每一个类的具体对象.在BeanDefinition中,我们就需要增加一些必须的字段

@SuppressWarnings("rawtypes")
public class BeanDefinition {
    
    private Object bean;
    
    private Class beanClass;
    
    private String beanClassName;
    
    public BeanDefinition() {
    }

    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 {
            this.beanClass = Class.forName(beanClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

这样,在BeanDefinition中,通过增加beanClassName字段,我们就可以在容器中初始化,实例化对象了.

BeanFactory修改后如下:

public class BeanFactory {
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    
    public Object getBean(String beanName) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        String beanClassName = beanDefinitionMap.get(beanName)
                .getBeanClassName();
        return Class.forName(beanClassName).newInstance();
    }
    
    public void setBean(String beanName, String beanClassName) {
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanClassName(beanClassName);
        beanDefinitionMap.put(beanName, beanDefinition);
    }
}

这样,一个简单的容器就构建完了.
我们写个测试类来测试一下这个容器

class BeanFactoryTest {

    @Test
    void test() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        BeanFactory bc = new BeanFactory();
        bc.setBean("hello", "com.zhangt.test.HelloWorldService");
        
        HelloWorldService hwService = (HelloWorldService)bc.getBean("hello");
        hwService.show();
        
    }

}

输出为
this is a simple test for IOC form

说明容器是可以使用的.
这一章我们完善了之前的简单容器,使其成为一个可用的,具有解耦功能的框架,但是这个框架中还是缺少很多功能,例如,我们没有办法将对象的字段属性给注入进去,我们将在下一章来解决这个问题

上一篇 下一篇

猜你喜欢

热点阅读