0


Spring的IOC容器分析

文章目录

Spring的IOC从入门到深入

1.分析下面代码开发中存在的问题:

在这里插入图片描述

2. 针对上述代码存在的问题,我们该解决,

解决方案是: 将测试类与接口的耦合,通过第三方容器来解决
实现步骤分为两步:

第一步: 将耦合类配置到xml文件中, 比如: beans.xml

<?xml version="1.0" encoding="utf-8" ?><!--上面是:文档声明是xml文档--><!--XML有且仅有一个根标签: objs,由于是自定义的xml,标签可以任意定义--><objs><!--子标签: obj
       id: 唯一标识,一般建议使用类名,首字母小写
       class:类的全路径
    --><objid="dog"class="com.tedu.service.impl.Dog"/><objid="cat"class="com.tedu.service.impl.Cat"/></objs>

第二步: 创建容器对象,加载配置文件,创建对象存储到容器中

/**
 * 模拟Spring核心对象:
 * 1.通过解析xml文件,读取到class属性的值
 * 2.利用反射Class.newInstance()创建对象
 * 3.把创建的对象存到map里面(map就是spring容器)
 *  map容器存对象有两种方式:
 *  方式一: map中的key: 类名称(首字母小写), map的value: 类对象
 *  方式二: map中的key: 类的class对象, map的value: 类对象
 */publicclassMyApplicationContext{//1.引入被加载的xml文件privateString resourcesXml;//2.创建容器对象, 就是map, 底层是线程安全的mapprivatestaticMap<Object,Object> map =newConcurrentHashMap<Object,Object>();//3.通过构造方法给引入的xml文件赋值publicMyApplicationContext(String xmlPath){this.resourcesXml = xmlPath;//解析配置文件,创建对象,存到map容器中try{//5.解析配置文件的代码: dom4j技术解析xml,SAXReader saxReader =newSAXReader();//核心解析器对象//6.类加载器获取配置文件字节输入流InputStream in =MyApplicationContext.class.getClassLoader().getResourceAsStream(resourcesXml);//7.读取配置文件字节输入流,获取xml的文档对象Document document = saxReader.read(in);//8.根据document获取所有的obj标签对象List<Node> list = document.selectNodes("//obj");//9.遍历list集合,获取list集合里面的每一个obj标签for(Node node : list){//10. 把node节点转换为 element标签Element element =(Element)node;//11. 根据element标签对象:获取id属性值,获取class属性值String idValue   = element.attributeValue("id");//比如:idValue = dogString classPath = element.attributeValue("class");//比如:classPath = 包名.Dog//12.利用反射创建对象Class aClass =Class.forName(classPath);//得到类的字节码对象, 比如: Dog.classObject obj = aClass.newInstance();//反射: 默认使用无参数的构造方法创建对象//13.把创建好的对象存到容器中//13.1比如: 根据 dog名称-- new Dog()对象
                map.put(idValue,obj);//13.2比如: 根据 Dog.class-- new Dog()对象
                map.put(aClass,obj);}}catch(Exception e){
            e.printStackTrace();}}//4.提供一个根据名称: 也就是根据id的属性值获取 bean对象的方法//直接从map容器中获取对象publicstaticObjectgetBean(String idValue){return  map.get(idValue);}//5.提供一个根据名称: 也就是根据Class字节码对象获取 bean对象的方法//定义泛型的优点: 避免类型强转//直接从map容器中获取对象publicstatic<T>TgetBean(Class<T> clz){return(T)map.get(clz);}}

第3步: 测试

publicclassDemo{publicstaticvoidmain(String[] args){//1.创建核心对象://核心对象使用类加载器加载配置文件,// 类加载器文件在resources根目录下面,所以和beans.xml同一级目录(相对路径写法)MyApplicationContext map =newMyApplicationContext("beans.xml");//2.根据id属性值: 获取bean对象,这个方法没有使用泛型,需要强转//解耦合: 看不到Demo类与 Pet接口,或者Dog实现类有耦合关系Pet pet =(Pet)map.getBean("dog");//3.根据class值: 获取bean对象,这个方法使用了泛型,不用强转Pet pet2 = map.getBean(Dog.class);
        pet.hello();
        pet2.hello();}}

4. 总结

在这里插入图片描述

5. 下面我们看下spring框架的IOC是如何实现的

第一步: 在创建的maven项目中,导入spring-webmvc依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.16.RELEASE</version></dependency>

依赖解释:
在这里插入图片描述

第二步: 创建spring配置文件

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><!--
    为什么写bean标签,不能写其它?
    因为上述头中spring-beans.xsd: 这个是约束文件,规定了标签的名称以及属性的书写
    id: 唯一标识
    scope: 作用范围, 比如: 创建单例对象(只创建一个对象)
    lazy-init: 是否立即创建对象,比如: false 懒加载,什么时候调用方法,什么时候创建对象
    --><beanid="dog"scope="singleton"lazy-init="false"class="com.tedu.service.impl.Dog"/><beanid="cat"class="com.tedu.service.impl.Cat"/></beans>

第三步: 使用spring核心对象,获取容器中的bean对象

publicclassDemo2{publicstaticvoidmain(String[] args){//1.创建容器对象//在这里: 为什么直接写文件名称, 因为底层是类加载器加载spring配置文件的//类加载器在resources根目录下面: 和spring.xml同一级目录ApplicationContext map =newClassPathXmlApplicationContext("spring.xml");//2.根据类的名称获取对象: 这个方法没有使用泛型,必须强转Pet pet =(Pet)map.getBean("dog");//3.根据Class获取对象: 这个方法使用泛型,不用强转Pet pet2 = map.getBean(Dog.class);}}

6. 对比spring框架的核心 与自定义的容器

通过下图我们能分析到一下三点:

  1. Spring框架底层是通过类加载器加载spring的配置文件的,类加载器的位置在resources的根目录下面 所以和配置文件同一级目录,直接写目录名称
  2. Spring框架的容器底层就是一个map集合
  3. Spring容器在存储对象有两种方式 第一: 根据类名,存储该类的对象 第二:根据类的class字节码,存储该类的对象在这里插入图片描述

7. Spring的注解开发

核心思路:

  1. 通过注解替代配置文件, Spring框架中配置自动扫描包机制,根据扫描的类,创建对象,存到容器中.
  2. Spring容器通过注解开发时,在存储对象依然是下面的两种方式 第一: 根据类名,存储该类的对象 第二:根据类的class字节码,存储该类的对象
  3. Spring的DI依赖注入: 其实就是给当前类的成员变量(成员属性)赋值 常见DI注入方式有两种: - 通过构造方法DI依赖注入 *比如:在这里插入图片描述- 通过set方法DI依赖注入- 比如:在这里插入图片描述

8. Spring整合junit进行单元测试

标签: spring 容器 java

本文转载自: https://blog.csdn.net/caozhisanguo/article/details/122621832
版权归原作者 小码哥的进阶 所有, 如有侵权,请联系我们删除。

“Spring的IOC容器分析”的评论:

还没有评论