从零开始造Spring01---BeanFactory的学习

举报
码农飞哥 发表于 2021/05/29 12:07:28 2021/05/29
【摘要】 前言 这是学习刘老师的《从零开始造Spring》的第一篇学习笔记。 主要分为两大块 : 一、解析xml文件,初始化BeanDefinition, 二、生成Bean的实例对象 第一堂课比较简单,我们首先从测试用例出发 测试用例 @Test public void testGetBean() { // 解析xml文件 reader.loadBeanDefin...

前言

这是学习刘老师的《从零开始造Spring》的第一篇学习笔记。
主要分为两大块 :
一、解析xml文件,初始化BeanDefinition
二、生成Bean的实例对象
第一堂课比较简单,我们首先从测试用例出发

测试用例

 @Test public void testGetBean() { // 解析xml文件 reader.loadBeanDefinitions(new ClassPathResource("petstore-v1.xml")); // 获得BeanDefinition BeanDefinition bd = factory.getBeanDefinition("petStore"); assertTrue(bd.isSingleton()); assertFalse(bd.isPrototype()); assertEquals(BeanDefinition.SCOPE_DEFAULT,bd.getScope()); assertEquals("org.litespring.service.v1.PetStoreService",bd.getBeanClassName()); PetStoreService petStore = (PetStoreService)factory.getBean("petStore"); assertNotNull(petStore); PetStoreService petStore1 = (PetStoreService)factory.getBean("petStore"); assertTrue(petStore.equals(petStore1)); }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

解析xml 文件

我们是通过XmlBeanDefinitionReader 来解析xml 文件的。采用dom4j的方式解析。核心代码如下:

public void loadBeanDefinitions(Resource resource){ InputStream is = null; try{ is = resource.getInputStream(); SAXReader reader = new SAXReader(); Document doc = reader.read(is); Element root = doc.getRootElement(); //<beans> Iterator<Element> iter = root.elementIterator(); while(iter.hasNext()){ Element ele = (Element)iter.next(); String id = ele.attributeValue(ID_ATTRIBUTE); String beanClassName = ele.attributeValue(CLASS_ATTRIBUTE); BeanDefinition bd = new GenericBeanDefinition(id,beanClassName); if (ele.attribute(SCOPE_ATTRIBUTE)!=null) { bd.setScope(ele.attributeValue(SCOPE_ATTRIBUTE)); } this.registry.registerBeanDefinition(id, bd); } } catch (Exception e) { throw new BeanDefinitionStoreException("IOException parsing XML document from " + resource.getDescription(),e); }finally{ if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } }

  
 
  • 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

注意: Resource类主要是用来获取xml 的文件流,它有两个实现类这里写ClassPathResource 以及FileSystemResource ,第一个实现类主要是获取类路径下的文件,也就是说该xml文件在项目中。第二个实现类主要是用于获取指定路径下的文件。该文件可能不在项目中。

public interface Resource { public InputStream getInputStream() throws IOException; public String getDescription();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

生成Bean的实例

首先,传入getBean方法传入beanID,在该方法中 首先拿到BeanDefinition,然后,根据beanClassName 字段通过反射的方式生成对应的bean 实例。
核心代码如下:

 public Object getBean(String beanID) { BeanDefinition bd = this.getBeanDefinition(beanID); if(bd == null){ return null; } //bd是单例 if(bd.isSingleton()){ Object bean = this.getSingleton(beanID); if(bean == null){ bean = createBean(bd); this.registerSingleton(beanID, bean); } return bean; } return createBean(bd); } private Object createBean(BeanDefinition bd) { ClassLoader cl = this.getBeanClassLoader(); String beanClassName = bd.getBeanClassName(); try { Class<?> clz = cl.loadClass(beanClassName); return clz.newInstance(); } catch (Exception e) { throw new BeanCreationException("create bean for "+ beanClassName +" failed",e); } }
  
 
  • 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

其中,DefaultSingletonBeanRegistry 类中定义了一个ConcurrentHashMap,将生成bean实例放在该Map中,在调用registerSingleton方法时,首先会根据beanName检查是否已存在实例,如果存在在抛出异常。否则,将新生成的实例放入该Map中。

 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64); public void registerSingleton(String beanName, Object singletonObject) { Assert.notNull(beanName, "'beanName' must not be null"); Object oldObject = this.singletonObjects.get(beanName); if (oldObject != null) { throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); } this.singletonObjects.put(beanName, singletonObject); } public Object getSingleton(String beanName) { return this.singletonObjects.get(beanName); }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

源代码:刘老师的源码地址

文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。

原文链接:feige.blog.csdn.net/article/details/80959439

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。