Java—实现 IOC 功能的简单 Spring 框架

编写一个实现 IOC 功能的简单 Spring 框架,包含对象注册、对象管理、及暴 露给外部获取对象的功能,并编写测试程序。扩展注册器的方式,要求采用 XML 和 txt 文件。

源代码

package myspring;import java.lang.reflect.Method;
import java.util.Map;/*** 最顶层的IOC实现* 该类负责从注册器中取出注册对象* 实现从对象描述信息转换为对象实例的过程、* 实现根据名称获取对象的方法*/
public abstract class AbstractBeanFactory implements BeanFactory {private String filePath;   //注册文件路径private Map<String,BeanInfo> container; //注册对象信息Mapprotected SourceReader reader; //对象注册读取器public AbstractBeanFactory(String filePath){this.filePath = filePath;}/*** 该方法为抽象方法,需有子类类实现,用于指定使用什么样的注册读取器* @param reader 指定的注册读取器*/protected abstract void setSourceReader(SourceReader reader);// 从注册读取器中读取,注册对象的信息MAPpublic void registerBeans(){this.container = this.reader.loadBeans(filePath);}//  实现BeanFactory定义的根据名称获取指定对象的方法@Overridepublic Object getBean(String name) {BeanInfo beaninfo = this.container.get(name); //根据对象名获取该对象的描述信息if(beaninfo == null){ //如果容器中不存在该对象的描述信息,则返回null,此处可以抛开一个异常return null;}else{ //根据对象信息,解析并生成指定对象实例,返回给用户return this.parseBean(beaninfo);}}  /*** 解析并生成对象实例* 该方法主要通过反射完成,步骤如下:* 1.根据类名,加载指定类,并获取该类的貌似Class对象clazz* 2.使用Class对象clazz实例化该类,获取一个对象,注意,这儿实例化对象时,采用的无参构造方法,因此要求注册的对象必须含有无参构造方法* 3.逐个设置对象字段的值,这儿采用setter Method方式,而不是直接使用Field对象的原因是,用户有可能在setter对象中,对注入的值进行额外处理,如格式化等* 4.返回对象实例* @param beaninfo 指定对象的描述信息* @return*/protected Object parseBean(BeanInfo beaninfo){Class clazz; try {clazz = Class.forName(beaninfo.getType()); //根据对象的全类名,指定类Object bean = clazz.newInstance(); //使用注册对象的无参构造函数,实例化对象实例Method[] methods = clazz.getMethods(); //获取该类声明的所有公共方法,其实Spring获取的是所有方法,包括非公有的for(String property : beaninfo.getProperties().keySet()){ //遍历对象的所有属性,进行赋值String setter = "set" + StringUtil.firstCharToUp(property); //获取属性的setter方法名称for(Method method : methods){ //遍历该类的所有公有方法String methodName = method.getName(); //获取方法名称if(methodName.equals(setter)){ //比较方法名与属性的setter方法名是否相同,如果相同则进行赋值Object value = beaninfo.getProperties().get(property); //从对象描述信息中获取该属性的值method.invoke(bean,value); //通过反射对属性进行赋值continue; //对下一属性赋值}}}return bean; //返回指定的对象} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} return null;}}package myspring;/*** IOC容器的顶层接口*/
public interface BeanFactory {/*** 根据对象的名称标识来获取对象实例* @param name 对象名称,即对象描述信息中的对象标识* @return 指定名称的对象实例*/Object getBean(String name);
}package myspring;import java.util.HashMap;
import java.util.Map;//该类用于描述注册在容器中的对象
public class BeanInfo {private String id; //对象的标识private String type; //对象的类型,即全类名private Map<String,Object> properties = new HashMap<String,Object>(); //对象的属性及值得集合 public String getId() {return id;}public void setId(String id) {this.id = id;}public String getType() {return type;}public void setType(String type) {this.type = type;}public Map<String,Object> getProperties() {return properties;}public void setProperties(Map<String, Object> properties) {this.properties = properties;}public void addProperty(String name, Object value){this.properties.put(name, value);}
}
package myspring;public class Bootstrap {public static void main(String[] args) {BeanFactory factory = new TXTContext("bean.txt");Speakable s = (Speakable)factory.getBean("Person");s.speak("Lesson one!");}
}
package myspring;public class Person implements Speakable {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void speak(String message) {System.out.println( this.name + " say: " + message);}
}
package myspring;import java.util.Map;/*** 注册读取器接口* 负责从读取用户注册的对象* 继承该接口的类可以实现多种读取方式,如从配置文件中读取,根据标注读取,从网络中读取等*/
public interface SourceReader {/*** 读取用户注册的对象信息* @param filePath 读取录取* @return 注册对象信息Map*/Map<String,BeanInfo> loadBeans(String filePath);
}
package myspring;public interface Speakable {public void speak(String message);
}
package myspring;public class StringUtil {/*public static void main(String[] args) {System.out.println(StringUtil.firstCharToUp(str)); }*/public static String firstCharToUp(String str){char ch[]=str.toCharArray();char ch1=Character.toUpperCase(ch[0]);ch[0]=ch1;String s=new String(ch);return s;}public static String firstCharToLower(String str){char ch[]=str.toCharArray();char ch1=Character.toLowerCase(ch[0]);ch[0]=ch1;String s=new String(ch);return s;}
}
package myspring;public class TXTContext extends AbstractBeanFactory {/*** 上下文的构造方法* 该方法中指明注册读取器* 并在构造该方法时一次性的加载注册的对象* @param filePath*/public TXTContext(String filePath) {super(filePath);this.setSourceReader(new TXTSourceReader()); //添加注册读取器,此处的注册读取器为XMLSourceReaderthis.registerBeans(); //加载注册的对象信息}//  设置注册读取器@Overrideprotected void setSourceReader(SourceReader reader) {this.reader = reader;}
}package myspring;import org.w3c.dom.*;
import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.HashMap;
import java.util.Map;public class TXTSourceReader implements SourceReader{/*** 实现读取注册对象信息方法* 此处只是模拟测试使用,感兴趣的同学可以自己书写通过配置文件读取的实现*/@Overridepublic Map<String, BeanInfo> loadBeans(String filePath) {//初始化一个对象信息Map<String,BeanInfo> beans = new HashMap<String,BeanInfo>(); //初始化一个对象信息MapBeanInfo beanInfo=new BeanInfo();File filename = new File("bean.txt"); // 要读取以上路径的input。txt文件InputStreamReader reader = null; // 建立一个输入流对象readertry {reader = new InputStreamReader(new FileInputStream(filename));BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言String line = "";line = br.readLine();while (line != null) {String[] t=line.split("=");System.out.println(t[0]+t[1]);if(t[0].equals("id")){beanInfo.setId(t[1]);}else if(t[0].equals("class")){beanInfo.setType(t[1]);}else beanInfo.addProperty(t[0],t[1]);line = br.readLine();}} catch (FileNotFoundException fileNotFoundException) {fileNotFoundException.printStackTrace();} catch (IOException ioException){ioException.printStackTrace();}beans.put(beanInfo.getId(),beanInfo);return beans; //返回对象信息MAP}package myspring;public class XMLContext extends AbstractBeanFactory{/*** 上下文的构造方法* 该方法中指明注册读取器* 并在构造该方法时一次性的加载注册的对象* @param filePath*/public XMLContext(String filePath) {super(filePath);this.setSourceReader(new XMLSourceReader()); //添加注册读取器,此处的注册读取器为XMLSourceReaderthis.registerBeans(); //加载注册的对象信息}  //  设置注册读取器@Overrideprotected void setSourceReader(SourceReader reader) {this.reader = reader;}
}package myspring;import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.xpath.XPath;import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;/*** XML注册读取器* 该类继承了注册读取器接口,并模拟实现了读取注册对象信息的方法*/
public class XMLSourceReader implements SourceReader {/*** 实现读取注册对象信息方法* 此处只是模拟测试使用,感兴趣的同学可以自己书写通过配置文件读取的实现*/@Overridepublic Map<String, BeanInfo> loadBeans(String filePath) {//初始化一个对象信息Map<String,BeanInfo> res = new HashMap<String,BeanInfo>(); //初始化一个对象信息Maptry {SAXBuilder builder = new SAXBuilder();Document doc = null;doc = (Document) builder.build(new File("book.xml"));  XPath xpath = null;    xpath = XPath.newInstance("//bean");List beans = null;beans = xpath.selectNodes(doc);  Iterator i = beans.iterator();while (i.hasNext()) {BeanInfo beaninfo = new BeanInfo();Element bean = (Element) i.next();String id = bean.getAttributeValue("id");String cls = bean.getAttributeValue("class");beaninfo.setId(id);beaninfo.setType(cls);List<Element> list = bean.getChildren("property");for (Element el : list) {if (el.getAttribute("name") != null) {beaninfo.addProperty(el.getAttributeValue("name"),el.getAttributeValue("value"));}}res.put(beaninfo.getId(),beaninfo);}} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return res;}
}}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读zepto核心源码学习JS笔记(3)--zepto.init()

上篇已经讲解了zepto.init()的几种情况,这篇就继续记录这几种情况下的具体分析. 1. 首先是第一种情况,selector为空 既然是反向分析,那我们先看看这句话的代码; if (!selector) return zepto.Z() 这里的返回值为zepto.Z();那我们继续往上找zepto.Z()函数 zepto.Z function(dom…

css flexbox模型_Flexbox和CSS Grid之间的主要区别

css flexbox模型by Shaira Williams由莎拉威廉姆斯(Shaira Williams) Flexbox和CSS Grid之间的主要区别 (The main differences between Flexbox and CSS Grid) Dimensions define the primary demarcation between Flexbox and CSS Grid. Flexbox was designed specifically …

置信区间估计 预测区间估计_估计,预测和预测

置信区间估计 预测区间估计Estimation implies finding the optimal parameter using historical data whereas prediction uses the data to compute the random value of the unseen data.估计意味着使用历史数据找到最佳参数&#xff0c;而预测则使用该数据来计算未见数据的…

鸿蒙系统还会推出吗,华为明年所有自研设备都升级鸿蒙系统,还会推出基于鸿蒙系统的新机...

不负期许&#xff0c;华为鸿蒙OS手机版如期而至。今日(12月15日)&#xff0c;鸿蒙OS 2.0手机开发者Beta版本正式上线&#xff0c;支持运行安卓应用&#xff0c;P40、Mate 30系列可申请公测。国内媒体报道称&#xff0c;华为消费者业务软件部副总裁杨海松表示&#xff0c;按照目…

C#中将DLL文件打包到EXE文件

1&#xff1a;在工程目录增加dll目录&#xff0c;然后将dll文件复制到此目录&#xff0c;例如&#xff1a; 2&#xff1a;增加引用&#xff0c;定位到工程的dll目录&#xff0c;选中要增加的dll文件 3&#xff1a;修改dll文件夹下面的dll文件属性 选中嵌入式资源&#xff0c;不…

PopupMenu控件的使用

1、用PopupMenu控件能进行右键菜单的实现&#xff0c;它的实现还需要绑定到barManager控件上&#xff0c;在barManager的Customize中添加右键所需要显示的功能。 2、PopupMenu属性栏中绑定Manager为barManager&#xff1b; 3、窗体加载事件中创建 this.popupMenu1.AddItems(new…

Java—动态代理

动态代理利用了JDK API&#xff0c;动态地在内存中构建代理对象&#xff0c;从而实现对目标对象的代理功能。动态代理又被称为JDK代理或接口代理。 静态代理与动态代理的区别主要在&#xff1a; 静态代理在编译时就已经实现&#xff0c;编译完成后代理类是一个实际的class文件…

Oracle VM Virtual Box的安装

安装Oracle VM Virtual Box安装扩展插件 选择"管理""全局设定" 在设置对话框中&#xff0c;选择"扩展" 选择"添加包" 找到"Oracle_VM_VirtualBox_Extension_Pack-4.1.18-78361"&#xff0c;点击"打开" 5&#x…

python 移动平均线_Python中的SMA(短期移动平均线)

python 移动平均线With the evolution of technology rapidly evolving, so do strategies in the stock market. In this post, I’ll go over how I created a SMA(Short Moving Average) strategy.随着技术的飞速发展&#xff0c;股票市场的策略也在不断发展。 在本文中&…

angular中的href=unsafe:我该怎么摆脱你的溺爱!!

解决方法&#xff1a;angular.module加入下面这行&#xff1a;&#xff08;依据Angular changes urls to “unsafe:” in extension page&#xff09; .config(function($compileProvider){//注:有些版本的angularjs为$compileProvider.urlSanitizationWhitelist(/^\s*(https?…

android view gesturedetector,如何在Android中利用 GestureDetector进行手势检测

如何在Android中利用 GestureDetector进行手势检测发布时间&#xff1a;2020-11-26 16:15:21来源&#xff1a;亿速云阅读&#xff1a;92作者&#xff1a;Leah今天就跟大家聊聊有关如何在Android中利用 GestureDetector进行手势检测&#xff0c;可能很多人都不太了解&#xff0c…

Ubuntu2204配置samba

0.前情说明 samba服务器主要是用来局域网共享文件的&#xff0c;如果想公网共享可能行不通&#xff0c;我已经踩坑一天了 所以说如果你想满足公网samba共享你就可以不要看下去了 1.参考连接 Ubuntu 安装 Samba 服务器_ubuntu安装samba服务器-CSDN博客 2.安装samba服务 sud…

Java—BIO模型

利用 BIO 模型&#xff08;传统阻塞 IO 模型&#xff09;实现多用户访问 源代码 Server类 public class server {public static void main(String[] args) {ExecutorService executorService Executors.newFixedThreadPool(6);try {ServerSocket serverSocketnew ServerSocke…

c++学编程如何锻炼耐力_我如何学习编程:这是一项耐力运动

c学编程如何锻炼耐力by Amy M Haddad通过艾米M哈达德(Amy M Haddad) 我如何学习编程&#xff1a;这是一项耐力运动 (How I’m learning to program: it’s an endurance sport) 为什么我的编程学习轨迹反映了我作为跑步者的训练方式 (Why my learning trajectory for programm…

python处理文本数据

处理文本数据&#xff0c;主要是通过Seris的str访问。遇到NaN时不做任何处理&#xff0c;保留结果为NaN&#xff0c;遇到数字全部处理为NaN。 str是Seris的方法&#xff0c;DataFrame不能直接使用&#xff0c;但是通过索引选择DataFrame中的某一行或者某一列&#xff0c;结果为…

Java系列笔记(4) - JVM监控与调优【转】

Java系列笔记(4) - JVM监控与调优【转】 目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例 光说不练假把式&#xff0c;学习Java GC机制的目的是为了实用&#xff0c;也就是为了在JVM出现问题时分析原因并解决之。通过学习&#xff0c;我觉得JVM监控与调…

Maven打包排除某个资源或者目录

最近在spark streaming本地调试的时候&#xff0c;引入了一些资源文件&#xff0c;打包的时候需要给排除掉。所以就考虑使用maven的方式 详细参考官方文档&#xff1a;https://maven.apache.org/plugins/maven-jar-plugin/examples/include-exclude.html 排除某个资源文件 <…

android发送网络请求没反应,Android无法使用HttpURLConnection发送GET请求

我正在尝试在我的应用程序中使用HttpURLConnection.我将我的请求方法设置为’GET’,但是当我尝试检索输出流时,该方法将更改为’POST’&#xff01;我不确定是什么原因,但是当我使用’POST’发送请求时,我的JSON服务器(我使用JAX-RS)会返回一个空白页面.这是我的代码片段&#…

地图 c-suite_C-Suite的模型

地图 c-suiteWe’ve all seen a great picture capture an audience of stakeholders.我们所有人都看到了吸引利益相关者听众的美好画面。 Let’s just all notice that the lady in the front right is not captivated by the image on the board (Photo by Christina wocin…

框架和库的区别_框架和库之间的区别

框架和库的区别Developers often use the terms “library” and “framework” interchangeably. But there is a difference.开发人员经常互换使用术语“库”和“框架”。 但是有区别。 Both frameworks and libraries are code written by someone else that is used to he…