美文网首页Java 杂谈
自己写一个Spring框架: 02 给容器分层次

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

作者: zhang5788 | 来源:发表于2018-08-21 15:28 被阅读1次

    在上一篇中,我们简单实现了一个基本的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

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

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/tztjiftx.html