控制反转_控制反转ioc - CSDN
精华内容
参与话题
  • 有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活 IoC很好的体...

    ​ IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活

    IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找

    ​ DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

    理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

    ●谁依赖于谁:当然是应用程序依赖于IoC容器;

    ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;

    ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;

    ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

    本质上IoC和DI是同一思想下不同维度的表现 ,用通俗的话说就是,IoC是bean的注册,DI是bean的初始化

    源码实现原理:

    参考文章:

    https://blog.csdn.net/lisongjia123/article/details/52129340

    https://blog.csdn.net/lisongjia123/article/details/52134396

    上面的文章根据源码进行分析,过程比较复杂,因此我进行了一个高度的抽象,希望来描述它们的实现原理:

    简单的IoC控制反转代码实现,定义测试的Bean,Student和Teacher

    public class Teacher {
        private String tName;
        // ....get set方法省略
    }
    ​
    public class Student {
        private String name;
        private String age;
        private Teacher teacher;
        // ....get set方法省略
    }

    BeanDefined类,对bean的描述类:

    public class BeanDefined {
        
        // bean的id
        private String beanId;
        
        // bean的文件路径
        private String classPath;
    ​
        public String getBeanId() {
            return beanId;
        }
        public void setBeanId(String beanId) {
            this.beanId = beanId;
        }
        public String getClassPath() {
            return classPath;
        }
        public void setClassPath(String classPath) {
            this.classPath = classPath;
        }
    }

    BeanFactory --- 生成Bean的容器类:

    public class BeanFactory {
        // 存放bean的集合
        private List<BeanDefined> beanDefinedList; 
    ​
        public List<BeanDefined> getBeanDefinedList() {
            return beanDefinedList;
        }
    ​
        public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
            this.beanDefinedList = beanDefinedList;
        }
    ​
        /**
         * 获取bean实例
         *
         * @param beanId
         * @return
         * @throws Exception
         */
        public Object getBean(String beanId) throws Exception {
            Object instance;
            for (BeanDefined bean : beanDefinedList) {
                if (beanId.equals(bean.getBeanId())) {
                    String classPath = bean.getClassPath();
                    Class classFile = Class.forName(classPath);
                    // 在spring中调用默认的构造方法,这里我们也调用默认的构造方法
                    instance = classFile.newInstance();
                    return instance;
                }
            }
            return null;
        }
    }

    测试类:

    public class Test {
        public static void main(String[] args) throws Exception {
            // 1、声明注册bean
            BeanDefined beanObj = new BeanDefined();
            beanObj.setBeanId("student");
            beanObj.setClassPath("com.pojo.Student");
            List<BeanDefined> beanList = new ArrayList<BeanDefined>();
            beanList.add(beanObj);
    ​
            // 2、声明一个BeanFactory,类似于Spring中的ApplicationContext
            BeanFactory factory = new BeanFactory();
            factory.setBeanDefinedList(beanList);
    ​
            // 3、开发人员向BeanFactory索要实例对象
            Student student = (Student) factory.getBean("student");
            System.out.println(student);
        }
    }

    测试结果截图:

    从代码里面可以看出来,我们是没有直接new学生类的,主要的思想是,定义BeanDefined对象添加进集合中,通过BeanFactory为我们生产出需要的对象,其中用到的核心技术就是:反射

     

    用代码实现简单的依赖注入:

    BeanDefined类需要做一定的修改:

    public class BeanDefined {
        // bean的id
        private String beanId;
        // bean的文件路径
        private String classPath;
        // 存放属性的集合
        private Map<String, String> propertyMap = new HashMap<>(); 
        
        // ....省略set和get方法
    }

    BeanFactory类需要做如下的修改:

    public class BeanFactory {
    ​
        // 存放bean的集合
        private List<BeanDefined> beanDefinedList; 
    ​
        public List<BeanDefined> getBeanDefinedList() {
            return beanDefinedList;
        }
    ​
        public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
            this.beanDefinedList = beanDefinedList;
        }
    ​
        /**
         * 获取bean实例
         *
         * @param beanId
         * @return
         * @throws Exception
         */
        public Object getBean(String beanId) throws Exception {
            Object instance;
            for (BeanDefined bean : beanDefinedList) {
                if (beanId.equals(bean.getBeanId())) {
                    String classPath = bean.getClassPath();
                    Class classFile = Class.forName(classPath);
                    // 在spring中调用默认的构造方法,这里我们也调用默认的构造方法
                    instance = classFile.newInstance();
                    // 获取bean的属性配置
                    Map<String, String> propertyMap = bean.getPropertyMap();
                    if(propertyMap !=null) {
                        setValue(instance, classFile, propertyMap);
                    }
                    return instance;
                }
            }
            return null;
        }
    ​
        /**
         * 依赖注入的方法
         *
         * @param instance    当前的实例对象
         * @param classFile   当前实例对象所关联的类文件
         * @param propertyMap 属性
         */
        public void setValue(Object instance, Class classFile, Map<String, String> propertyMap) throws Exception {
            if(propertyMap !=null ) {
                /***
                 * 获取map的所有属性配置
                 */
                Set<String> proper = propertyMap.keySet();
                for(String string : proper) {
                    // 通过字符串拼接,拼出set方法名
                    char c = string.toUpperCase().charAt(0);
                    String s = "set" + c + string.substring(1);
                    // 获取当前属性的类型
                    Field field = classFile.getDeclaredField(string);
                    // 根据属性的类型进行调用
                    Method m = instance.getClass().getMethod(s, field.getType());
                    /**
                     * 直接try注入普通类型,或者catch注入bean工厂中的其他类型
                     */
                    try {
                        m.invoke(instance, propertyMap.get(string));
                    } catch (Exception e) {
                        m.invoke(instance, getBean(propertyMap.get(string)));
                    }
                }
            }
        }
    }

    测试类代码需要做如下修改:

    public class Test {
        public static void main(String[] args) throws Exception {
            // 1、声明注册bean
            BeanDefined beanObj = new BeanDefined();
            beanObj.setBeanId("student");
            beanObj.setClassPath("com.pojo.Student");
            // 设置 property
            Map<String, String> propertyMap = beanObj.getPropertyMap();
            propertyMap.put("name", "kxm");
            propertyMap.put("age", "22岁");
            propertyMap.put("teacher", "teacher");
            // 注册教师类
            BeanDefined teacher = new BeanDefined();
            teacher.setBeanId("teacher");
            teacher.setClassPath("com.pojo.Teacher");
            List<BeanDefined> beanList = new ArrayList<BeanDefined>();
            beanList.add(beanObj);
            beanList.add(teacher);
            
            // 2、声明一个BeanFactory,类似于Spring中的ApplicationContext
            BeanFactory factory = new BeanFactory();
            factory.setBeanDefinedList(beanList);
    ​
            // 3、开发人员向BeanFactory索要实例对象
            Student student = (Student) factory.getBean("student");
            System.out.println(student);
        }
    }

    测试结果截图:

     

    仔细分析代码,我们可以发现,没有显示的new对象,也没用用set方法去赋值,但是模拟出来了依赖注入的效果,这也是Spring中依赖注入的原理,当然这里是最简单的实现,剩下的路,还需要骚年你自己走哇~

    展开全文
  • 控制反转

    2016-08-23 11:39:37
    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI...

    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。

    应用控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。所以,控制反转是,关于一个对象如何获取他所依赖的对象的引用,这个责任的反转。


    设计模式

    Interface Driven Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:AInterface a = new AInterfaceImp(); 这样一来,耦合关系就产生了,如:

    classA
    {
        AInterface a;
    
        A(){}
    
        AMethod()//一个方法
        {
            a = new AInterfaceImp();
        }
    }

    Class A与AInterfaceImp就是依赖关系,如果想使用AInterface的另外一个实现就需要更改代码了。当然我们可以建立一个Factory来根据条件生成想要的AInterface的具体实现,即:

    InterfaceImplFactory
    {
       AInterface create(Object condition)
       {
          if(condition = condA)
          {
              return new AInterfaceImpA();
          }
          else if(condition = condB)
          {
              return new AInterfaceImpB();
          }
          else
          {
              return new AInterfaceImp();
          }
        }
    }

    表面上是在一定程度上缓解了以上问题,但实质上这种代码耦合并没有改变。通过IoC模式可以彻底解决这种耦合,它把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中,这可能就是“依赖注入”说法的来源了。

    IoC模式,系统中通过引入实现了IoC模式的IoC容器,即可由IoC容器来管理对象的生命周期、依赖关系等,从而使得应用程序的配置和依赖性规范与实际的应用程序代码分开。其中一个特点就是通过文本的配置文件进行应用程序组件间相互关系的配置,而不用重新修改并编译具体的代码。

    可以把IoC模式看做是工厂模式的升华,可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java 的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

    IoC中最基本的Java技术就是“反射”编程。反射又是一个生涩的名词,通俗的说反射就是根据给出的类名(字符串)来生成对象。这种编程方式可以让对象在生成时才决定要生成哪一种对象。反射的应用是很广泛的,像Hibernate、Spring中都是用“反射”做为最基本的技术手段。

    在过去,反射编程方式相对于正常的对象生成方式要慢10几倍,这也许也是当时为什么反射技术没有普遍应用开来的原因。但经SUN改良优化后,反射方式生成对象和通常对象生成方式,速度已经相差不大了(但依然有一倍以上的差距)。

    展开全文
  • 控制反转的通俗解释

    万次阅读 2011-11-09 13:06:15
    套用好莱坞的一句名言就是:你呆着别动,到时我会找你。 什么意思呢?就好比一个皇帝和太监 有一天皇帝想幸某个美女,于是跟太监...这就是控制反转,而把美女送到皇帝的寝宫里面去就是注射 太监就是是框架里面的

    套用好莱坞的一句名言就是:你呆着别动,到时我会找你。
    什么意思呢?就好比一个皇帝和太监
    有一天皇帝想幸某个美女,于是跟太监说,今夜我要宠幸美女
    皇帝往往不会告诉太监,今晚几点会回宫,会回哪张龙床,他只会告诉太监他要哪位美女
    其它一切都交由太监去安排,到了晚上皇帝回宫时,自然会有美女出现在皇帝的龙床上
    这就是控制反转,而把美女送到皇帝的寝宫里面去就是注射
    太监就是是框架里面的注射控制器类BeanFactory,负责找到美女并送到龙床上去
    整个后宫可以看成是Spring框架,美女就是Spring控制下的JavaBean
    而传统的模式就是一个饥渴男去找小姐出台
    找领班,帮助给介绍一个云云,于是领班就开始给他张罗
    介绍一个合适的给他,完事后,再把小姐还给领班,下次再来
    这个过程中,领班就是查询上下文Context,领班的一个职能就是给客户找到他们所要的小姐
    这就是lookup()方法,领班手中的小姐名录就是JNDI//Java Naming and Directory Interface
    小姐就是EJB,饥渴男是客户端,青楼是EJB容器
    看到区别了么?饥渴男去找小姐出台很麻烦,不仅得找,用完后还得把小姐给还回去
    而皇帝爽翻了,什么都不用管,交给太监去处理,控制权转移到太监手中去了
    而不是皇帝,必要时候由太监给注射进去就可以了
    看到Spring的美妙了吧,Spring还提供了与多个主流框架的支持
    可以和其它开源框架集成

     

     

    IoC,用白话来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也
    就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。
    USB接口例子:
    笔记本电脑与外围存储设备通过预先指定的一个接口(USB)相连,对于笔记本而言,
    只是将用户指定的数据发送到USB接口,而这些数据何去何从,则由当前接入的USB设备决定。在USB
    设备加载之前,笔记本不可能预料用户将在USB接口上接入何种设备,只有USB设备接入之后,这种设
    备之间的依赖关系才开始形成。
    对应上面关于依赖注入机制的描述,在运行时(系统开机,USB 设备加载)由容器(运行在笔记本
    中的Windows操作系统)将依赖关系(笔记本依赖USB设备进行数据存取)注入到组件中(Windows
    文件访问组件)。
    理解:
    传统模式中是类和类之间直接调用,所以有很强的耦合度,程序之间的依赖关系比较强,后期维护时牵扯的比较多。
    IOC,用配置文件(XML)来描述类与类之间的关系,由容器来管理,降低了程序间的耦合度,程序的修改可以通过简单的配置文件修改来实现

    面向切面编程AOP

    Aspect Oriented Programming(面向切面编程),可以 通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一 添加功能的一种技术。

     

     

    6.2.1  IOC原理

    IoC,直观地讲,就是容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在。控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。IoC还有另外一个名字—“依赖注入Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象地说,即由容器动态地将某种依赖关系注入到组件之中。

    下面通过一个生动形象的例子介绍控制反转

    比如,一个女孩希望找到合适的男朋友,如图6-2所示,可以有3种方式,即青梅竹马、亲友介绍、父母包办。

     

    1种方式是青梅竹马,如图6-3所示。

    通过代码表示如下。

    public class Girl {

      void kiss(){

        Boy boy = new Boy();

      }

    }

     

    2种方式是亲友介绍,如图**所示。

    通过代码表示如下。

    public class Girl {

      void kiss(){

        Boy boy = BoyFactory.createBoy();

      }

    }

    3种方式是父母包办,如图6-5所示。

     

    通过代码表示如下。

    public class Girl {

      void kiss(Boy boy){

        // kiss boy

       boy.kiss();

      }

    }

    哪一种为控制反转IoC呢?虽然在现实生活中我们都希望青梅竹马,但在Spring世界里,选择的却是父母包办,它就是控制反转,而这里具有控制力的父母,就是Spring所谓的容器概念。

    典型的IoC可以如图6-6所示。

     

    IoC3种依赖注入类型如下。

    1种是通过接口注射,这种方式要求我们的类必须实现容器给定的一个接口,然后容器会利用这个接口给我们这个类注射它所依赖的类。

    public class Girl implements Servicable {

      Kissable kissable;

      public void service(ServiceManager mgr) {

        kissable = (Kissable) mgr.lookup("kissable");

      }

      public void kissYourKissable() {

        kissable.kiss();

      }

    }

     

    <container>

      <component name="kissable" class="Boy">      

        <configuration> … </configuration>

      </component>

      <component name="girl" class="Girl" />

    </container>

    2种是通过setter方法注射,这种方式也是Spring推荐的方式

    public class Girl {

      private Kissable kissable;

      public void setKissable(Kissable kissable) {

        this.kissable = kissable;

      }

      public void kissYourKissable() {

        kissable.kiss();

      }

    }

     

    <beans>

      <bean id="boy" class="Boy"/>

      <bean id="girl" class="Girl">

        <property name="kissable">

          <ref bean="boy"/>

        </property>

      </bean>

    </beans>

    3种是通过构造方法注射类,这种方式Spring同样给予了实现,它和通过setter方式一样,都在类里无任何侵入性,但是,不是没有侵入性,只是把侵入性转移了,显然第1种方式要求实现特定的接口,侵入性非常强,不方便以后移植。

    public class Girl {

      private Kissable kissable;

      public Girl(Kissable kissable) {

        this.kissable = kissable;

      }

      public void kissYourKissable() {

        kissable.kiss();

      }

    }

     

    PicoContainer container = new DefaultPicoContainer();

    container.registerComponentImplementation(Boy.class);

    container.registerComponentImplementation(Girl.class);

    Girl girl = (Girl) container.getComponentInstance(Girl.class);

    girl.kissYourKissable();

    展开全文
  • 依赖注入和控制反转的理解,写的太好了。

    万次阅读 多人点赞 2015-08-11 17:53:22
    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring...

     学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解。

    一、分享Iteye的开涛对Ioc的精彩讲解

      首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文,原文地址:http://jinnianshilongnian.iteye.com/blog/1413846

    1.1、IoC是什么

      Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

      ●谁控制谁,控制什么传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)

      ●为何是反转,哪些方面反转了有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

      用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:

    图1-1 传统应用程序示意图

      当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2-2所示:

    图1-2有IoC/DI容器后程序结构示意图

    1.2、IoC能做什么

      IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

      其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

      IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

    1.3、IoC和DI

      DI—Dependency Injection,即“依赖注入”组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

      理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

      ●谁依赖于谁:当然是应用程序依赖于IoC容器

      ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源

      ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象

      ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

      IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”

      看过很多对Spring的Ioc理解的文章,好多人对Ioc和DI的解释都晦涩难懂,反正就是一种说不清,道不明的感觉,读完之后依然是一头雾水,感觉就是开涛这位技术牛人写得特别通俗易懂,他清楚地解释了IoC(控制反转) 和DI(依赖注入)中的每一个字,读完之后给人一种豁然开朗的感觉。我相信对于初学Spring框架的人对Ioc的理解应该是有很大帮助的。

    二、分享Bromon的blog上对IoC与DI浅显易懂的讲解

    2.1、IoC(控制反转)

      首先想说说IoC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。

      那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

    2.2、DI(依赖注入)

      IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

      理解了IoC和DI的概念后,一切都将变得简单明了,剩下的工作只是在spring的框架中堆积木而已。

    三、我对IoC(控制反转)和DI(依赖注入)的理解

      在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。

      所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

      这是我对Spring的IoC(控制反转)的理解。DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。

    四、小结

      对于Spring Ioc这个核心概念,我相信每一个学习Spring的人都会有自己的理解。这种概念上的理解没有绝对的标准答案,仁者见仁智者见智。如果有理解不到位或者理解错的地方,欢迎广大园友指正!

    展开全文
  • 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring...
  • IoC控制反转是什么意思?

    千次阅读 2018-06-28 20:58:36
    Spring最大的特点,相信大家在网上看了许多,都知道是控制反转(IOC),或者叫依赖注入(DI),那么究竟什么是控制反转,什么是依赖注入呢?IOC(inversion of control)控制反转模式;控制反转是将组件间的依赖关系...
  • 什么是控制反转

    2019-12-06 11:42:20
    第一次遇到控制反转(或IoC)时,可能会很混乱。 它是什么? 它解决什么问题? 什么时候合适,什么时候不合适?
  • 控制反转步骤

    2019-08-06 12:59:36
    控制反转步骤 ** 开门见山,这篇博客详细讲一讲这个控制反转的步骤,Let 's go       控制反转嘛,上篇博客已经介绍了,它是由容器创建对象,然后交给使用者。那么容器怎么搞,我们...
  • 学习Spring第一课,就是认识IOC控制反转,要了解它还真得花一些功夫。今天主要理解透彻它的真谛,而不仅限于表面。 上道小菜 public class BusinessService { private UserDao dao = new UserDao(); ...
  • C#之控制反转

    2018-08-03 11:59:12
    控制反转  控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency ...
  • Spring框架中IoC(控制反转)的原理

    万次阅读 多人点赞 2015-05-26 16:40:42
    即软件系统中对象之间的耦合,对象A和对象B之间有关联,对象B又和对象C有依赖关系,这样对象和对象之间有着复杂的依赖关系,所以才有了控制反转这个理论。 2.什么是控制反转(IoC): (1).IoC是Inver
  • 什么是IOC(控制反转)、DI(依赖注入)

    万次阅读 多人点赞 2019-07-25 09:44:16
    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring...
  • c# 依赖注入 控制反转

    2020-07-21 09:59:22
    控制反转 依赖注入的c#实现,很好的教程。
  • 控制反转和依赖注入

    2019-01-16 10:34:27
    但是当你了解之后,才发现有些术语你经常在使用,只是不知道这个术语而已,控制反转和依赖注入就是这样的术语名词,不禁让人想骂上一句MMP。(新手入行,错误的地方欢迎批评指正)2.示例在使用一个简单的示例来说明...
  • 详解spring的IOC控制反转和DI依赖注入

    千次阅读 2018-06-05 15:45:34
    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring...
  • 控制反转与依赖注入模式

    万次阅读 2014-06-27 22:55:01
    Java 社群近来掀起了一阵...人们用一个大而化之的名字来称呼这个模式:“控制反转”( Inversion of Control,IoC)。在本文中,我将深入探索这个模式的工作原理,给它一个更能描述其特点的名 字——“依赖注入”(De
  • IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection,简称DI)。 当一个类的实例需要另一个类的实例协助时,在传统的程序设计过程中,通常由调用者来创建被...
  • 控制反转,和依赖注入是同一个意思,我觉得应该重点去了解什么是依赖,而后控制反转、依赖注入就有体会了;关于依赖,可以查看UML相关的书籍,重点去看java对象之间的关系是怎样的,而所谓的依赖就是对象之间的一种...
  • 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来解释依赖注入这个概念。后来想一下,这些在面向对象开发过程中与依赖相关的诸多术语和概念实际情况下非常的抽象,因此独立成文也有就...
  • 依赖倒置、控制反转和依赖注入辨析   在《道法自然——面向对象实践指南》一书中,我们采用了一个对立统一的辩证关系来说明“模板方法”模式—— “正向依赖 vs. 依赖倒置”(参见:《道法自然》第15章[王...
1 2 3 4 5 ... 20
收藏数 110,572
精华内容 44,228
关键字:

控制反转