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

在上一篇博客《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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值