java学习之路----对spring的初步研究-----你看了这个都不懂什么叫IOC,我就。。。。

来源:互联网 发布:九阴御姐女捏脸数据 编辑:程序博客网 时间:2024/05/11 01:38
学习Spring

               在学习Spring 的时候,我们先不直接去学,我们先来模拟一下Spring的一些功能,然后再去学,这样就比好容易理解

          1.建立一个项目。。。名字叫springTest_IOC(这样取名的目的是为了直接明了,看见标题就知道这个是干什么的)

          2.创建了一个项目,第一步不是去考虑用什么设计模式或者其他,首先肯定要用一个实体,我们先来建立一个用户实体

          package com.bjsxt.model;

public class User {
     private String userName;
     private String password;
     public String getUserName() {
           return userName ;
     }
     public void setUserName(String userName) {
           this.userName = userName;
     }
     public String getPassword() {
           return password ;
     }
     public void setPassword(String password) {
           this.password = password;
     }
     
     
}

3.我们应该分层
               一般有这几层:model(实体层),service(服务层,控制层),dao(数据库管理层,数据交换层),一般又把service分为service(应用接口层)和serviceImpl(应用实现层),dao也同样dao和daoImpl
源码:
package com.test.dao;

import com.test.model.User;
public interface UserDAO {
     public void save(User u);

}

package com.test.dao.Impl;
import com.test.dao.UserDAO;
import com.test.model.User;
public class UserDAOImpl implements UserDAO{

     @Override
     public void save(User u) {
          System.out.println( "save user" );
          
     }

}

package com.test.service;

import com.test.dao.UserDAO;
import com.test.dao.Impl.UserDAOImpl;
import com.test.model.User;

public class UserService {
     private UserDAO userDAO= new UserDAOImpl();
     
     
     
     
     public UserDAO getUserDA0() {
           return userDA0 ;
     }
     public void setUserDAO(UserDAO userDAO) {
           this.userDAO = userDAO;
     }

     public void addUser(User user ){
           userDAO.save(user);
          
     };

}



4.spring 读取文件时通过*.xml格式的文件来读取的
               我们首先来看先怎样读取文件
          
xml文件
<?xml version= "1.0" encoding ="UTF-8"?>
<result>
     <value >
           <no> A1234</ no>
           <addr> 成都</addr >
     </value >
     <value >
           <no> B1234</ no>
           <addr> 上海</addr >
     </value >
</result>


我们可以通过四种方法来读取xml文件

这里的xml文件需要注意的是:如果你发现你复制一段xml文件到xml里面去,却没有变色,则说明这段xml文件有误

     我这里先介绍一种JDOM
  JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一个Java特定模型,JDOM一直得到大力推广和促进。正在考虑通过“Java规范请求JSR-102”将它最终用作“Java标准扩展”。从2000年初就已经开始了JDOM开发。

    JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。

    JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)Java/XML问题”(根据学习曲线假定为20%)。JDOM对于大多数Java/XML应用程序来说当然是有用的,并且大多数开发者发现API比DOM容易理解得多。JDOM还包括对程序行为的相当广泛检查以防止用户做任何在XML中无意义的事。然而,它仍需要您充分理解XML以便做一些超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习DOM或JDOM接口都更有意义的工作。

    JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入XML文档(尽管它还可以将以前构造的DOM表示作为输入)。它包含一些转换器以将JDOM表示输出成SAX2事件流、DOM模型或XML文本文档。JDOM是在Apache许可证变体下发布的开放源码。



代码:

import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;


public class MyXMLReader {
     
     public static void main(String[] args)throws Exception {
               long lasting=System. currentTimeMillis();
              SAXBuilder builder= new SAXBuilder();
              
              Document doc=builder.build(MyXMLReader.class .getClassLoader().getResourceAsStream("text.xml")); //读取文件
              
              Element foo=doc.getRootElement(); //获取根元素
              
              System. out.println(foo);
               List allChildren=foo.getChildren();//获取所有的子元素
               for(int i=0;i<allChildren.size();i++){
                   System. out.println("号码" +((Element)allChildren.get(i)).getChild("no").getText());
                   System. out.println("地址" +((Element)allChildren.get(i)).getChild("addr").getText());
              }
              
     }
}

结果:
[Element: <result/>]
号码A1234
地址成都
号码B1234
地址上海

 5.加测试,怎么样加喃?
               第一,选择你要测试的类,右键-->New-->Juint test-->选择Junit 4--->finish---最好建立一个包叫测试包,然后把测试方法统一的放到里面去。

源码:package com.test.test;

import static org.junit.Assert.*;

import org.junit.Test;

public class UserServiceTest {

     @Test
     public void testAddUser() {
           fail("Not yet implemented");
     }

}
6.写自己的测试方法(修改上面的测试方法)
public class UserServiceTest {

     @Test
     public void testAddUser() {
     UserService service= new UserService();
     User user= new User();
     service.addUser(user);
     
     }

}
结果:
save user

7.下面我们来模仿spring的xml配置

我们来建立一个beans.xml文件

          源码:
<beans>
          
<!-- class 是全路径,包名加类名 -->
           <bean id= "u" class="com.test.dao.impl.UserDAOImpl" >
           </bean>
          
          <!--
          <bean id="userService" class="com.test.service.UserService">
              <property name="userDAO" bean="u"/>
          </bean>
           -->
</beans>

8.我们来建立一个spring的类,主要是为了模拟spring。在用这个类来实现一个beanFactory(bean工厂)接口。

我们在做这一步的时候也要修改UseeService的源码:

修改:

public class UserService {
     //private UserDAO userDao=new UserDAOImpl();原来是这样的
     
     private UserDAO userDao; //现在是这样,通过配置文件来实例化
     
     
     public UserDAO getUserDao() {
           return userDao ;
     }
     public void setUserDao(UserDAO userDao) {
           this.userDao = userDao;
     }

     public void addUser(User user ){
           userDao.save(user);
          
     };

}





源码:

package com.test.spring;

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 com.test.util.MyXMLReader;

public class ClassPathXmlApplicationContext implements BeanFactory{
           private Map<String, Object> beans =new HashMap<String,Object>();//容器,用户来装bean
     
     
     
     public ClassPathXmlApplicationContext() throws Exception{
          SAXBuilder builder= new SAXBuilder();
          
          Document doc=builder.build(MyXMLReader.class .getClassLoader().getResourceAsStream("beans.xml")); //读取文件
          
          Element root=doc.getRootElement(); //获取根元素
          
          System. out.println(root);
           List allChildren=root.getChildren();//获取所有的子元素
          
           for(int i=0;i<allChildren.size();i++){
              Element element=(Element)allChildren.get(i);//获取一个子元素
              String id=element.getAttributeValue("id" );//子元素的属性id
              String clazz=element.getAttributeValue("class" );
              System. out.println(id+":" +clazz);
              
              Object o=Class.forName(clazz).newInstance(); //通过反射来产生一个实体
              
               beans.put(id, o); //放入bean中
              
          }
          
     }



     @Override
     public Object getBean(String name) {//从beans中获取一个元素
          
           return beans .get(name);
     }

}
        

public class UserServiceTest {

     @Test
     public void testAddUser() throws Exception{
//   UserService service=new UserService();原来的做法
//   User user=new User();
//   service.addUser(user);
          BeanFactory beans= new ClassPathXmlApplicationContext();//实例化bean工厂
          UserService service= new UserService();
          UserDAO userDAO=(UserDAO)beans.getBean( "u");//通过工厂是实例化
          
          service.setUserDao(userDAO);
          
          User user= new User();
          service.addUser(user);
     
     }

}

  
运行:

结果:
[Element: <beans/>]
u:com.test.dao.impl.UserDAOImpl
save user

9.上面体现了一点SPring的好处,但是它的最好的还没体现,就是自动装配,上面的beans源码不是下面的一段被注释了嘛


< beans>
          
<!-- class 是全路径,包名加类名 -->
           < bean id= "u" class ="com.test.dao.impl.UserDAOImpl" >
           </ bean>
          
          <!--
          <bean id="userService" class="com.test.service.UserService">
              <property name="userDAO" bean="u"/>
          </bean>
           -->
</ beans>

红色的一段就是自动装配

修改代码:
//这个类取这样的名字都是为了模仿spring,因为spring里面也有这样的类

public class ClassPathXmlApplicationContext implements BeanFactory{
           private Map<String, Object> beans =new HashMap<String,Object>();//容器,用户来装bean
     
     
     
     public ClassPathXmlApplicationContext() throws Exception{
          SAXBuilder builder= new SAXBuilder();
          
          Document doc=builder.build(MyXMLReader.class .getClassLoader().getResourceAsStream("beans.xml")); //读取文件
          
          Element root=doc.getRootElement(); //获取根元素
          
          System. out.println(root);
           List allChildren=root.getChildren();//获取所有的子元素
          
           for(int i=0;i<allChildren.size();i++){
              Element element=(Element)allChildren.get(i);//获取一个子元素
              String id=element.getAttributeValue("id" );//子元素的属性id
              String clazz=element.getAttributeValue("class" );
              System. out.println(id+":" +clazz);
              
              Object o=Class.forName(clazz).newInstance(); //通过反射来产生一个实体
              
               beans.put(id, o); //放入bean中
                       //下面是才增加的方法
              for(Element propertyElement:(List<Element>)element.getChildren("property" )){
                   String name=propertyElement.getAttributeValue("name" );//取出name属性userDAO
                   String bean=propertyElement.getAttributeValue("bean" );//u
                   Object beanObject= beans.get(bean); //取出K为bean的值
                   
                   String methodName="set" +name.substring(0, 1).toUpperCase()+name.substring(1);//拼凑set方法名字
                   Method m=o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);//取出方法,传递参数(setUserDAO(UserDAOImpl实现了一个借口)就变成了setUserDAO(UserDAO))
                   
                   m.invoke(o, beanObject);
              }
          }
          
     }



     @Override
     public Object getBean(String name) {
          
           return beans .get(name);
     }

}




public class UserServiceTest {

     @Test
     public void testAddUser() throws Exception{
//   UserService service=new UserService();
//   User user=new User();
//   service.addUser(user);
          BeanFactory beans= new ClassPathXmlApplicationContext();//实例化bean工厂
//        UserService service=new UserService();
//        UserDAO userDAO=(UserDAO)beans.getBean("u");//通过工厂是实例化
//        
//        service.setUserDao(userDAO);
          
          UserService service=(UserService)beans.getBean("userService" );//现在直接工厂来实例化
          User user= new User();
          service.addUser(user);
     
     }

}
    
运行:
结果:
[Element: <beans/>]
u:com.test.dao.impl.UserDAOImpl
userService:com.test.service.UserService
save user
  


上面就是模拟spring的IOC的注入功能



这里解释一下什么叫IOC(DI)

        IOC:控制反转
例如:原来我们创建一个叫userDAO的实例是这样创建的

       UserDAO   userDAO=new UserDAO();

但是现在我们不用这样创建,我们只需要配置一下文件,让spring 来帮我们创建,本来是我们控制 创建,但是现在是spring 来控制创建,我们把控制权交给了spring 所以叫控制反转


         DI:依赖注入

比如:userService里面的userDAO是依赖容器帮我注入进来的。
     

这样做的好处:解耦和,就是修改代码很容易,只需要修改一下配置文件就OK了(也就是书上说的更加灵活)

    
原创粉丝点击