zoukankan      html  css  js  c++  java
  • 依赖注入与控制反转

    记得大学开的有一门课是软件工程,而且还是两个学期,可能实践的机会少有的理论可能也只是记住的,比如软件设计的六大原则:单一原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、开闭原则,但没真正的理解明白为什么要这样。现在毕业也3年多了,项目也接触了几个,还有一些开源的框架,记得在中软给华为做外包时帮悍马其他组的支援了几天,当时还不知道ABP框架,对IOC也只是听说过,并没有理解。当接触了ABP框架才发现,原来当时做的项目就是采用的ABP框架啊。其实像这些设计原则、还有模式这些,主要还是为了系统的高内聚,低耦合。最近在自学javaweb,学javaweb自然不能少了spring,spring的核心就是IOC和AOP,今天主要来说下IOC——Inversion of Control/控制反转。

    一、依赖注入DI—Dependency Injection

    1.依赖

    在说IOC之前先聊下依赖注入,依赖注入可以分两部分一是依赖二是注入。那什么是依赖?不是我自身的但没有就活不下去,人没了空气、水、阳光,那就活不下去。所以人依赖空气、水、阳光。下面代码定义了一个Person和一个CleanAir的类,Person依赖CleanAir。

    package com.cyw.Model;
    
    public class Person {
    
        public Person(CleanAir air) {
            
            this.air = air;
        }
        CleanAir air;
    }
    View Code
    package com.cyw.Model;
    
    public class CleanAir {
    
    }
    View Code

     但是有这样一句话世界上唯一不变的就是变化。之前干净的空气不复存在,而Person依赖的不在是CleanAir,而是比CleanAir更有内涵的DirtyAir.如果还是按照上面的方式来,那就需要在增加一个DirtyAir类的同时,还要修改Person,这种强依赖有很大的弊端,一个地方变化引起其他地方也要修改,而且改变的只是Air,但Person也要改变。那怎么样能尽量减少修改的地方呢?于是面向接口的编程出现了。下面是先定义一个接口IAir,类CleanAir实现接口IAir,在Person中不在直接依赖CleanAir,而是依赖接口IAir,这样即使是DirtyAir也只需要修改给Person不同的Air就像了。

    package com.cyw.Model;
    
    public interface IAir {
    
    }
    View Code
    package com.cyw.Model;
    
    public class CleanAir implements IAir {
    
    }
    View Code
    package com.cyw.Model;
    
    public class Person {
    
        public Person(IAir air) {
            
            this.air = air;
        }
        IAir air;
    }
    View Code

    2.注入

    注入是啥?注入那它之前是没有的,而是塞给它。上面实例化Person的时候我们可以塞给它一个只要实现IAir接口的对象就可以,只是我们这是手动的给,这有点类似代理设计模式,要给代理设置具体对象。

    二、控制反转 IOC——Inversion Of Control

    上面依赖注入分两部分,当然控制反转也可分两部分。一是控制二是反转。

    1.控制

    像上面的不管是直接在Person中生命CleanAir属性还是创建一个接口,都是需要在程序New()一个对象出来,是程序控制Air.而IOC呢,它有专门的容器来管理这些对象,控制着他们的创建及生命周期,只要配置下,不用我们在new了。下次如果有CoolAir(冷空气),那只需要增加一个类CoolAir并实现IAir接口就行,然后在配置文件中配置一下,这样多省事。

    2.反转

    有反转那就有正转。上面的那种通过new来获取依赖的对象,是对象主动找依赖的对象,而IOC是管理着依赖的对象,然后给对象找它所对应的依赖的对象并注入。获取依赖对象的方式改变了,一个是主动一个是被动的。而Spring就是提供了自动注入依赖的功能。

    三、个人理解

    依赖注入手动注入依赖也算是依赖注入,控制反转呢算是自动注入依赖。手动注入还是需要new来创建对象,还是适应不了以后的变化,控制反转算是更加包容,不需要new创建,只要实现某个接口,IOC会自动注入。如果再往下一步思考,IOC配置的依赖在XML中,Xml中保存的内容都可以理解为字符串,怎么让字符串转换成对象呢,那就需要用到反射。其实这些不管是Java还是C#,思想都是一样的,不管那门语言,只要理解了思想,学习起来也不难,很容易就能上手。

     四、Spring中使用Ioc的demo

    上周四写完觉得不完美,上面基本没代码,最好有demo,操作一下,这样才好,所以计划着周六也就是今天上午来看下Spring的Ioc,可计划赶不上变化,买的洗衣机到货了,又是收快递又是联系售后来安装,一个上午就这么没了,所以趁着下午来看下spring。

    1.创建maven project,选择的是quickstart

    2.创建接口层

    这里创建了两个一个数据层一个服务层的接口层,并创建了两个接口用来演示

    IDao

    package Cuiyw.Spring.IDao;
    
    public interface IDao {
    
        public String sayHello(String name);
    }
    View Code

    IService

    package Cuiyw.Spring.IService;
    
    public interface IService {
    
        public void service(String name);
    }
    View Code

     3.创建属性层

    根据上面的接口层创建了两个实现层,并实现了上面的接口

    DaoImpl

    package Cuiyw.Spring.Dao;
    
    import java.util.Calendar;
    
    import Cuiyw.Spring.IDao.IDao;
    
    public class DaoImpl implements IDao{
    
        public String sayHello(String name) {
            int hour=Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
            if(hour<6) return "凌晨早,"+name;
            if(hour<12)return "早上好,"+name;
            if(hour<13)return "中午好,"+name;
            if(hour<18)return "下午好,"+name;
            return "晚上好,"+name;
                
        }    
    }
    View Code

    ServiceImpl

    package Cuiyw.Spring.Service;
    
    import Cuiyw.Spring.IDao.IDao;
    import Cuiyw.Spring.IService.IService;
    
    public class ServiceImpl implements  IService{
    
        private IDao dao;
        public IDao getDao() {
            return dao;
        }
        public void setDao(IDao dao) {
            this.dao = dao;
        }
        public void service(String name) {
            System.out.println(dao.sayHello(name));
        }
    }
    View Code

    4.引入spring

    使用maven引入也很容易,在pom.xml中配置一下就可以了。

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>Cuiyw</groupId>
      <artifactId>SpringAop</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>SpringAop</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          <spring.version>5.0.0.RELEASE</spring.version>
      </properties>
    
      <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>
    View Code

    5.Ioc配置

    要想让spring自动注入,那也得让spring知道要注入的是什么。新建ApplicationContext.xml并进行下面的配置,具体配置是什么意思,会在以后慢慢介绍。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="DaoImpl" class="Cuiyw.Spring.Dao.DaoImpl"></bean>
    <bean id="ServiceImpl" class="Cuiyw.Spring.Service.ServiceImpl">
    <property name="dao" ref="DaoImpl"></property>
    </bean>
    </beans>
    View Code

    6.调用

    在mian中通过xml获取bean对象,然后调用里面的方法。

    package Cuiyw.SpringAop;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import Cuiyw.Spring.IService.IService;
    
    public class App 
    {
        public static void main( String[] args )
        {
            ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"ApplicationContext.xml"});
            BeanFactory factory=context;
            IService service=(IService)factory.getBean("ServiceImpl");
            service.service("Cuiyw"); 
        }
    
    }
    View Code

    7.项目结构

    8.运行main方法

    上面几步算是简单的实现了spring的ioc,但只是大概简单的了解,并未深入。我们在mian中并为进行new创建,而是通过spring来自动填充,找到对应的依赖注入给service。

  • 相关阅读:
    Java实现 LeetCode 101 对称二叉树
    编写在浏览器中不弹出警告的ActiveX控件
    ocx控件避免弹出警告的类--2
    修改注册表添加IE信任站点及启用Activex控件
    让动态创建的ActiveX控件响应Windows消息
    source code analyzer 功能强大的C/C++源代码分析软件 Celerity CRACK 破解版
    分析函数调用关系图(call graph)的几种方法
    用CodeViz绘制函数调用关系图(call graph)
    C++的辅助工具介绍
    局域网入侵的方法
  • 原文地址:https://www.cnblogs.com/5ishare/p/7774624.html
Copyright © 2011-2022 走看看