天天看点

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

学习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了(也就是书上说的更加灵活)