spring Ioc

转自:http://blog.csdn.net/javastudyr/article/details/17055743

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值