手写XML版Spring容器
文章目录
- 目标:
- 实现:
- 思路:
- 一、具体开发流程
- 1、加入依赖
- 2、定义User实体类
- 3、定义spring.xml
- 4、定义容器类
- 5、测试
- 总结
- 流程图
目标:
类似原生的Spring
框架,在spring.xml
中定义bean
信息,通过自定义ChenClassPathXmlApplicationContext
解析xml
文件,将bean
对象实例化。
实现:
思路:
自定义ChenClassPathXmlApplicationContext
,完成解析XML
文件并将bean
对象实例化的功能。大致步骤如下:
- 首先读取配置文件,获取根节点信息。
- 其次使用
beanId
查找对应的class
地址。 - 最后使用反射机制实例化该
bean
对象。
一、具体开发流程
实现通过ChenClassPathXmlApplicationContext
获取自定义User
类。
1、加入依赖
本项目需要解析XML
文件,所以需要dom4j
等jar包。源码如下:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"><parent><artifactId>handwritingproject</artifactId><groupId>com.njust</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>springanno</artifactId><dependencies><!-- https://mvnrepository.com/artifact/dom4j/dom4j --><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!-- https://mvnrepository.com/artifact/commons-lang/commons-lang --><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency></dependencies>
</project>
2、定义User实体类
定义User
类。只有简单的id
和userName
属性。tostring()
方法可以不要,但是为了便于测试,此处将其加入源码中。源码如下:
User .java
package com.njust.spring.entity;public class User {private Integer id = 1;private String userName = "userName";public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}@Overridepublic String toString() {return "User{" +"id=" + id +", userName='" + userName + '\'' +'}';}
}
3、定义spring.xml
spring.xml
中主要定义一个user
对象,和spring
语法一致。源码如下:
spring.xml
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><bean id="user" class="com.njust.spring.entity.User"></bean></beans>
4、定义容器类
定义ChenClassPathXmlApplicationContext
类,对外暴露的主要就是getBean()
方法,具体操作流程如下:首先读取配置文件,获取根节点信息,其次使用beanId
查找对应的class
地址。最后使用反射机制实例化该bean
对象。源码如下:
ChenClassPathXmlApplicationContext .java
package com.njust.spring;import java.io.InputStream;
import java.util.List;import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;/*** 手写Spring专题 XML方式注入bean*/
public class ChenClassPathXmlApplicationContext {// xml路径地址private String xmlPath;public ChenClassPathXmlApplicationContext(String xmlPath) {this.xmlPath = xmlPath;}public Object getBean(String beanId) throws Exception {// 1. 读取配置文件List<Element> elements = readerXml();if (elements == null) {throw new Exception("该配置文件没有子元素");}// 2. 使用beanId查找对应的class地址String beanClass = findXmlByIDClass(elements, beanId);if (StringUtils.isEmpty(beanClass)) {throw new Exception("未找到对应的class地址");}// 3. 使用反射机制初始化,对象Class<?> forName = Class.forName(beanClass);return forName.newInstance();}// 读取配置文件信息public List<Element> readerXml() throws DocumentException {SAXReader saxReader = new SAXReader();if (StringUtils.isEmpty(xmlPath)) {new Exception("xml路径为空...");}Document read = saxReader.read(getClassXmlInputStream(xmlPath));// 获取根节点信息Element rootElement = read.getRootElement();// 获取子节点List<Element> elements = rootElement.elements();if (elements == null || elements.isEmpty()) {return null;}return elements;}// 使用beanid查找该Class地址public String findXmlByIDClass(List<Element> elements, String beanId) throws Exception {for (Element element : elements) {// 读取节点上是否有valueString beanIdValue = element.attributeValue("id");if (beanIdValue == null) {throw new Exception("使用该beanId为查找到元素");}if (!beanIdValue.equals(beanId)) {continue;}// 获取Class地址属性String classPath = element.attributeValue("class");if (!StringUtils.isEmpty(classPath)) {return classPath;}}return null;}// 读取xml配置文件public InputStream getClassXmlInputStream(String xmlPath) {InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(xmlPath);return resourceAsStream;}}
5、测试
定义Test002
类,价值spring.xml
配置文件,通过getbean()
方法获取实例化对象并输出到控制台。源码如下:
Test002.java
package com.njust.spring;import com.njust.spring.entity.User;public class Test002 {public static void main(String[] args) throws Exception {ChenClassPathXmlApplicationContext applicationContext = new ChenClassPathXmlApplicationContext("spring.xml");User user = (User) applicationContext.getBean("user");System.out.println(user);}}
通过控制台输出,我们发现程序成功的输出user
基本信息。
Console
User{id=1, userName='userName'}Process finished with exit code 0
总结
流程图
有问题欢迎各位读者批评指正。
点个赞再走呗!欢迎留言哦!
手写XML版Spring容器相关推荐
- 解鞍卸甲——手写简易版Spring框架(终):使用三级缓存解决循环依赖问题
什么是三级缓存 按照目前我们实现的 Spring 框架,是可以满足一个基本需求的,但如果你配置了A.B两个Bean对象互相依赖,那么立马会抛出 java.lang.StackOverflowError ...
- 手写简版spring --8--Aware感知容器对象Aware感知容器对象
一.目标 目前已实现的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 对象的定义和注册,以及在操作 Bean 对象过程中执行的,BeanFactoryPostProcesso ...
- 手写简版spring --1--创建简单的Bean容器
一.声明 这个系列是我自己的学习笔记,为了在学习的过程中巩固知识而记录的,好强迫自己用心拜读,而不是进收藏夹.本系列都是基于小缚哥的文章和代码的,想要深入了解,请移步小缚哥博客 二.spring-Be ...
- 手写简易版Spring框架(七):定义标记类型接口Aware,实现感知容器相关的信息
文末有惊喜 目标 目前已实现的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 对象的定义和注册,以及在操作 Bean 对象过程中执行的,BeanFactoryPostProc ...
- 手写简版spring --10--容器事件和事件监听器
一.降低耦合 解耦场景在互联网开发的设计中使用的也是非常频繁,如:这里需要一个注册完成事件推送消息.用户下单我会发送一个MQ.收到我的支付消息就可以发货了等等,都是依靠事件订阅和发布以及MQ消息这样的 ...
- 手写简版spring --9--对象作用域和FactoryBean
一.目标 交给 Spring 管理的 Bean 对象,一定就是我们用类创建出来的 Bean 吗?创建出来的 Bean 就永远是单例的吗,没有可能是原型模式吗?在集合 Spring 框架下,我们使用的 ...
- 手写简版spring --2--实现Bean的定义、注册、获取
一.目标 在上一章节我们初步依照 Spring Bean 容器的概念,实现了一个粗糙版本的代码实现.那么本章节我们需要结合已实现的 Spring Bean 容器进行功能完善,实现 Bean 容器关于 ...
- 手写简版spring --7--初始化方法和销毁方法
一.目标 当我们的类创建的 Bean 对象,交给 Spring 容器管理以后,这个类对象就可以被赋予更多的使用能力.就像我们在上一章节已经给类对象添加了修改注册Bean定义未实例化前的属性信息修改和实 ...
- 手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor)
一.目标 如果你在自己的实际工作中开发过基于 Spring 的技术组件,或者学习过关于SpringBoot 中间件设计和开发等内容.那么你一定会继承或者实现了 Spring对外暴露的类或接口,在接口的 ...
最新文章
- 阿里云专家手把手教你重塑 IT 架构!
- DayDayUp:博主,在此,祝愿大家(十五种编程语言输出),2019年春节快乐!猪年诸事大吉!学要有所成,劳要有所获!
- 微软MSDN中文网络广播(Webcast)——Visual Studio 2010 ALM应用实践系列课程预告(2011)...
- ssh无密码公钥登陆
- java指定sql生成xml,用Java实现可保存状态的数据库生成XML树(8)-JSP教程,Java与XML...
- c语言事件结构体,C语言结构体史上最详细的讲解
- Java21天打卡Day7-循环
- boost基础——any(二)
- 【狂神MySQL笔记】初识Mysql
- baseline如何发布_baseline-简单的字符串基线。-Dan Gass
- 至今为止碰到的非常妖怪的计算机问题
- 川师c语言实验报告9,川师c语言实验报告十.doc
- 【如何快速的开发一个完整的iOS直播app】(原理篇)
- C语言代码绘制,利用数组输出 0-2Π之间的 sin 函数图像和 cos 函数图像,实验报告及代码。
- Gym - 100886I 2015-2016 Petrozavodsk Winter Training Camp, Saratov SU Contest I - Archaeological Res
- 用Python爬取28010条《隐秘的角落》评论,我发现了这些...
- word教程之word2007和2010版本查找和替换快捷键介绍
- 牛客小白月赛21(求三角形的外心模板)
- Unity踩坑:FindObjectsOfType can only be called from the main thread
- ORACLE ORA-01653: unable to extend table 的错误处理