提到Spring框架,首先要知道一个概念:面向接口编程。首先要抽象编程的实体类,首先要编辑其属性,例如前一篇的两个类,涉及到到给不同的类分责任,例如添加用户的功能是不能放在User实体类中的,否则每一次添加用户都会面临再生成一个user。所以在表现层和实体数据层中间就加入一个UserService层(类的管理层),再加上一个UserDAO数据库管理层。
UserService是对外的接口,UserDAO提供底层数据库的屏蔽。在调用的过程中,UserService应当保存一个UserDAO的引用,Service层除了完成存储数据之外,能完成认证的作用(负责业务逻辑),例如登陆和注册都在此实现。
UserDAO操作的实际上是MySQL的代码,但是假如要更换数据库的话,办法就是面向抽象编程,就将UserDAO改为接口类型,不写实现方法,根据不同的数据库实现UseDAO。
由于有很多比较固定的东西,所以就可以使用框架,在这里就要用框架进行就要学配置,配置文件使用了xml,习惯xml读取数据的方式。
1、xml语法学习
由配置好的test.xml文件作为数据源,xml文件可以用于保存数据之间的层级关系,编写Sample.java来读取
代码如下:
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<HD>
<disk name="C">
<capacity>8G</capacity>
<directories>200</directories>
<files>1500</files>
</disk>
<disk name="D">
<capacity>16G</capacity>
<directories>500</directories>
<files>3000</files>
</disk>
</HD>
Sample.java
import java.util.*;
import org.jdom2.*;
import org.jdom2.input.SAXBuilder;
public class Sample {//访问xml文件内容
public static void main(String[] args) throws Exception{
SAXBuilder sb = new SAXBuilder();//默认的解析器
Document doc = sb.build(Sample.class.getClassLoader().getResourceAsStream("/test.xml"));//构造文档对象
Element root = doc.getRootElement();//获取根元素
List list=root.getChildren("disk");//获取所有名字为disk的元素
for(int i=0; i<list.size(); i++){
Element element = (Element) list.get(i);//强制转换
String name = element.getAttributeValue("name");
String capacity = getChildText("capacity");
String directories = element.getChildText("directories");
String files = element.getChildText("files");
System.out.println("磁盘信息");
System.out.println("分区盘符"+name);
System.out.println("分区容量"+capacity);
System.out.println("目录数"+directories);
System.out.println("文件数"+files);
System.out.println("-----------------------------");
}
}
}
最终结果:
Sample文件思路:使用了Jdom内置的解析器,然后从根元素<HD>开始,逐级读入<disk>等属性
接下来要完成的内容:
2、写一个JUnit的测试文件:
1、建立一个JUnit的文件(一定要注意要和被测试的类放在同一个包里),选择测试方法。例如建立TestUserService,测试方法为user.addUser(User user)
2、在类开头添加@Test标注,主要目的是测试是否该方法是否被调用
代码如下:
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<HD>
<disk name="C">
<capacity>8G</capacity>
<directories>200</directories>
<files>1500</files>
</disk>
<disk name="D">
<capacity>16G</capacity>
<directories>500</directories>
<files>3000</files>
</disk>
</HD>
Sample.java
import java.util.*;
import org.jdom2.*;
import org.jdom2.input.SAXBuilder;
public class Sample {//访问xml文件内容
public static void main(String[] args) throws Exception{
SAXBuilder sb = new SAXBuilder();//默认的解析器
Document doc = sb.build(Sample.class.getClassLoader().getResourceAsStream("/test.xml"));//构造文档对象
Element root = doc.getRootElement();//获取根元素
List list=root.getChildren("disk");//获取所有名字为disk的元素
for(int i=0; i<list.size(); i++){
Element element = (Element) list.get(i);//强制转换
String name = element.getAttributeValue("name");
String capacity = getChildText("capacity");
String directories = element.getChildText("directories");
String files = element.getChildText("files");
System.out.println("磁盘信息");
System.out.println("分区盘符"+name);
System.out.println("分区容量"+capacity);
System.out.println("目录数"+directories);
System.out.println("文件数"+files);
System.out.println("-----------------------------");
}
}
}
运行结果:调用addUser的内容,返回“存储成功”字样
3、在学习了xml和JUnit之后,编写Spring的配置文件bean.xml
想法就是把bean读出来,放到userDao变量中去,从配置文件中读出来,能提高灵活性
模拟Spring中的类ClassPathXmlApplicationContext(置于classpath中的XML应用的上下文),相当于把new出来的东西都放到一个配置文件中
程序启动,把配置文件中的bean都初始化,然后放到容器中,用的时候,从容器中取出来。
使用注解的优缺点:
疑问:使用getClass的作用,getCLass().getClassLoader.getResourceAsStream("文件名")
模拟Spring建立了一个ClassPathXmlApplicationContext的类,读取xml文件中的bean的内容
代码如下:
Spring的重要功能,直接在配置文件中把两个对象的关系设定好,bean标签下的property指的是set方法,UserService中生成了UserDao,所以需要写的方法是
<bean id="u" class="com.test.msg.dao.impl.UserDaoImpl">
<bean id="userService" class="com.test.msg.service.UserService">
<property name="userDao" bean="u">动态装配,就是可以把属性给注入进来,注入的概念
实现的方法:
package com.test.msg.spring;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
public class ClassPathXmlApplicationContext implements com.test.msg.spring.BeanFactory{
private Map<String, Object> beans = new HashMap<String, Object>();
public ClassPathXmlApplicationContext() throws Exception {
//解析XML文件,要设置解析器
SAXBuilder sb = new SAXBuilder();//设置解析器
Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("bean.xml"));
Element root=doc.getRootElement();//获取根元素、
List list = root.getChildren("bean");
for(int i=0; i<list.size(); i++){
Element element=(Element) list.get(i);
String id = element.getAttributeValue("id");
String clazz = element.getAttributeValue("class");
System.out.println(id+ ":"+ clazz);
Object o = Class.forName(clazz).newInstance();//新生成一个类
beans.put(id, o);
for(Element propertyElement: (List<Element>)element.getChildren("property")){
//如果bean下面的子元素下面有property,把bean的property装入list中
String name = propertyElement.getAttributeValue("name");
String bean = propertyElement.getAttributeValue("bean");
Object beanObject = beans.get(bean);//UserDaoImpl instance
String methodName= "set" + name.substring(0,1).toUpperCase() + name.substring(1);
System.out.println("method name=" + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject);
}
}
}
@Override
public Object getBeans(String name) {
// TODO Auto-generated method stub
return null;
}
}
这段代码比较难懂