Spring IoC学习笔记

    xiaoxiao2025-05-27  10

    关于对于IOC的讲解本文就总结了一篇博客也是以防后边回看时找不到,写的很好赞一个:  http://zhangll98.iteye.com/blog/1551302 ,http://zhangll98.iteye.com/blog/1551301

    IOC(一)

    首先了解三层架构:界面层、业务逻辑层、DAO(data access object )层。每层含义就此略过。

      然后通过例子来理解IoC:

     假如我们描述回家,Dao层可以选择多种方法

    Java代码  (通过乘公交车方式)

    Public class ByBus{ Public void gohome(){ System.out.println(“坐公交车”); } } Java代码(通过自行车方法) Public   class  Cycle{     Public  void  gohome(){        System.out.println(“骑自行车”);     } } 业务逻辑层如果选择做公交车,那么:

    Java代码

    Public class GoHow{ Public void Gohome(){ ByBus byBus=new ByBus(); byBus.gohome(); } } 在GoHow类的设计中,回家的需求依赖于实际的ByBus对象,如果要将方法改为骑自行车则必须要修改GoHow这个类。

    DI----依赖倒转原则是:程序不应该依赖于实现,而是要依赖于抽象接口。

    所以如果我们在设计系统的过程中,对业务进行抽象,抽出一个接口:

    Java

    Public interface Ivehicle{ Public void gohome(); }

    然后ByBus和Cycle类都实现Ivehicle接口.

    Java 代码 Public class ByBus implements Ivehicle{ Public void gohome(){ System.out.println(“坐公交车”); } }Java 代码

    Public class Cycle imeplements Ivehicle{ Public void gohome(){ System.out.println(“骑自行车”); } }

    下面是重新设计GoHow类,回家的方法可设计为依赖Ivehicle接口,而不依赖于实际的ByBus和Cycle。

    Java 代码

    Public class GoHow{ Private Ivehicle vehicle; Public void setVehicle(Ivehicle vehicle){ This.vehicle=vehicle; } Public void Gohome(){ Vehicle.gohome(); } } 按照这样的设计方式,GoHow类是可以重用的。这样,在表示层,如果选择坐车回家,则可以写为:

    Java 代码

    GoHow goHow=new goHow(); go<span style="font-size: 16px;"></span>How.setVehicle(new ByBus); go<span style="font-size: 16px;"></span>How.Gohome(); 如果选择骑车回家,则写为:

    Java 代码

    GoHow goHow=new goHow(); goHow.setVehicle(new Cycle); goHow.Gohome();

    由此可以看出,无论底层的存储如何变化,对于GoWhere类来说都不用修改。修改的只是客户端。

    我们可以编写一个配置文件,在配置文件中对所需的对象进行配置,这样的话,连客户端的代码都不用修改,就可以方便的更换方法。

    其实,Spring的核心容器IOC就是提供的这样对象的配置管理功能。

    IOC(一)

    IOC(二)

    上篇文章介绍了Ioc和他的作用,简单的来讲,就是由容器控制程序之间的关系,而不是由我们手动编写控制实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转

    下面通过添加用户的小例子具体来看,首先配置Spring的环境

    1、加入spring的依赖包

    (1).SPRING_HOME/dist/spring.jar

    (2).SPRING_HOME/lib/log4j/log4j-1.2.14.jar

    (3).SPRING_HOME/lib/jakarta-commons/commons-logging.jar

    2、提供spring配置文件applicationContext.xml,一个典型的Spring项目需要创建一个或多个Bean配置文件,这些配置文件用于在Spring IOC容器里配置Bean,这个配置文件最好放在classpath目录下。

    3、提供log4j.properties配置文件

    创建项目,写Dao层接口IUserDao.java

    Java代码 public interface IUserDao {            public void InsertUser(String username,String password);  }  

    Dao接口的实现类 UserDaoImpl.java

    Java代码 public class UserDaoImpl implements IUserDao{           @Override           public void InsertUser(String username, String password){                             System.out.println("----UserDaoImpl --addUser----");           }   }  

    业务层接口IUserManager.java

    Java代码 public interface IUserManager {            public void addUser(String username,String password);  }  

    业务层接口的实现UserManagerImpl.java

    Java代码 public class UserManagerImpl implements IUserManager {        private IUserDao  userDao;        @Override        public void addUser(String username, String password) {                              userDao=new IUserDaoImpl();              userDao.InsertUser(username,password);        }   }  

    其实从这里就可以看出,业务层其实也是依赖了Dao层的具体实现,没有起到解耦的作用。

    Client.java

    Java代码 public classClient {      public static void main(String[] args) {           IUserManager usermanager=new UserManagerImpl();          userManager.addUser("wanghuan","password");      }  }  

    从客户端的代码里,我们也可以看出,跟上篇文章的例子是一样的,客户端也还是依赖于业务层的具体实现。接下来我们使用IOC容器。

    使用IOC容器很简单,就是将我们的对象放到配置文件里,让Spring知道,从而由Spring来帮我们管理。

    Spring 框架的 IOC 容器采用两种方法实现:

    (一)【setter方法注入】:通过 JavaBean的属性分配依赖性。

    (二)【构造器注入】:依赖性以构造函数的形式提供,不以 JavaBean 属性的形式公开。

    首先看setter方法注入,是IOC通过set方法将需要的对象注入。需要提供被注入对象的set方法。

    Java代码 Public  class  UserManagerImpl  implements  UserManager {      private  IUserDao  userDao;      //set方法         public void  setUserDao(IUserDao  userDao) {         this.userDao = userDao;      }      @Override      public void addUser(String username, String password) {                     //不需要实例化,直接可以使用        userDao.InsertUser(username,password);    }  }  

    重点是配置Spring的核心配置文件applicationContext.xml,在配置文件中配置上userDao的信息,使得IOC容器自己将UserDao对象注入到UserManagerImpl中。

    applicationContext.xml

    Html代码 <?xml version="1.0"encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"           xmlns:aop="http://www.springframework.org/schema/aop"           xmlns:tx="http://www.springframework.org/schema/tx"           xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd            http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  <!--id名字自己取,class表示他代表的类,如果在包里的话需要加上包名-->  <bean id="userManager"  class="UserManagerImpl" >      <!—property代表是通过set方法注入,ref的值表示注入的内容-->       <property  name="userDao"  ref="userDao"/>        </bean>    <bean id="userDao"  class="UserDaoImpl"/>    </beans>  

    这样我们就可以看出,业务层里只出现了Dao层的接口,是依赖于接口,而没有依赖于真正的实现。客户端对业务层的依赖是同样道理,可以只依赖业务层接口,通过IOC注入解决。

    下面看另一种通过构造器注入。这种方法不需要提供set方法,但需要提供构造方法。看代码:

    Java代码 Public  class  UserManagerImpl  implements  UserManager {      private  IUserDao  userDao;      //构造函数      public  UserManagerImpl(IUserDao  userDao) {         this.userDao = userDao;      }            @Override      public void addUser(String username, String password) {                      userDao.InsertUser(username,password);      }  }  

    配置文件也有不同:

    applicationContext.xml

    Html代码 <?xml version="1.0"encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"           xmlns:aop="http://www.springframework.org/schema/aop"           xmlns:tx="http://www.springframework.org/schema/tx"           xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd            http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  <bean id="userManager" class="UserManagerImpl" >      <!—constructor-arg代表是通过构造函数注入,ref的值表示注入的内容-->      <constructor-arg  ref="userDao "/>        </bean>    <bean id="userDao" class="UserDaoImpl"/>    </beans>  

    这两种注入方式,在客户端进行调用都是一样的。来看客户端代码:

    Java代码 public  class  Client{  public staticvoidmain(String[] args) {         /*这句话就不用出现了              IUserManager  usermanager=new UserManagerImpl();       */         //使用Spring的工厂将ioc容器中的对象取出         BeanFactory factory=newClassPathXmlApplicationContext("applicationContext.xml");         //依赖于接口,不会出现具体实现          IUserManager userManager=(IUserManager)factory.getBean("userManager");         userManager.addUser("wanghuan""password");      }  }  

    上篇文章的解耦过程于上文相同,都是将对象交与IOC容器管理,避免在程序中出现具体实现。通过代码我们可以看出IOC依赖注入的好处:

    1.对象之间的依赖关系,不由对象自身来负责,而是由容器依据配置文件动态建立,这样就很灵活,可配。

    2.采用依赖注入,模块之间一定是松散耦合的

    3.代码易维护易测试

    如果不使用框架,我们传统的写法一般是自己建立工厂或者用单例来处理业务层与Dao层,而使用了Spring,这些工作我们就都不用管了,而且每层的代码都很清楚。这样就使得真正的业务流程更明确了。

    转载请注明原文地址: https://ju.6miu.com/read-1299306.html
    最新回复(0)