在上一篇博客《step1:tiny Spring Ioc 学习一最基本的容器BeanFactory》中,bean(HelloWorldService)是通过new初始化好之后再set进去BeanDefinition对象中的,实际使用中,我们希望容器来管理bean的创建。于是我们将bean的初始化工作放入BeanFactory中去。为了保证扩展性,我们使用ExtractInterface的方法,将BeanFactory替换成接口,而使用AbstractBeanFactory和AutowireCapableBeanFactory作为其实现。"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时获得更好的灵活性,提供给了一种降耦的手段。