SpringIOC容器Bean对象的实例化模拟

思路:
1. 定义 Bean ⼯⼚接⼝,提供获取 bean ⽅法
2. 定义 Bean ⼯⼚接⼝实现类,解析配置⽂件,实例化Bean对象
3. 实现获取 Bean ⽅法

1、定义 Bean 属性对象

package org.example.spring;

/**
 * Bean属性对象:用来封装Spring配置文件中bean标签的id和class属性值
 */
public class MyBean {
    private String id;  //存放bean标签的id值
    private String clazz;  //存放bean标签的class属性值

    public MyBean() {
    }

    public MyBean(String id, String clazz) {
        this.id = id;
        this.clazz = clazz;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

2、添加 dom4j和xpath依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>spring02</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring02</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- dom4j -->
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    
    <!-- XPath -->
    <dependency>
      <groupId>jaxen</groupId>
      <artifactId>jaxen</artifactId>
      <version>1.1.6</version>
    </dependency>
  </dependencies>
</project>

3、准备自定义的spring配置文件

<?xml version="1.0" encoding="utf-8" ?>
<beans>
    <bean id="userDao" class="org.example.service.UserDao"></bean>
    <bean id="userService" class="org.example.service.UserService"></bean>
</beans>

4、定义 Bean 工厂接口

package org.example.spring;

/**
 * Bean工厂接口的定义
 */
public interface MyFactory {
    //根据id属性值获取bean对象
    public Object getBean(String id);
}

5、定义 Bean 接口的实现类

package org.example.spring;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 模拟Spring的实现
 * 1.通过有参构造方法获得对应的配置文件
 * 2.使用dom4j解析配置文件(spring配置文件),得到一个List集合(这个List集合存放了一系列bean标签的id和class属性值)
 * 3.通过反射机制创建对应的实例化对象并存入到一个Map集合中(遍历List集合,通过获取对应的class属性值,利用反射机制实例化对象)
 * 4.根据id值获取bean对象
 */
public class MyClassPathXmlApplicationContext implements MyFactory{
    //存放从spring配置文件中获取到的bean标签的信息
    private List<MyBean> beanList;
    //使用Map集合存放实例化好的bean对象
    private Map<String,Object> beanMap = new HashMap<>();

    //1.通过有参构造方法获得对应的配置文件
    public MyClassPathXmlApplicationContext(String fileName) {
        //2.使用dom4j解析配置文件(spring配置文件),然后得到一个List集合(这个List集合存放了一系列bean标签的id和class属性值)
        this.parseXml(fileName);
        //3.通过反射机制创建对应的实例化对象并存入到一个Map集合中
        this.instanceBean();
    }

    /**
     * 通过反射机制创建对应的实例化对象并存入到一个Map集合中
     */
    private void instanceBean() {
        //1.判断对象集合是否为空,如果不为空则遍历集合,获取对应的id和class属性
        if (beanList != null && beanList.size()>0){
            for (MyBean bean:beanList){
                String id = bean.getId();
                String clazz = bean.getClazz();
                try {
                    //2.通过反射机制根据类的全路径名实例化对象
                    Object object = Class.forName(clazz).newInstance();
                    //3.将对应的id和实例化好的bean对象放入Map集合中
                    beanMap.put(id,object);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 使用dom4j解析spring配置文件,得到List集合
     * @param fileName
     */
    private void parseXml(String fileName) {
        //1.获取解析器
        SAXReader saxReader = new SAXReader();
        //2.获取配置文件的URL
        URL url = this.getClass().getClassLoader().getResource(fileName);
        try{
            //3.通过解析器解析spring配置文件
            Document document = saxReader.read(url);
            //4.通过xpath语法解析,获取beans标签下的所有bean标签
            XPath xPath = document.createXPath("beans/bean");
            //5.通过指定的解析语法解析文档对象,返回元素集合
            List<Element> elementList = xPath.selectNodes(document);
            //6.判断元素集合是否为空
            if (elementList != null && elementList.size()>0){
                //实例化List集合
                beanList = new ArrayList<>();
                //7.如果元素集合不为空,就遍历集合
                for (Element e:elementList){
                    //8.获取bean标签元素的属性(id和class属性值)
                    String id = e.attributeValue("id");
                    String clazz = e.attributeValue("class");
                    //9.获取MyBean对象,将id和class属性值设置到对象中,再将对象添加到List集合中
                    MyBean myBean = new MyBean(id,clazz);
                    beanList.add(myBean);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 通过id获取对应bean对象
     * @param id
     * @return
     */
    public Object getBean(String id) {
        Object object = beanMap.get(id);
        return object;
    }
}

6、测试自定义的IOC容器

先定义用于测试的两个类:

package org.example.dao;

public class UserDao {
    public void test(){
        System.out.println("UserDao Test...");
    }
}


package org.example.service;

public class UserService {
    public void test(){
        System.out.println("UserService Test...");
    }
}

编写测试程序: 

package org.example;

import org.example.dao.UserDao;
import org.example.service.UserService;
import org.example.spring.MyClassPathXmlApplicationContext;
import org.example.spring.MyFactory;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        //得到工厂的实现对象
        MyFactory factory = new MyClassPathXmlApplicationContext("spring.xml");
        //得到对应的实例化对象
        UserDao userDao = (UserDao)factory.getBean("userDao");
        userDao.test();

        UserService userService = (UserService)factory.getBean("userService");
        userService.test();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/567659.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

云架构(五)BBF模式

BFF模式&#xff08;Backends for Frontends pattern&#xff09;- https://learn.microsoft.com/en-us/azure/architecture/patterns/backends-for-frontends。 创建单独的后台服务用以提供给特定的前端或者接口。当你希望避免为多个接口定制单独的后台时&#xff0c;此模…

隋总分享:Temu选品师算不算是蓝海项目?

在当今日新月异的互联网经济浪潮中&#xff0c;跨境电商正成为一股不可忽视的力量。最近&#xff0c;网红隋总对Temu选品师这一职业进行了深入介绍&#xff0c;引发了广泛关注。那么&#xff0c;Temu选品师是否真的可以视为一个蓝海项目呢?本文将对此进行一番细致的探讨。 首先…

RBA认证是什么?RBA认证的流程是怎么样的

RBA认证&#xff0c;即“责任商业联盟”认证&#xff0c;英文全称是Responsible Business Alliance。这是一个为电子行业或以电子为主要组成部分的行业及其供应链制定的社会责任审核标准。该标准旨在确保工作环境的安全、工人受到尊重并富有尊严、商业营运合乎环保性质并遵守道…

DenseDiffusion:Dense Text-to-Image Generation with Attention Modulation

1 研究目的 该文献的研究目的主要是&#xff1a; 探讨一种更为广泛的调制方法&#xff0c;通过设计多个正则化项来优化图像合成过程中的空间控制。论文的大致思想是&#xff0c;在现有的基于数据驱动的图像合成系统基础上&#xff0c;通过引入更复杂的调制策略&#xff0c;实现…

2024.4.23

1.const 修饰 *p。 p所指向地址内的值不可变&#xff0c;p指向的地址可以改变 2.const 修饰 p。 p指向的地址不可变&#xff0c;p所指向的地址的值可变 3.const 修饰 p。 p指向的地址不可变&#xff0c;p所指向地址的值可变 4.const 修饰 *p 和p。p指向的地址和p所指向地址的…

[激光原理与应用-90]:光功率计基本原理

目录 一、光功率计原理 二、光功率计硬件电路 三、光功率计探头 四、接口信号 一、光功率计原理 光功率计是用来测量光功率的仪器&#xff0c;其原理基于光电效应和电信号的检测与处理。 下面是光功率计的基本原理&#xff1a; 光电效应&#xff1a; 光功率计使用光敏元件…

链表的分割

题目 现给定一链表的头指针 phead 以及值 x&#xff0c;需编写一段代码将所有小于 x 节点的排在其余节点之前&#xff0c;且不能改变原来的数据顺序&#xff0c;最后返回重新排列后的链表的头指针。 算法思想 将小于x的尾插在第一个链表 将大于等于x的尾插在第二个链表 最后…

1142 - SELECT command denied to user ···

MySql子账户操作数据库权限不够&#xff0c;提示错误 1142 - SELECT command denied to user database 1142 - ALTER command denied to user database 以下命令可以解决 GRANT SELEC your_database_name TO mysql_account%;

centos7上搭建mongodb数据库

1.添加MongoDB的YUM仓库&#xff1a; 打开终端&#xff0c;执行以下命令来添加MongoDB的YUM仓库&#xff1a; sudo vi /etc/yum.repos.d/mongodb-org-4.4.repo 在打开的文件中&#xff0c;输入以下内容&#xff1a; [mongodb-org-4.4] nameMongoDB Repository baseurlh…

【Mysql】用frm和ibd文件恢复mysql表数据

问题 总是遇到mysql服务意外断开之后导致mysql服务无法正常运行的情况&#xff0c;使用Navicat工具查看能够看到里面的库和表&#xff0c;但是无法获取数据记录&#xff0c;提示数据表不存在。 这里记录一下用frm文件和ibd文件手动恢复数据表的过程。 思路 1、frm文件&…

第一个Spring Boot程序

目录 一、Spring Boot介绍 二、创建Spring Boot项目 1、插件安装&#xff08;专业版不需要&#xff09; 2、创建SpringBoot项目 &#xff08;1&#xff09;这里如果插件下载失败&#xff0c;解决方案&#xff1a; &#xff08;2&#xff09;项目启动失败&#xff0c;解决…

Docker镜像与容器操作

一、Docker 镜像操作 1.1 搜索镜像 格式&#xff1a;docker search 关键字 docker search nginx 1.2 获取镜像nginx 格式&#xff1a;docker pull 仓库名称[:标签] 如果下载镜像时不指定标签&#xff0c;则默认会下载仓库中最新版本的镜像&#xff0c;即选择标签为 latest…

SwiftUI 5.0(iOS 17.0)触摸反馈“震荡波”与触发器模式趣谈

概览 要想创作出一款精彩绝伦的 App&#xff0c;绚丽的界面和灵动的动画并不是唯一吸引用户的要素。有时我们还希望让用户真切的感受到操作引发的触觉反馈&#xff0c;直击使用者的灵魂。 所幸的是新版 SwiftUI 原生提供了实现触觉震动反馈的机制。在介绍它之后我们还将进一步…

HBase的简单学习三

一 过滤器 1.1相关概念 1.过滤器可以根据列族、列、版本等更多的条件来对数据进行过滤&#xff0c; 基于 HBase 本身提供的三维有序&#xff08;行键&#xff0c;列&#xff0c;版本有序&#xff09;&#xff0c;这些过滤器可以高效地完成查询过滤的任务&#xff0c;带有过滤…

Redis中的缓存击穿、缓存穿透、缓存雪崩问题

1.什么是缓存击穿&#xff1f; 客户端恶意访问一个不存在的数据&#xff0c;从而造成穿透缓存&#xff0c;请求直接到达数据库&#xff0c;频繁的发送这一类的请求&#xff0c;直接查询数据库&#xff0c;数据库的压力变大。 1.1如何解决缓存击穿呢&#xff1f; 1&#xff0…

基于harris角点和RANSAC算法的图像拼接matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ....................................................................... I1_harris fu…

【MySQL]】数据库操作指南之数据库的基础操作

&#x1f331;博客主页&#xff1a;青竹雾色间 &#x1f331;系列专栏&#xff1a;MySQL探险日记 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ✨人生如寄&#xff0c;多忧何为 ✨ 文章目录 1. 创建数据库2.数据库的编码集与校验集2.1 编码集 (Character…

嵌入式Python基础1-2

嵌入式Python基础1-2 条件语句 if elif else 随机数random eval while循环 for循环 水仙花数 循环else list 列表常用方法 增删改查 加排序 append remove pop index() 升序sort(&#xff09;降序 sort(reverseTrue) 反转 reverse&#xff08;&#xff09;…

ESP32开发

1、简介 1.1 种类 WIFI模块在PC上做为客户端、服务器&#xff0c;在STM32上做服务器的通讯。在物联网应用开发有重要作用&#xff0c;种类居多&#xff0c;如下图 红色方框的esp8266-01s型号的无限wifi模块就是本章学习的主要对象。 1.2 特点 小巧的尺寸&#xff1a;ESP-01…

SpanBert学习

SpanBERT: Improving Pre-training by Representing and Predicting Spans 核心点 提出了更好的 Span Mask 方案&#xff0c;也再次展示了随机遮盖连续一段字要比随机遮盖掉分散字好&#xff1b;通过加入 Span Boundary Objective (SBO) 训练目标&#xff0c;增强了 BERT 的性…
最新文章