《step2:tiny Spring IoC学习二》——将bean创建放入工厂

来源:互联网 发布:cnzz数据专家 编辑:程序博客网 时间:2024/06/05 14:21

在上一篇博客《step1:tiny Spring Ioc 学习一最基本的容器BeanFactory》中,bean(HelloWorldService)是通过new初始化好之后再set进去BeanDefinition对象中的,实际使用中,我们希望容器来管理bean的创建。于是我们将bean的初始化工作放入BeanFactory中。为了保证扩展性,我们使用ExtractInterface的方法,将BeanFactory替换成接口,而使用AbstractBeanFactoryAutowireCapableBeanFactory作为其实现。"AutowireCapable"的意思是“可自动装配的”,在这里的作用是根据jvm已记载的类进行实例化。(为我们后面注入属性做准备)。

    同样,demo的类图:


     时序图:


    根据类图和时序图,我们来看代码的实现:

     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);}
      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) {        Object bean = doCreateBean(beanDefinition);        beanDefinition.setBean(bean);        beanDefinitionMap.put(name,beanDefinition);    }    //初始化bean    protected abstract Object doCreateBean(BeanDefinition beanDefinition);}
       3·AutowireCapableBeanFactory子类:

package us.codecraft.tinyioc.factory;/** * Created by 贾丽敏 on 2017/5/29. */import us.codecraft.tinyioc.BeanDefinition;/*** 自动初始化bean* @author * @create 2017-05-29 15:23**/public class AutowireCapableBeanFactory extends AbstractBeanFactory {    @Override    protected Object doCreateBean(BeanDefinition beanDefinition) {        try {            Object bean = beanDefinition.getBeanClass().newInstance();            return bean;        }catch (InstantiationException e){            e.printStackTrace();        }catch (IllegalAccessException e){            e.printStackTrace();        }        return null;    }}

    4·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;    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·Bean对象:HelloWorldService类

package us.codecraft.tinyioc;/** * Created by 贾丽敏 on 2017/5/29. *//*** * @author * @create 2017-05-29 10:58**/public class HelloWorldService {    public void printHelloWorld(){        System.out.println("hello world");    }}

     6·测试类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(){        //1·初始化beanFactory        BeanFactory beanFactory = new AutowireCapableBeanFactory();        //2·注入bean        BeanDefinition beanDefinition= new BeanDefinition();        beanDefinition.setBeanClassName("us.codecraft.tinyioc.HelloWorldService");        beanFactory.registerBeanDefinition("helloWorldService",beanDefinition);        //3·获取bean        HelloWorldService helloWorldService=(HelloWorldService)beanFactory.getBean("helloWorldService");        helloWorldService.printHelloWorld();    }}

     整体代码就是这些,下边是执行结果:



                   第二步的内容就是这些,下边我们来分析一下这个代码实现的过程和上一篇博客的区别点:

上边已经分析过是“初始化”的工作由谁来做?怎么做?

    与step1主要不同的地方就是“初始化”的工作由谁来做?

很明显,step1,是在main方法中通过new实例化bean对象再放到beanDefinition对象中管理。step2是怎么做的呢?

step2中想要达到的效果就是:动态加载bean对象,具体详解前先来思考下边的一个问题:

 

    ·给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?


     你首先想到的是不是new实例化?看下边代码:

A a=(A)Class.forName("package.A").newInstance();//拆开来看Class t=Class.forName("package.A");t.newInstance();

    这句代码和A a = new A();是一样的效果。既然一样的效果,那区别是什么?换句话说,我应该选择哪种方式呢?

    从代码中可以看出,newInstance()实际上是把new方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。

    step2的代码中就是通过Class.forName("包名.类名")来动态加载的类,然后在自动加载类AutowireCapableBean中该类的newInstance()创建的bean对象。这样的好处是:我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。



阅读全文
0 0
原创粉丝点击