Spring系列之手写注解与配置文件的解析
目录
引入
在前面我们已经完成了IOC,DI,AOP的实现,基本的功能都已经完成了,我们的手写框架也能勉强使用起来。为了让我们的框架能够使用起来比较简单,这一节我们来实现注解和xml的配置。
tips
本章的xml和注解的功能都是为实现bean的创建,其他如aop等功能可仿造实现。
为什么要加注解和xml配置
如果有同学测试过我们写好的框架,可能会感受到使用起来非常麻烦,在测试的时候我们需要显示的来定义bean以及运行过程中需要的其他对象。
public void test() throws Exception {
DefaultBeanDefinition bd = new DefaultBeanDefinition();
bd.setClazz(User.class);
bd.setSingleton(true);
bd.setBeanFactoryName("TestFactory");
bd.setCreateBeanMethodName("createMethod");
bd.setStaticCreateBeanMethodName("staticCreateMethod");
factory.register(bd, "user");
bd = new DefaultBeanDefinition();
bd.setClazz(BeforeAdvice.class);
factory.register(bd, "myBeforeAdvice");
AopProxyCreator aapc = new AopProxyCreator();
aapc.setBeanFactory(factory);
factory.registerBeanPostProcessor(aapc);
// 向AdvisorAutoProxyCreator注册Advisor
aapc.register(new RegexMatchAdvisor("myBeforeAdvice", "execution(* bean.User.*())", new RegexExpressionPointCutResolver()));
User user = (User) factory.doGetBean("user");
user.sayHello();
}
如上为测试一个AOP的功能,需要定义很多的对象来完成功能,这还只是一个对象的功能增强,在实际使用中肯定会有大量的实例。这样在使用起来就变得及其麻烦了。参考Spring中,可以通过xml和annotation的方式来简化类定义或者其他一些处理。
注解和xml的整个处理过程
在实际实现之前,我们先来宏观的看一些注解和xml是如何来解析的。
基本上在spring中xml就是这样工作的,同理,注解也差不多是这样一个过程。
上面的这一过程实际上就是我们需要实现的功能,现在我们就根据以上过程进行实现吧。
XML
定义XML标记
这一小节的内容并不重要,实际就我们的开发中作用并不大,稍微了解即可。没兴趣的可以直接跳到下一节。
定义xml标记的方式有dtd和xsd两种,假设我想定义一个下面这样的xml标记:
<?xml version="1.0"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
那么我们既可以用dtd实现,也可以用xsd实现:
dtd
<!ELEMENT note (to, from, heading, body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com"
elementFormDefault="qualified">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
这节内容只是稍微提下,有兴趣的可以搜一些资料学习。
加载xml文件
要来加载文件那么首先我们需要知道这个文件的位置,很明显这个位置需要由用户来指定,由用户来告诉我们需要加载那些配置文件,那么用户该如何来指定呢?
这里我们需要定义新的类和接口来完成这件事,这个新定义的类用来完成xml文件的加载,解析以及对bean实例的创建和注册等。同时该类是给用户使用的,在bean创建后还需要让用户能够取到容器中的实例,即该类还需要具备beanfactory的部分功能。
如何加载配置文件
说到加载,首先我们需要明白这些配置文件可能会以什么样的形式展现,一般来说有着以下的类型:
- FileSystem:从本地文件加载
- URL:从网络获取
- ClassPath:在项目中读取配置
可能还有其他不同的形式,当然这不重要。我们需要明白的是很明显不同形式的内容加载的方式肯定是不同的,比如通过文件系统加载的是获得一个文件,而url形式的是从网络获取数据。所以我们需要为每一种方式都提供个性的加载方式。
加载的方式不一样,那么解析呢?
解析xml,我们都是需要获取到xml的流信息,都是解析xml的InputStream,所以虽然加载方式各不相同,但是解析的方法是可以通用的。
根据上面的分析,我们可以知道,加载的过程实际上就是获取一个InputStream的过程,很明显每一种方式获取配置文件都需要最终返回一个InputStream,这里我们定义一个获取InputStream的接口。
对于配置文件的加载实际上不管通过哪一种方式,实际上都是对文件进行操作,为了方便能够对解析提供一致的接口,我们需要对不同方式加载进行抽象,使其能接受任意类型的加载方式对象。这里我们定义Resource接口来表示xml资源,不同的实现类表示不同的加载方式。Resource接口具备一部分文件的特性。
到了现在我们还有一个很重要的问题,就是我们如何来分辨当前需要加载的配置是属于哪一种类型呢?只有解决了这一问题才能正确的解析。
这里我们使用前缀匹配的方式来分配不同类型的配置文件加载器,比如:
- FileSystem:使用file:前缀
- ClassPath:使用classpath:前缀
- URL:可以使用url:前缀,或者直接使用instanceof来校验对象
通过不同的前缀来来返回不同的对象,如果看过前面几节的同学应该马上就能反应过来这里肯定要用工厂模式了[笑]。
那么加载配置文件这一行为在什么时候进行呢?
考虑到类ApplicationContext是用户使用框架的入口,该类还包含获取bean实例的操作,要保证在该类实例化完成后让ApplicationContext具备获取实例的能力,那么加载配置文件的功能就需要在ApplicationContext的构造方法中完成。
结合以上分析,对ApplicationContext类图做出修改。
如何解析配置文件
加载已经完成了,就是说我们现在已经取到不同的Resource,那么现在如何对其进行解析呢?
对于xml类型的文件解析我们这里使用dom4j,这个东西没必要深入研究,要用到的时候查下api就行了。对于xml的解析就是获取节点,然后对获取节点的内容。回顾我们之前在做IOC的时候,创建一个bean首先是需要获取BeanDefinition。xml这里也一样,根据解析到的内容构造BeanDefinition,通过BeanDefinitionRegistery注册。在对bean实例化时取用。所以很明显我们需要定义一个新的接口用于解析Resource,将解析后的内容封装为BeanDefinition并注册。
好了,到这里关于xml的加载和解析基本就完成了,而对于annotation的解析流程基本也是这样的,用户指定需要扫描的包,框架遍历包所在目录及子目录,记录下相应被注解修饰的类,反射生成class对象,获取class对象数据生成BeanDefinition。类图在上面也已经体现出来了。后面就需要我们去写代码了。
相关的代码已经托管到github
Spring系列之手写注解与配置文件的解析的更多相关文章
- Spring系列之手写一个SpringMVC
目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 Spring系列之AOP的原理及手动实现 Spring系列之手写注解与配置文件的解析 引言 在前面的几个章节中我 ...
- 【Spring系列】- 手写模拟Spring框架
简单模拟Spring 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 前言 上次已经学习了 ...
- Spring学习之——手写Spring源码V2.0(实现IOC、D、MVC、AOP)
前言 在上一篇<Spring学习之——手写Spring源码(V1.0)>中,我实现了一个Mini版本的Spring框架,在这几天,博主又看了不少关于Spring源码解析的视频,受益匪浅,也 ...
- Spring系列9:基于注解的Spring容器配置
写在前面 前面几篇中我们说过,Spring容器支持3种方式进行bean定义信息的配置,现在具体说明下: XML:bean的定义和依赖都在xml文件中配置,比较繁杂. Annotation-based ...
- 【深度学习系列】手写数字识别卷积神经--卷积神经网络CNN原理详解(一)
上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...
- 【PaddlePaddle系列】手写数字识别
最近百度为了推广自家编写对深度学习框架PaddlePaddle不断推出各种比赛.百度声称PaddlePaddle是一个“易学.易用”的开源深度学习框架,然而网上的资料少之又少.虽然百度很用心地提供 ...
- 2020年春招面试必备Spring系列面试题129道(附答案解析)
前言 关于Spring的知识总结了个思维导图分享给大家 1.不同版本的 Spring Framework 有哪些主要功能? 2.什么是 Spring Framework? Spring 是一个 ...
- Spring学习之——手写Mini版Spring源码
前言 Sping的生态圈已经非常大了,很多时候对Spring的理解都是在会用的阶段,想要理解其设计思想却无从下手.前些天看了某某学院的关于Spring学习的相关视频,有几篇讲到手写Spring源码,感 ...
- spring的bean管理(注解和配置文件混合使用)
1.建三个类,在一个类中引用其他两个类 import javax.annotation.Resource; import org.springframework.beans.factory.annot ...
随机推荐
- C++标准库第二版笔记 2.1
C++标准库第二版笔记 2.1 1 Range-Based for 循环 for ( decl : coll ) { statements; } // collaborate 类似C# foreach ...
- 查看进程被哪台电脑的哪个进程连接(netstat)
1.netstat -ano|findstr 进程号,找出连接该进程A所有的ip(可以看到该进程的端口号和连接进程的端口号): 2.到连接该进程的电脑上,打开cmd命令行,输入netstat -ano ...
- ehcache如何配置
1.pom.xml文件配置(主要针对jar包的引入) <ehcache.version>2.6.9</ehcache.version><ehcache-web.versi ...
- 直播流RTMP 知识
分享直播相关知识点: http://blog.csdn.net/kingroc/article/details/50839994 #!/bin/bash# Order Finish Startup# ...
- orm介绍
昨日回顾: 1 今日内容: 1 orm介绍 1 tools--->Run manage.py Task python3 manage.py makemigrations 只需要敲命令:makem ...
- python学习,excel操作之xlsxwriter常用操作
from datetime import datetime import xlsxwriter #打开文件 workbook = xlsxwriter.Workbook('Expenses03.xls ...
- CSU1333最短路问题SPFA
fastvj.rainng.com/contest/236779#problem/I Description: n个点m条路每条路 l,r,t:表示这条路开l秒,关r秒,通过要t秒,问你车辆从s到t最 ...
- junit 方法:assertEquals 和 assertTrue
assertEquals 和 assertTrue 区别相同之处:都能判断两个值是否相等 assertTrue 如果为true,则运行success,反之Failure assertEquals 如果 ...
- python的基本数据类型(一)
一.运算符逻辑运算and:两边都真则真or:有真则真not:非假是真 顺序:()>==>not==>and>=or 二.while.. elsewhile 条件: 代码块els ...
- 简易webpack 入门
webpack 模块打包机 作用:将浏览器不识别的语言转化成浏览器识别的语言 工作流程 通过一个入口文件 找到这个入口文件所依赖的所有模块,将这些文件打包成一个或多个文件 如何使用: 1.安装 cnp ...