在版本一中,实现了简单的BeanFactory,这是一个接口,一个是获取bean,一个是注册bean。

BeanFactory利用SimpleBeanFactory实现,可以基于xml对Bean进行管理。

而由于BeanFactory在Spring中不提供给开发人员使用,又实现了ClassPathXmlApplicationContext,通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象 。

具体流程图 :

这里进行单例bean的构建。

构建单例bean

为了和 Spring 框架内的方法名保持一致,我们把 BeanFactory 接口中定义的 registryBeanDefinition 方法修改为 registryBean,参数修改为 beanName 与 obj。其中,obj 为 Object 类,指代与 beanName 对应的 Bean 的信息。

1
2
3
4
5
6
7
public interface BeanFactory {
//删
//void registerBeanDefinition(BeanDefinition beanDefinition);
//增
Boolean containsBean(String name);
void registerBean(String beanName, Object obj);
}

另外再定义接口SingletonBeanRegistry,这里起到的作用是规范管理单例bean的方法。把这个接口放在beans目录下。

1
2
3
4
5
6
7
8
9
10
public interface SingletonBeanRegistry {
//注册单例bean
void registerSingleton(String beanName, Object singletonObject);
//获取
Object getSingleton(String beanName);
//检测是否存在
boolean containsSingleton(String beanName);
//查询所有单例bean
String[] getSingletonNames();
}

使用DefaultSingletonBeanRegistry类实现该接口,放在beans目录下 :

注意这里如何实现单例Bean :

原来 :

1
2
3
4
5
6
//在 SimpleBeanFactory 中实现
private List<BeanDefinition> beanDefinitions = new ArrayList<>();
public void registerBeanDefinition(BeanDefinition beanDefinition) {
this.beanDefinitions.add(beanDefinition);
this.beanNames.add(beanDefinition.getId());
}

现在:

1
2
3
4
5
6
7
8
9
//定义了一个专门的管理单例bean接口SingletonBeanRegistry,里面包含registerSingleton函数,让SimpleBeanFactory去继承这个接口的实现类
protected Map<String, Object> singletons = new ConcurrentHashMap<>(256);
public void registerSingleton(String beanName, Object singletonObject) {
//关键字 synchronized,保证多线程下正常
synchronized (this.singletons) {
this.singletons.put(beanName, singletonObject);
this.beanNames.add(beanName);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
//容器中存放所有bean的名称的列表
protected List<String> beanNames = new ArrayList<>();
//容器中存放所有bean实例的map,ConcurrentHashMap线程安全
protected Map<String, Object> singletons = new ConcurrentHashMap<>(256);
public void registerSingleton(String beanName, Object singletonObject) {
//关键字 synchronized,保证多线程下正常
synchronized (this.singletons) {
this.singletons.put(beanName, singletonObject);
this.beanNames.add(beanName);
}
}
public Object getSingleton(String beanName) {
return this.singletons.get(beanName);
}
public boolean containsSingleton(String beanName) {
return this.singletons.containsKey(beanName);
}
public String[] getSingletonNames() {
return (String[]) this.beanNames.toArray();
}
protected void removeSingleton(String beanName) {
synchronized (this.singletons) {
this.beanNames.remove(beanName);
this.singletons.remove(beanName);
}
}
}

修改上一版代码

在上一版中,SimpleBeanFactory实现了BeanFactory。现在让SimpleBeanFactory在实现BeanFactory同时继承DefaultSingletonBeanRegistry ,这样它就一定会创建单例bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 一个简单的bean工厂实现类,同样有注册和get两个功能
*主要有三个实例域 :
* 1.beanDefinitions,是一个泛型列表,存了所有的bean的定义
* 2.beanNames,是一个字符串列表,存了所有bean的名字
* 3.singletons,哈希表,key为bean的名字,value为bean实例
* */
public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory{
private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>(256);
//beanName和singletons在父级定义了,这里就删掉了

public SimpleBeanFactory() {
}

//getBean,容器的核心方法
public Object getBean(String beanName) throws BeansException {
//先尝试直接拿bean实例
Object singleton = this.getSingleton(beanName);
//如果此时还没有这个bean的实例,则获取它的定义来创建实例
if (singleton == null) {
//获取bean的定义
BeanDefinition beanDefinition = beanDefinitions.get(beanName);
if (beanDefinition == null) {
throw new BeansException("No bean.");
} try {
singleton = Class.forName(beanDefinition.getClassName()).newInstance();
}
//新注册这个bean实例,通过单例的方法 ()
this.registerSingleton(beanName, singleton);
}
return singleton;
}
//接口新增方法,注册 ,前面Beanfactory接口中改了新名字
public void registerBean(String beanName, Object obj) {
this.registerSingleton(beanName, obj);
}
//接口新增方法,检查是否存在bean
public Boolean containsBean(String name) {
return containsSingleton(name);
}
/**
* 注册,遗留方法
* */
public void registerBeanDefinition(BeanDefinition beanDefinition) {
this.beanDefinitions.put(beanDefinition.getId(), beanDefinition);
}
}

注意,ClassPathXmlApplicationContext 也是BeanFactory的实现,需要新增方法 :

1
2
3
4
5
6
public Boolean containsBean(String name) {
return this.beanFactory.containsBean(name);
}
public void registerBean(String beanName, Object obj) {
this.beanFactory.registerBean(beanName, obj);
}

注意,此时BeanFactorry中已经没有registerBeanDefinition,因此XmlBeanDefinitionReader 需要将实例域改成 SimpleBeanFactory,这样还能通过registerBeanDefinition注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class XmlBeanDefinitionReader {
//原来实例域是BeanFactory,现在改成SimpleBeanFactory
SimpleBeanFactory simpleBeanFactory;

public XmlBeanDefinitionReader(SimpleBeanFactory simpleBeanFactory) {
this.simpleBeanFactory = simpleBeanFactory;
}

public void loadBeanDefinitions(Resource resource) {
while (resource.hasNext()) {
Element element = (Element) resource.next();
String beanID = element.attributeValue("id");
String beanClassName = element.attributeValue("class");
BeanDefinition beanDefinition = new BeanDefinition(beanID, beanClassName);
this.simpleBeanFactory.registerBeanDefinition(beanDefinition);
}
}
}

小结