在版本一中,实现了简单的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 { 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 { void registerSingleton(String beanName, Object singletonObject); Object getSingleton(String beanName); boolean containsSingleton(String beanName); String[] getSingletonNames(); }
|
使用DefaultSingletonBeanRegistry类实现该接口,放在beans目录下 :
注意这里如何实现单例Bean :
原来 :
1 2 3 4 5 6
| 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
| protected Map<String, Object> singletons = new ConcurrentHashMap<>(256); public void registerSingleton(String beanName, Object singletonObject) { 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 { protected List<String> beanNames = new ArrayList<>(); protected Map<String, Object> singletons = new ConcurrentHashMap<>(256); public void registerSingleton(String beanName, Object singletonObject) { 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
|
public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory{ private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>(256);
public SimpleBeanFactory() { }
public Object getBean(String beanName) throws BeansException { Object singleton = this.getSingleton(beanName); if (singleton == null) { BeanDefinition beanDefinition = beanDefinitions.get(beanName); if (beanDefinition == null) { throw new BeansException("No bean."); } try { singleton = Class.forName(beanDefinition.getClassName()).newInstance(); } this.registerSingleton(beanName, singleton); } return singleton; } public void registerBean(String beanName, Object obj) { this.registerSingleton(beanName, obj); } 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 { 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); } } }
|
小结