我也来写spring
本文可作为北京尚学堂 spring课程的学习笔记
我们还是用上一篇文章的例子 给数据库中增加一个user
整体代码如下
- package com.bjsxt.test;
- import com.bjsxt.dao.UserDaoMysql;
- import com.bjsxt.model.User;
- import com.bjsxt.services.UserService;
- public class Test {
- public static void main(String[] args) {
- User user=new User();
- UserService userService=new UserService();
- UserDao dao=new UserDaoMysql();
- userService.setUserDao(dao);
- userService.Save(user);
- }
- }
上一个的test中 还是需要我写出
UserDao dao=new UserDaoMysql();
如果我想从xml中读出数据 以后可以不再改硬代码 如何?
首先写出xml文件
- <?xml version="1.0" encoding="UTF-8"?>
- <beans>
- <bean id="u" class="com.bjsxt.dao.UserDaoMysql" />
- </beans>
如果是oracle 也只用xml文件即可
现在我们需要做的就是读取xml "自动"生成userdao 关于用jdom操作xml的只是 请看文章末尾的参考资料
我们现在要生产一个对象 那就是工厂模式嘛
- package com.bjsxt.spring;
- public interface BeanFactory {
- public Object getBean(String id);
- }
再来一个操作xml的类
- package com.bjsxt.spring;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.jdom.Document;
- import org.jdom.Element;
- import org.jdom.JDOMException;
- import org.jdom.input.SAXBuilder;
- public class ClassPathXmlApplicationContext implements BeanFactory {
- Map<String, Object> map=new HashMap<String, Object>();
- @SuppressWarnings("unchecked")
- public ClassPathXmlApplicationContext() throws JDOMException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
- SAXBuilder sb = new SAXBuilder();
- Document doc = sb.build(ClassPathXmlApplicationContext.class
- .getClassLoader().getResourceAsStream("spring.xml")); // 构造文档对象
- // Document doc=sb.build("d://test.xml"); //构造文档对象可以有两种方式 如果是在把xml文档放在
- //eclipse的根目录下 就有上面的方法
- Element root = doc.getRootElement(); // 获取根元素
- List<Element> list = root.getChildren("bean");// 取名字为bean的所有元素
- for (int i = 0; i < list.size(); i++) {
- Element element = (Element) list.get(i);
- String name = element.getAttributeValue("id");
- String classPath = element.getAttributeValue("class");//取bean的元素class的内容
- Object object=Class.forName(classPath).newInstance();
- map.put(name,object);
- System.out.println("bean:");
- System.out.println("bean name: " + name);
- System.out.println("bean class: " + classPath);
- System.out.println("———————————–");
- }
- }
- @Override
- public Object getBean(String id) {
- return map.get(id);
- }
- }
测试test如下
- package com.bjsxt.test;
- import java.io.IOException;
- import org.jdom.JDOMException;
- import com.bjsxt.dao.UserDao;
- import com.bjsxt.dao.UserDaoMysql;
- import com.bjsxt.model.User;
- import com.bjsxt.services.UserService;
- import com.bjsxt.spring.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) throws JDOMException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
- User user=new User();
- UserService userService=new UserService();
- ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext();
- Object object=context.getBean("u");
- userService.setUserDao((UserDao) object);
- userService.Save(user);
- }
- }
现在看看 上面的代码 我们还是有
userService.setUserDao((UserDao) object);
能不能吧userservice也从xml中读取 同时 它内部的属性也从xml中来
可以 那么xml首先得变成如下的样子
- <?xml version="1.0" encoding="UTF-8"?>
- <beans>
- <bean id="u" class="com.bjsxt.dao.UserDaoMysql" />
- <bean id="userService" class="com.bjsxt.services.UserService" >
- <property name="userDao" bean="u" />
- </bean>
- </beans>
test测试函数应该是这样的
- package com.bjsxt.test;
- import com.bjsxt.model.User;
- import com.bjsxt.services.UserService;
- import com.bjsxt.spring.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) throws Exception {
- User user=new User();
- ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext();
- UserService userService=(UserService) context.getBean("userService");
- userService.Save(user);
- }
- }
关键问题就是 ClassPathXmlApplicationContext内部怎么写
其实大家可以这样想 我在读取每一个bean的时候就看看它底下有没有参数 有的话就用反射技术 自动将属性装填进去
- package com.bjsxt.spring;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.jdom.Document;
- import org.jdom.Element;
- import org.jdom.input.SAXBuilder;
- public class ClassPathXmlApplicationContext implements BeanFactory {
- Map<String, Object> map = new HashMap<String, Object>();
- @SuppressWarnings("unchecked")
- public ClassPathXmlApplicationContext() throws Exception {
- SAXBuilder sb = new SAXBuilder();
- Document doc = sb.build(ClassPathXmlApplicationContext.class
- .getClassLoader().getResourceAsStream("spring.xml")); // 构造文档对象
- // Document doc=sb.build("d://test.xml");
- Element root = doc.getRootElement(); // 获取根元素
- List<Element> list = root.getChildren("bean");// 取名字为disk的所有元素
- for (int i = 0; i < list.size(); i++) {
- Element element = (Element) list.get(i);
- String name = element.getAttributeValue("id");
- String classPath = element.getAttributeValue("class");// 取disk子元素capacity的内容
- Object object = Class.forName(classPath).newInstance();
- map.put(name, object);
- for (Element propertyElement : (List<Element>) element
- .getChildren("property")) {
- String parameter = propertyElement.getAttributeValue("name"); // 获得userDao这个属性名称
- String bean = propertyElement.getAttributeValue("bean"); //就是xml里面的那个u
- Object obj = map.get(bean); //找到map里面的那个u
- //大家再试试把xml里面的两个bean的顺序调换一下 看有什么问题
- // 如何修改?
- String methodName = "set" //获得setUserDao这个方法名
- + parameter.substring(0, 1).toUpperCase()
- + parameter.substring(1);
- System.out.println(methodName);
- Method m = object.getClass().getMethod(methodName,
- obj.getClass().getInterfaces()[0]);
- // 查看getMethod的参数 String name, Class<?>... parameterTypes
- // 我们知道方法的名字是setUserDao 可问题是一个类中 可能出现重载情况 也就是方法名一样的情况
- // 所以后面的参数的意思就是 setUserDao的参数就是上面那个obj所实现的第一个接口
- m.invoke(object, obj);
- }
- }
- }
- @Override
- public Object getBean(String id) {
- return map.get(id);
- }
- }
ok 搞定 里面最麻烦的东西 我认为还是反射
这些代码 我认为初学者还是自己敲一遍比较好
参考资料
http://www.blogjava.net/fjq639/archive/2005/12/20/24806.html
我也来写spring的更多相关文章
- 自己动手写spring容器(3)
好久没有写博客了,今天闲下来将之前未完成的表达出来. 在之前的文章自己动手写spring容器(2)中完成了对spring的依赖注入的实现,这篇将会介绍spring基于注解的依赖注入的实现. 在一般的J ...
- 一个老程序员是如何手写Spring MVC的
人见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十 ...
- 【Spring】手写Spring MVC
Spring MVC原理 Spring的MVC框架主要由DispatcherServlet.处理器映射.处理器(控制器).视图解析器.视图组成. 完整的Spring MVC处理 流程如下: Sprin ...
- 我是这样手写 Spring 的(麻雀虽小五脏俱全)
人见人爱的 Spring 已然不仅仅只是一个框架了.如今,Spring 已然成为了一个生态.但深入了解 Spring 的却寥寥无几.这里,我带大家一起来看看,我是如何手写 Spring 的.我将结合对 ...
- 《四 spring源码》利用TransactionManager手写spring的aop
事务控制分类 编程式事务控制 自己手动控制事务,就叫做编程式事务控制. Jdbc代码: Conn.setAutoCommite(false); // 设置手动控制事务 Hibern ...
- 自己写spring boot starter
自己写spring boot starter 学习了:<spring boot实战>汪云飞著 6.5.4节 pom.xml <project xmlns="http://m ...
- 手写 Spring
手写 Spring 不多说,简历装 X 必备.不过练好还是需要求一定的思维能力. 一.整体思路 思路要熟练背下来 1)配置阶段 配置 web.xml: XDispatchServlet 设定 init ...
- 自己动手写Spring框架--IOC、MVC
对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...
- 手写Spring框架,加深对Spring工作机制的理解!
在我们的日常工作中,经常会用到Spring.Spring Boot.Spring Cloud.Struts.Mybatis.Hibernate等开源框架,有了这些框架的诞生,平时的开发工作量也是变得越 ...
- 手写Spring+demo+思路
我在学习Spring的时候,感觉Spring是很难的,通过学习后,发现Spring没有那么难,只有你去学习了,你才会发现,你才会进步 1.手写Spring思路: 分为配置.初始化.运行三个阶段如下图 ...
随机推荐
- JVM常见问题 一(转载)
1. 内存模型以及分区 JVM内存模型如下图所示: 此处我们集中注意中间绿色的部分,该部分为JVM的运行时内存,该部分包含了: 线程私有的(灰色): 程序计数器:记录执行到第几条指令 虚拟机方法栈:执 ...
- Mysql中where条件一个单引号引发的性能损耗
日常写SQL中可能会有一些小细节忽略了导致整个sql的性能下降了好几倍甚至几十倍,几百倍.以下这个示例就是mysql语句中的一个单引号('')引发的性能耗损,我相信很多朋友都遇到过,甚至还在这样写. ...
- 列表ListBox、ListView、GridView 排序
列表排序 1.使用控件默认排序方式(推荐) ListControl.Items.SortDescriptions.Clear(); ListControl.Items.SortDescriptions ...
- WIN2008虚拟机安装ORACLE11g记录
---恢复内容开始--- 1.ORACLE11g的安装包下载与解压 官网下载地址:(http://www.oracle.com/technetwork/database/enterprise-edit ...
- UDP网络编程
概念: UDP协议(用户数据报协议)是无连接,不可靠的,无序的.速度比较快, UDP协议以数据报作为数据传输的载体 进行数据传输时,首先将传输的数据定义成数据报(Datagram),在数据报中指明数据 ...
- SimpleDateFormat中parse和format的区别
parse()返回的是一个Date类型数据,format返回的是一个StringBuffer类型的数据 //SimpleDateFormat中的parse方法可以 //把String型的字符串转换成特 ...
- sklearn:最近邻搜索sklearn.neighbors
http://blog.csdn.net/pipisorry/article/details/53156836 ball tree k-d tree也有问题[最近邻查找算法kd-tree].矩形并不是 ...
- 有无序的实数列V[N],要求求里面大小相邻的实数的差的最大值,关键是要求线性空间和线性时间。
int findMaxDifBt2Nums(int* arr, int len) { int maxItem = arr[0], minItem = arr[0]; for (int i = 1; i ...
- Android Multimedia框架总结(十一)CodeC部分之AwesomePlayer到OMX服务
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52623882 前言:上篇文< ...
- lucene内存索引库、分词器
内存索引库 特点 在内存中开辟一块空间,专门为索引库存放.这样有以下几个特征: 1) 因为索引库在内存中,所以访问速度更快. 2) 在程序退出时,索引库中的文件也相应的消失了. 3) ...