前面通过定义一个单例接口的实现类,并让classpathxmlApplication继承这个类,从而实现了单例bean,具体如图 :

下面要干两件事 :

  1. 增加事件监听。虽然这里没有用到,但是预留了事件监听的接口,方便后续进一步解耦代码逻辑。
  2. 扩展 BeanDefinition。扩展 BeanDefinition,添加一些属性,现在它只有 id 和 class 两个属性,我们要进一步地丰富它。
  3. 给BeanFactory 新增接口。这里新增的接口对应步骤2中新增的属性。

增加事件监听

为了监控容器的启动状态,我们要增加事件监听。事件监听使用ApplicationEvent,事件发布使用ApplicationEventPublisher。这两个都写在context目录下。

  • ApplicationEvent:定义一个事件监听类,继承Java事件模型 EventObject,在 Java 的事件监听的基础上进行了简单的封装。虽然目前还没有任何实现,但这为我们后续使用观察者模式解耦代码提供了入口。

    1
    2
    3
    4
    5
    6
    7
    public class ApplicationEvent  extends EventObject {
    private static final long serialVersionUID = 1L;
    //构造器使用父类的。
    public ApplicationEvent(Object arg0) {
    super(arg0);
    }
    }
  • ApplicationEventPublisher : 定义一个接口,里面包含发布事件publishEvent()这个方法。

    1
    2
    3
    public interface ApplicationEventPublisher {
    void publishEvent(ApplicationEvent event);
    }

拓展BeanDefinition

扩展 BeanDefinition 的属性,在原有 id 与 name 两个属性的基础上,新增 lazyInit、dependsOn、initMethodName 等属性。

1
2
3
4
5
6
7
 String SCOPE_SINGLETON = "singleton"; //单例
String SCOPE_PROTOTYPE = "prototype"; //原型
private String scope = SCOPE_SINGLETON;
private boolean lazyInit = false; //表示 Bean 要不要在加载的时候初始化
private String[] dependsOn; //记录 Bean 之间的依赖关系
private String initMethodName; //初始化方法的声明

拓展BeanFactory 接口 :

增强对 Bean 的处理能力,根据上面 BeanDefinition 的定义来,新增以下方法 :

1
2
3
boolean isSingleton(String name); //新增 Singleton 的判断 
boolean isPrototype(String name); //新增 Prototype 的判断
Class<?> getType(String name); //获取 Bean 的类型

而BeanFactory 接口被SimpleBeanFactory和ClassPathXmlApplicationContext两个类实现,因此这两个类也需要新增以上相应的方法。

在对SimpleBeanFactory和ClassPathXmlApplicationContext两个类新增实现之前 ,先再考虑这样一件事 :

现在的Bean都是通过XmlBeanDefinitionReader读取后,转化成相应的BeanDefinition去SimpleBeanFactory中注册,并没有一个地方能统一的管理BeanDefinition。

因此新增 BeanDefinitionRegistry 接口。它类似于一个存放 BeanDefinition 的仓库,可以存放、移除、获取及判断 BeanDefinition 对象。

1
2
3
4
5
6
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String name, BeanDefinition bd);
void removeBeanDefinition(String name);
BeanDefinition getBeanDefinition(String name);
boolean containsBeanDefinition(String name);
}

上面们初步定义四个接口对应存放、移除、获取及判断 BeanDefinition 对象这四个功能,分别是 register、remove、get、contains。这里的管理的是bean的定义,而不是备案。所以BeanFactory 接口中注册的功能仍然要保留。

到此,SimpleBeanFactory 首先就要新增BeanFactory 接口中新增的方法。然后再让它实现BeanDefinitionRegistry接口,这样这个SimpleBeanFactory类就对 BeanDefinition有了增删改查的功能。

现在SimpleBeanFactory 既是一个工厂同时也是一个仓库

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
public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry{
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private List<String> beanDefinitionNames = new ArrayList<>();

public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
this.beanDefinitionMap.put(name, beanDefinition);
this.beanDefinitionNames.add(name);
if (!beanDefinition.isLazyInit()) {
try {
getBean(name);
} catch (BeansException e) {
}
}
}
public void removeBeanDefinition(String name) {
this.beanDefinitionMap.remove(name);
this.beanDefinitionNames.remove(name);
this.removeSingleton(name);
}
public BeanDefinition getBeanDefinition(String name) {
return this.beanDefinitionMap.get(name);
}
public boolean containsBeanDefinition(String name) {
return this.beanDefinitionMap.containsKey(name);
}
public boolean isSingleton(String name) {
return this.beanDefinitionMap.get(name).isSingleton();
}
public boolean isPrototype(String name) {
return this.beanDefinitionMap.get(name).isPrototype();
}
public Class<?> getType(String name) {
return this.beanDefinitionMap.get(name).getClass();
}
}

ClassPathXmlApplicationContex类也实现了BeanFactory、以及事件发布接口,因此需要增加一些方法 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ClassPathXmlApplicationContext implements BeanFactory, ApplicationEventPublisher
{
public void publishEvent(ApplicationEvent event) {
}
public boolean isSingleton(String name) {
return false;
}
public boolean isPrototype(String name) {
return false;
}
public Class<?> getType(String name) {
return null;
}
}

小结