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

简介: 这是学习刘老师的《从零开始造Spring》的第一篇学习笔记。

前言


这是学习刘老师的《从零开始造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));
    }


解析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();
                }
            }
        }
    }


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

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


生成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);
        }   
    }


其中,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月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。
|
8月前
|
监控 Java 应用服务中间件
微服务——SpringBoot使用归纳——为什么学习Spring Boot
本文主要探讨为什么学习Spring Boot。从Spring官方定位来看,Spring Boot旨在快速启动和运行项目,简化配置与编码。其优点包括:1) 良好的基因,继承了Spring框架的优点;2) 简化编码,通过starter依赖减少手动配置;3) 简化配置,采用Java Config方式替代繁琐的XML配置;4) 简化部署,内嵌Tomcat支持一键式启动;5) 简化监控,提供运行期性能参数获取功能。此外,从未来发展趋势看,微服务架构逐渐成为主流,而Spring Boot作为官方推荐技术,与Spring Cloud配合使用,将成为未来发展的重要方向。
306 0
微服务——SpringBoot使用归纳——为什么学习Spring Boot
|
5月前
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
690 2
|
7月前
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
186 20
|
Java Maven Spring
springboot学习一:idea社区版本创建springboot项目的三种方式(第三种为主)
这篇文章介绍了在IntelliJ IDEA社区版中创建Spring Boot项目的三种方法,特别强调了第三种方法的详细步骤。
10706 0
springboot学习一:idea社区版本创建springboot项目的三种方式(第三种为主)
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
277 9
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
832 2
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
839 1
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
177 9
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
115 1