本文可作为北京尚学堂 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的更多相关文章

  1. 自己动手写spring容器(3)

    好久没有写博客了,今天闲下来将之前未完成的表达出来. 在之前的文章自己动手写spring容器(2)中完成了对spring的依赖注入的实现,这篇将会介绍spring基于注解的依赖注入的实现. 在一般的J ...

  2. 一个老程序员是如何手写Spring MVC的

    人见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十 ...

  3. 【Spring】手写Spring MVC

    Spring MVC原理 Spring的MVC框架主要由DispatcherServlet.处理器映射.处理器(控制器).视图解析器.视图组成. 完整的Spring MVC处理 流程如下: Sprin ...

  4. 我是这样手写 Spring 的(麻雀虽小五脏俱全)

    人见人爱的 Spring 已然不仅仅只是一个框架了.如今,Spring 已然成为了一个生态.但深入了解 Spring 的却寥寥无几.这里,我带大家一起来看看,我是如何手写 Spring 的.我将结合对 ...

  5. 《四 spring源码》利用TransactionManager手写spring的aop

    事务控制分类 编程式事务控制          自己手动控制事务,就叫做编程式事务控制. Jdbc代码: Conn.setAutoCommite(false);  // 设置手动控制事务 Hibern ...

  6. 自己写spring boot starter

    自己写spring boot starter 学习了:<spring boot实战>汪云飞著 6.5.4节 pom.xml <project xmlns="http://m ...

  7. 手写 Spring

    手写 Spring 不多说,简历装 X 必备.不过练好还是需要求一定的思维能力. 一.整体思路 思路要熟练背下来 1)配置阶段 配置 web.xml: XDispatchServlet 设定 init ...

  8. 自己动手写Spring框架--IOC、MVC

    对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...

  9. 手写Spring框架,加深对Spring工作机制的理解!

    在我们的日常工作中,经常会用到Spring.Spring Boot.Spring Cloud.Struts.Mybatis.Hibernate等开源框架,有了这些框架的诞生,平时的开发工作量也是变得越 ...

  10. 手写Spring+demo+思路

    我在学习Spring的时候,感觉Spring是很难的,通过学习后,发现Spring没有那么难,只有你去学习了,你才会发现,你才会进步 1.手写Spring思路: 分为配置.初始化.运行三个阶段如下图 ...

随机推荐

  1. 基于PHP的对接免费电子面单接口平台的案例-快宝开放平台

    一.电子面单对接平台 电子面单对接平台分为两类: 1 .各大快递公司自有的电子面单接口开放平台:对接起来麻烦,需要每个快递公司分别调试接口,费时费力. 2 .第三方快递开放平台:如快宝开放平台(htt ...

  2. 90. Subsets II(中等,编写代码有难度)

    Given a collection of integers that might contain duplicates, nums, return all possible subsets. Not ...

  3. Go 处理yaml类型的配置文件

    先说一下,这里用到了很多关于反射类型的功能,可能刚开始看代码,如果对反射不熟悉的可能会不是非常清晰,但是同时也是为了更好的理解golang中的反射,同时如果后面想在代码中可以直接从我的git地址get ...

  4. delphi 线程教学第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行

    第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行     以 Ado 为例,常见的方法是拖一个 AdoConnection 在窗口上(或 DataModule 中), 再配合 AdoQ ...

  5. Codeforces Round #305 (Div. 2) A. Mike and Fax 暴力回文串

     A. Mike and Fax Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/548/pro ...

  6. jQuery – AJAX get() 和 post() 方法

    jQuery get() 和 post() 方法用于通过 HTTP GET 或 POST 请求从服务器请求数据. HTTP 请求:GET vs. POST 两种在客户端和服务器端进行请求-响应的常用方 ...

  7. Git提交代码到远程服务器

    1.下载Git 不用说了,这个是必须的,也是最简单的步骤,地址如下: http://git-scm.com/download 这里会提供三个版本的下载地址,读者可以自行查找. 2.创建代码库 远程的代 ...

  8. Java中使用CountDownLatch进行多线程同步

    CountDownLatch介绍 在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法: 1.synchronized关键字进行同步. 2.Lock锁接口及其实现类ReentrantL ...

  9. windows pe

    下载adk https://www.microsoft.com/en-us/download/details.aspx?id=30652 安装 C:\Program Files (x86)\Windo ...

  10. cassandra 常见问题

    摘要 本文主要介绍在部署cassandra集群以及使用cassandra过程中遇到的一些问题. 文章只发布在CSDN 和个人站点 更多nosql文章可以访问stone fang 个人主页 正文 Q1: ...