精华内容
下载资源
问答
  • 什么控制反转: 原本,一个对象A需要调用它的外部资源对象C时,需要直接在对象A内,创建对象C再对它进行方法的调用。控制反转就是对象需要调用外部资源时,不再通过创建对象C的方式主动调用资源,而是通过loC容器...

    什么是控制反转:

    原本,一个对象A需要调用它的外部资源对象C时,需要直接在对象A内,创建对象C再对它进行方法的调用。控制反转就是对象需要调用外部资源时,不再通过创建对象C的方式主动调用资源,而是通过loC容器获取一个C的实例,对象A被动的接收loC容器传递过来的外部资源。

    什么是依赖注入:

    DI容器将某个对象所需要的外部资源注入到某个对象

    两者联系:

    从上我们基本可以看出控制反转与依赖注入为同一件事的不同描述,只是她们的描述方向不一样。
    控制反转是从容器方面,容器控制应用程序的创建,并且为其提供需要调用的外部资源。
    依赖注入是从应用程序方面,应用程序依赖容器进行创建,并且注入它所需要的外部资源。

    展开全文
  • 依赖倒置,控制反转,依赖注入及Google Guice 1. 依赖倒置 依赖 字面意思事物之间具有的一种关系。在面向对象编程中我将其理解为一种对象之间引用的持有关系。任何系统都无法避免依赖,如果一个类或接口在系统中没有...

    依赖倒置,控制反转,依赖注入及Google Guice

    1. 依赖倒置

    依赖
    字面意思事物之间具有的一种关系。在面向对象编程中我将其理解为一种对象之间引用的持有关系。任何系统都无法避免依赖,如果一个类或接口在系统中没有被依赖,那么他们就不应该出现在系统之中。举个简单的例子说明依赖关系:师徒四人去西天取经。我们说说唐僧,他有个徒弟,其他的东西我们暂且忽略。如果把唐僧师徒一个具体类的话,他在收服了悟空之后应该有这样的依赖关系。

    one2one.png

    我们从唐僧角度考虑的话,他应该是依赖于悟空的,没有他,他可取不到经。那么我们可以说唐僧依赖于他的徒弟。

    在代码中,他们的关系如下:

    public class TangSeng {
      WuKong wuKong = new WuKong();
    }
    

    有了徒弟,唐僧就可以跟他愉快地取经了。中途遇到妖怪,也可以让徒弟去打妖怪了。

    public class TangSeng {
    
      WuKong wuKong = new WuKong();
    
      public void letsFight(String name) {
          wuKong.fight();
      }
    
    }
    

    那么问题了,唐僧在后面还会收徒弟。当他收齐之后情况应该是这样的。
    one2four.png

    这里他就依赖于四个徒弟了,也就是说徒弟越多,他的依赖就越多。依赖多的话会产生什么影响呢?首先,遇到妖怪了,让谁出场是个问题了,总不能天天让一个人吃苦,这就不是一个好的领导了。所以,出战的方法也得修改。

    public class TangSeng {
    
      WuKong wuKong = new WuKong();
      BaJie baJie = new BaJie();
      LaoSha laoSha = new LaoSha();
      XiaoBaiLong xiaoBaiLong = new XiaoBaiLong();
    
      public void letsFight(String name) {
        if (name.equals("wuKong")) {
          wuKong.fight();
        } else if (name.equals("baJie")) {
          baJie.fight();
        } else if (name.equals("laoSha")) {
          laoSha.fight();
        } else {
          runAway();
        }
      }
    
      private void runAway() {
        System.out.println("Bye Bye ~");
      }
    
    }
    

    这里代码量虽然只稍微上来一点,但是我们得看到更本质的东西。徒弟每增加一个徒弟,唐僧的依赖就会多一个,对应的代码可能就得修改一下。而且,唐僧直接依赖于具体的徒弟类,如果某个徒弟除了问题,那唐僧是不是也可能会出问题。因为他有一个具体的徒弟类,而且还会调用到具体的方法。这种耦合性比较高的代码,后期维护起来会比较糟糕,修改一个地方,其他地方可能也要跟着做很多更改。所以我们需要换个角度考虑一下。

    依赖倒置

    上面分析了问题出现在什么地方。主要是类之间直接的依赖关系导致的高耦合,那么要如何改变这种依赖关系呢?这就要改变我们思考的方式了,我们应该更多的依赖于接口(广泛概念上的接口)而不是具体的类,即要依赖于接口,而不是依赖于具体。无论是悟空,八戒还是沙僧,他们对于唐僧而言都是徒弟。我们可以将徒弟抽象成一个接口。如下:

    dependeyOfInterface.png
    这里,具体类之间的直接依赖关系就被改变了。由类与具体类之间的依赖,转换成了类与接口之间的依赖。即唐僧类依赖于TuDi接口,而四个徒弟也依赖于TuDi接口,他们实现了接口。从上往下的依赖关系,在TuDi与徒弟实现类这里发生了改变,成了徒弟向上依赖于TuDi接口。这种倒置,就是依赖倒置。

    下面看看这种倒置对代码产生的影响:

    public class TangSeng {
    
      List<TuDi> ts = new ArrayList<TuDi>();
    
      public TangSeng(List<TuDi> ts) {
        this.ts = ts;
      }
    
      public void letsFight(TuDi tudi) {
        tudi.fight();
      }
    
    }
    

    实例化的语句没有了,具体类和实例对象也没有了。TuDi的具体实现对于唐生而言已经无所谓了,能打就行了。

    2. 控制反转(IOC)

    继续用上面的例子分析。我们知道师徒四人会遇到妖怪,但是遇到的妖怪是哪个?跟谁打?这个在正常情况下我们可能没法确定,但是在代码实现时,如果需要指定他们要面对的妖怪,我们可能就要在类中实例化这个妖怪了。

    public class TangSeng {
    
      List<TuDi> ts = new ArrayList<TuDi>();
      LionMonster lion = new LionMonster();
        
      public TangSeng(List<TuDi> ts) {
        this.ts = ts;
      }
    
      public void letsFight(TuDi tudi) {
        tudi.fight(lion);
      }
    
    }
    

    这里就等于写死了,他们只会跟狮子怪干架。妖怪是应用程序自己主动指定创建的。如果我们更改这种模式,他们跟哪个妖怪打架可以动态改变,由其他的配置控制。就是我们可以在需要的时候,将对象实例传递过去,这是被动的过程。这种由主动变成被动的方式,就是我理解中的反转控制。 具体的实现可能有多种方式,反射就是一种比较经典的实现。

    public class TangSeng {
    
      List<TuDi> ts = new ArrayList<TuDi>();
      Property pro = new Property();
        
      public TangSeng(List<TuDi> ts) {
        this.ts = ts;
      }
        
        public Monster getMonster() {
            Class monsterClass = Class.forName(pro.getClassName());
            return monsterClass.newInstance();
        }
    
      public void letsFight(TuDi tudi) {
        tudi.fight(getMonster);
      }
    
    }
    

    pro.getClassName()返回的值,可以通过配置文件更改成指定的类。

    3. 依赖注入(Dependency injection)

    • 注入
      我们再看看唐僧类中妖怪战斗的方法,圣僧是铁定上不了场的,这里我们是通过接口声明参数的,但是当真正调用方法的时候,这个地方肯定是要有个具体的徒弟实现类。所以问题就是这个徒弟怎么来。通过上面的讨论我们已经有两种方法可以实现了。其一,在代码中直接实例化好,然后传入对象,可以是通过工厂返回的对象。其二,通过配置文件指定徒弟类,在运行时动态生成徒弟类。后者变是反转控制的一种实现。反转控制是一个概念,他具体的实现方式可能有很多种。大部分场景是通过IOC容器,根据配置文件来实现注入。常用的框架有Spring,非常用的有Google Guice,因为Druid的依赖注入都是通过Google Guice实现的,所以这里简单介绍一下它。

    4. Google Guice

    Google Guice 是一款轻量级的依赖注入框架。

    < dependency

    < groupId >com.google.inject< /groupId >

    < artifactId>guice < /artifactId >

    < version >4.1.0< /version >

    < /dependency >

    4.1 使用实例

    场景1:唐僧被妖怪抓走了,大师兄刚刚化缘回来。各位师兄弟的反应如下,沙僧:大师兄!师父被妖怪抓走了!!八戒:分行李吧!!悟空:我去看看是哪路妖怪,如此胆大!!于是,悟空出发了!!
    以下是悟空类,悟空多了一个拯救师父的任务

    
    public class Wukong implements Tudi {
    
        private String name = "wukong";
        private Skill skill;
        
        public void toSaveMaster(){
            //悟空使用它的技能(skill)对付妖怪
             skill.Effect();
        }
    
        @Override
        public void fight(Monster monster) {
            System.out.println("WuKong is fighting with " + monster);
        }
    }
    

    那我们知道悟空会很多的法术,妖怪也是千奇百怪,所以要对症下药,选择正确的技能才能在损失最小的情况下快速地救出师傅。那这里的技能就又要用我们上面的思想来处理了:

    //把Skill定义为一个接口
    public interface Skill {
        public void Effect();
    }  
      
    //下面是悟空的几个技能
    class Fire implements Skill{
        @Override
        public void Effect() {
            System.out.println("悟空在喷火!!对敌方造成火属性伤害100");
        }
    }
    
    
    class Water implements Skill{
        @Override
        public void Effect() {
            System.out.println("哇!!悟空在喷水!!对敌方造成水属性伤害100");
        }
    }
    
    class Wind implements Skill{
        @Override
        public void Effect() {
            System.out.println("悟空在刮风!!对敌方造成风属性伤害100");
        }
    }
    
    

    这里我们知道了悟空会法术(Skill接口),还知道了他的技能清单(Skill的实现类)。接下来就是根据地方选择正确的技能了。例如对面是白骨精,那我们就选择喷水技能打伤害吧(我也不知道为什么,感觉会很有效!)。那我们要做的就是把悟空的技能接口和接口的实现类Water绑定到一起。不使用框架的操作。

         Wukong wukong = new Wukong();
         wukong.skill=new Water();
    

    使用Guice,需要做的步骤如下:

    1. 创建接口;
    2. 接口实现;
    3. 将接口和实现类绑定;
    4. 创建接口实例。

    前两步已经在上面的代码中完成了,接口为Skill,实现类就是喷火、喷水、刮风。接下来我们进行接口的绑定。
    步骤三:将接口和实现类绑定

    public class SkillModule implements Module {
        @Override
        public void configure(Binder binder) {
            binder.bind(Skill.class).to(Water.class);
        }
        //接口和实现类绑定的一种方式就是通过实现配置模块,实现其config方法来完成。这种绑定关系,我们也可以通过配置文件指定。
    

    步骤四:创建接口的实例

         public static void main(String[] args) {
             //将配置传入
            Injector injector = Guice.createInjector(new SkillModule());
            skill = injector.getInstance(Skill.class);
            Wukong wukong = new Wukong();
            wukong.skill=skill;
            wukong.toSaveMaster();
        } 
    
        运行结果如下:
        哇!!悟空在喷水!!对敌方造成水属性伤害100
    

    4.2 Guice中的注解

    @ImplementedBy:用于注解接口,直接指定接口的实现类而不需要在Module中实现接口的绑定;
    Demo

    //定义接口时即指定其实现类为Water
    @ImplementedBy(Water.class)
    public interface Skill {
        public void Effect();
    }
    

    在Main方法中的代码也做相应的更改:

    public static void main(String[] args) {
            Injector injector = Guice.createInjector();
            skill = injector.getInstance(Skill.class);
            Wukong wukong = new Wukong();
            wukong.skill=skill;
            wukong.toSaveMaster();
        }
    

    运行结果一样,但是整个代码工程中少了配置module的过程。但是谁又能在定义接口时就知道其实现类呢,我觉得用处不是特别大。

    @Inject:使用该注解,可以将对象实例直接注入到一个对其依赖的类中。可以用在某个类的构造方法中:
    Demo

    public class Wukong implements Tudi {
    
        private static String name = "wukong";
        private static Skill skill;
    
        @Inject
        public Wukong(Skill skill) {
            this.skill = skill;
        }
    
        public void toSaveMaster(){
            skill.Effect();
        }
    
        @Override
        public void fightMonster() {
            System.out.println("WuKong is fighting !!");
        }
    }
    

    Main方法也变了

    public static void main(String[] args) {
            Injector injector = Guice.createInjector();
            Wukong wukong = injector.getInstance(Wukong.class);
            wukong.toSaveMaster();
        }
    

    运行结果一样。

    @Singleton
    用来注解类,可以确保调用injector.getInstance时创建的是一个单例类。

    @Named:当一个接口实多个绑定时可以使用该注解区分。
    改写SkillModule类

    public class SkillModule implements Module {
        @Override
        public void configure(Binder binder) {
            binder.bind(Skill.class).annotatedWith(Names.named("Water")).to(Water.class);
            binder.bind(Skill.class).annotatedWith(Names.named("Fire")).to(Fire.class);
        }
    }
    

    在看看这个注解是如何发挥作用的

    public static void main(String[] args) {
            Injector injector = Guice.createInjector(new SkillModule());
            @Named("Water") Skill waterSkill = injector.getInstance(Skill.class);
            Wukong wukong = new Wukong();
            wukong.skill = waterSkill;
            wukong.toSaveMaster();
            @Named("Fire") Skill fireSkill = injector.getInstance(Skill.class);
            wukong.skill = fireSkill;
            wukong.toSaveMaster();
        }
    

    这样就可以把一个接口绑定到多个实现类上,根据不同的Name可以创建不同的实例。但是在实际中无法通过编译,还没有看出是什么问题,所以不建议使用该注解。
    Guice很强大,这里只是简单记录。

    展开全文
  • 依赖倒置,控制反转,依赖注入及Google Guice1. 依赖倒置依赖 字面意思事物之间具有的一种关系。在面向对象编程中我将其理解为一种对象之间引用的持有关系。任何系统都无法避免依赖,如果一个类或接口在系统中没有被...

    依赖倒置,控制反转,依赖注入及Google Guice

    1. 依赖倒置

    依赖
    字面意思事物之间具有的一种关系。在面向对象编程中我将其理解为一种对象之间引用的持有关系。任何系统都无法避免依赖,如果一个类或接口在系统中没有被依赖,那么他们就不应该出现在系统之中。举个简单的例子说明依赖关系:师徒四人去西天取经。我们说说唐僧,他有个徒弟,其他的东西我们暂且忽略。如果把唐僧师徒一个具体类的话,他在收服了悟空之后应该有这样的依赖关系。

    e4e08a2f1c75f3cc0d350dbed79763e7.png

    我们从唐僧角度考虑的话,他应该是依赖于悟空的,没有他,他可取不到经。那么我们可以说唐僧依赖于他的徒弟。

    在代码中,他们的关系如下:

    public class TangSeng {
      WuKong wuKong = new WuKong();
    }

    有了徒弟,唐僧就可以跟他愉快地取经了。中途遇到妖怪,也可以让徒弟去打妖怪了。

    public class TangSeng {
    
      WuKong wuKong = new WuKong();
    
      public void letsFight(String name) {
          wuKong.fight();
      }
    
    }

    那么问题了,唐僧在后面还会收徒弟。当他收齐之后情况应该是这样的。

    b71f05a998e54f50d5888c5a28e08884.png

    这里他就依赖于四个徒弟了,也就是说徒弟越多,他的依赖就越多。依赖多的话会产生什么影响呢?首先,遇到妖怪了,让谁出场是个问题了,总不能天天让一个人吃苦,这就不是一个好的领导了。所以,出战的方法也得修改。

    public class TangSeng {
    
      WuKong wuKong = new WuKong();
      BaJie baJie = new BaJie();
      LaoSha laoSha = new LaoSha();
      XiaoBaiLong xiaoBaiLong = new XiaoBaiLong();
    
      public void letsFight(String name) {
        if (name.equals("wuKong")) {
          wuKong.fight();
        } else if (name.equals("baJie")) {
          baJie.fight();
        } else if (name.equals("laoSha")) {
          laoSha.fight();
        } else {
          runAway();
        }
      }
    
      private void runAway() {
        System.out.println("Bye Bye ~");
      }
    
    }

    这里代码量虽然只稍微上来一点,但是我们得看到更本质的东西。徒弟每增加一个徒弟,唐僧的依赖就会多一个,对应的代码可能就得修改一下。而且,唐僧直接依赖于具体的徒弟类,如果某个徒弟除了问题,那唐僧是不是也可能会出问题。因为他有一个具体的徒弟类,而且还会调用到具体的方法。这种耦合性比较高的代码,后期维护起来会比较糟糕,修改一个地方,其他地方可能也要跟着做很多更改。所以我们需要换个角度考虑一下。

    依赖倒置

    上面分析了问题出现在什么地方。主要是类之间直接的依赖关系导致的高耦合,那么要如何改变这种依赖关系呢?这就要改变我们思考的方式了,我们应该更多的依赖于接口(广泛概念上的接口)而不是具体的类,即要依赖于接口,而不是依赖于具体。无论是悟空,八戒还是沙僧,他们对于唐僧而言都是徒弟。我们可以将徒弟抽象成一个接口。如下:

    d3f92e22943cc5925b6cbafc7022c620.png

    这里,具体类之间的直接依赖关系就被改变了。由类与具体类之间的依赖,转换成了类与接口之间的依赖。即唐僧类依赖于TuDi接口,而四个徒弟也依赖于TuDi接口,他们实现了接口。从上往下的依赖关系,在TuDi与徒弟实现类这里发生了改变,成了徒弟向上依赖于TuDi接口。这种倒置,就是依赖倒置。

    下面看看这种倒置对代码产生的影响:

    public class TangSeng {
    
      List<TuDi> ts = new ArrayList<TuDi>();
    
      public TangSeng(List<TuDi> ts) {
        this.ts = ts;
      }
    
      public void letsFight(TuDi tudi) {
        tudi.fight();
      }
    
    }

    实例化的语句没有了,具体类和实例对象也没有了。TuDi的具体实现对于唐生而言已经无所谓了,能打就行了。

    2. 控制反转(IOC)

    继续用上面的例子分析。我们知道师徒四人会遇到妖怪,但是遇到的妖怪是哪个?跟谁打?这个在正常情况下我们可能没法确定,但是在代码实现时,如果需要指定他们要面对的妖怪,我们可能就要在类中实例化这个妖怪了。

    public class TangSeng {
    
      List<TuDi> ts = new ArrayList<TuDi>();
      LionMonster lion = new LionMonster();
    
      public TangSeng(List<TuDi> ts) {
        this.ts = ts;
      }
    
      public void letsFight(TuDi tudi) {
        tudi.fight(lion);
      }
    
    }

    这里就等于写死了,他们只会跟狮子怪干架。妖怪是应用程序自己主动指定创建的。如果我们更改这种模式,他们跟哪个妖怪打架可以动态改变,由其他的配置控制。就是我们可以在需要的时候,将对象实例传递过去,这是被动的过程。这种由主动变成被动的方式,就是我理解中的反转控制。 具体的实现可能有多种方式,反射就是一种比较经典的实现。

    public class TangSeng {
    
      List<TuDi> ts = new ArrayList<TuDi>();
      Property pro = new Property();
    
      public TangSeng(List<TuDi> ts) {
        this.ts = ts;
      }
    
        public Monster getMonster() {
            Class monsterClass = Class.forName(pro.getClassName());
            return monsterClass.newInstance();
        }
    
      public void letsFight(TuDi tudi) {
        tudi.fight(getMonster);
      }
    
    }

    pro.getClassName()返回的值,可以通过配置文件更改成指定的类。

    3. 依赖注入(Dependency injection)

    • 注入
      我们再看看唐僧类中妖怪战斗的方法,圣僧是铁定上不了场的,这里我们是通过接口声明参数的,但是当真正调用方法的时候,这个地方肯定是要有个具体的徒弟实现类。所以问题就是这个徒弟怎么来。通过上面的讨论我们已经有两种方法可以实现了。其一,在代码中直接实例化好,然后传入对象,可以是通过工厂返回的对象。其二,通过配置文件指定徒弟类,在运行时动态生成徒弟类。后者变是反转控制的一种实现。反转控制是一个概念,他具体的实现方式可能有很多种。大部分场景是通过IOC容器,根据配置文件来实现注入。常用的框架有Spring,非常用的有Google Guice,因为Druid的依赖注入都是通过Google Guice实现的,所以这里简单介绍一下它。

    4. Google Guice

    Google Guice 是一款轻量级的依赖注入框架。

    <dependency>
        <groupId>com.google.inject</groupId> 
        <artifactId>guice </artifactId>  
        <version>4.1.0</version>  
     </dependency>  
    
    <dependency>
        <groupId>aopalliance</groupId>
        <artifactId>aopalliance</artifactId>
        <version>1.0</version>
    </dependency>

    4.1 使用实例

    场景1:唐僧被妖怪抓走了,大师兄刚刚化缘回来。各位师兄弟的反应如下,沙僧:大师兄!师父被妖怪抓走了!!八戒:分行李吧!!悟空:我去看看是哪路妖怪,如此胆大!!于是,悟空出发了!!
    以下是悟空类,悟空多了一个拯救师父的任务
    public class Wukong implements Tudi {
    
        private String name = "wukong";
        private Skill skill;
    
        public void toSaveMaster(){
            //悟空使用它的技能(skill)对付妖怪
             skill.Effect();
        }
    
        @Override
        public void fight(Monster monster) {
            System.out.println("WuKong is fighting with " + monster);
        }
    }

    那我们知道悟空会很多的法术,妖怪也是千奇百怪,所以要对症下药,选择正确的技能才能在损失最小的情况下快速地救出师傅。那这里的技能就又要用我们上面的思想来处理了:

    //把Skill定义为一个接口
    public interface Skill {
        public void Effect();
    }  
    
    //下面是悟空的几个技能
    class Fire implements Skill{
        @Override
        public void Effect() {
            System.out.println("悟空在喷火!!对敌方造成火属性伤害100");
        }
    }
    
    
    class Water implements Skill{
        @Override
        public void Effect() {
            System.out.println("哇!!悟空在喷水!!对敌方造成水属性伤害100");
        }
    }
    
    class Wind implements Skill{
        @Override
        public void Effect() {
            System.out.println("悟空在刮风!!对敌方造成风属性伤害100");
        }
    }

    这里我们知道了悟空会法术(Skill接口),还知道了他的技能清单(Skill的实现类)。接下来就是根据地方选择正确的技能了。例如对面是白骨精,那我们就选择喷水技能打伤害吧(我也不知道为什么,感觉会很有效!)。那我们要做的就是把悟空的技能接口和接口的实现类Water绑定到一起。不使用框架的操作。

    Wukong wukong = new Wukong();
         wukong.skill=new Water();

    使用Guice,需要做的步骤如下:
    1. 创建接口;
    2. 接口实现;
    3. 将接口和实现类绑定; 4. 创建接口实例。

    前两步已经在上面的代码中完成了,接口为Skill,实现类就是喷火、喷水、刮风。接下来我们进行接口的绑定。
    步骤三:将接口和实现类绑定

    public class SkillModule implements Module {
        @Override
        public void configure(Binder binder) {
            binder.bind(Skill.class).to(Water.class);
        }
        //接口和实现类绑定的一种方式就是通过实现配置模块实现其config方法来完成这种绑定关系我们也可以通过配置文件指定

    步骤四:创建接口的实例

    public static void main(String[] args) {
             //将配置传入
            Injector injector = Guice.createInjector(new SkillModule());
            skill = injector.getInstance(Skill.class);
            Wukong wukong = new Wukong();
            wukong.skill=skill;
            wukong.toSaveMaster();
        } 
    
        运行结果如下
        !!悟空在喷水!!对敌方造成水属性伤害100

    4.2 Guice中的注解

    @ImplementedBy:用于注解接口,直接指定接口的实现类而不需要在Module中实现接口的绑定;
    Demo

    //定义接口时即指定其实现类为Water
    @ImplementedBy(Water.class)
    public interface Skill {
        public void Effect();
    }

    在Main方法中的代码也做相应的更改:

    public static void main(String[] args) {
            Injector injector = Guice.createInjector();
            skill = injector.getInstance(Skill.class);
            Wukong wukong = new Wukong();
            wukong.skill=skill;
            wukong.toSaveMaster();
        }

    运行结果一样,但是整个代码工程中少了配置module的过程。但是谁又能在定义接口时就知道其实现类呢,我觉得用处不是特别大。

    @Inject:使用该注解,可以将对象实例直接注入到一个对其依赖的类中。可以用在某个类的构造方法中:
    Demo

    public class Wukong implements Tudi {
    
        private static String name = "wukong";
        private static Skill skill;
    
        @Inject
        public Wukong(Skill skill) {
            this.skill = skill;
        }
    
        public void toSaveMaster(){
            skill.Effect();
        }
    
        @Override
        public void fightMonster() {
            System.out.println("WuKong is fighting !!");
        }
    }

    Main方法也变了

    public static void main(String[] args) {
            Injector injector = Guice.createInjector();
            Wukong wukong = injector.getInstance(Wukong.class);
            wukong.toSaveMaster();
        }

    运行结果一样。

    @Singleton
    用来注解类,可以确保调用injector.getInstance时创建的是一个单例类。

    @Named:当一个接口实多个绑定时可以使用该注解区分。
    改写SkillModule类

    public class SkillModule implements Module {
        @Override
        public void configure(Binder binder) {
            binder.bind(Skill.class).annotatedWith(Names.named("Water")).to(Water.class);
            binder.bind(Skill.class).annotatedWith(Names.named("Fire")).to(Fire.class);
        }
    }

    在看看这个注解是如何发挥作用的

    public static void main(String[] args) {
            Injector injector = Guice.createInjector(new SkillModule());
            @Named("Water") Skill waterSkill = injector.getInstance(Skill.class);
            Wukong wukong = new Wukong();
            wukong.skill = waterSkill;
            wukong.toSaveMaster();
            @Named("Fire") Skill fireSkill = injector.getInstance(Skill.class);
            wukong.skill = fireSkill;
            wukong.toSaveMaster();
        }

    这样就可以把一个接口绑定到多个实现类上,根据不同的Name可以创建不同的实例。但是在实际中无法通过编译,还没有看出是什么问题,所以不建议使用该注解。
    Guice很强大,这里只是简单记录。啥?啥是控制反转,依赖注入啊!?

    展开全文
  • 控制反转

    2020-05-14 15:24:21
    何谓控制反转? 以前我们要使用一个对象,这样...应用控制反转、依赖注入,类似这样的: public class Test { IClass1 obj;//类内只有接口 public Test(IClass obj) { this.obj = obj;//你会给我一个实例.

    何谓控制反转?

    以前我们要使用一个对象,是这样的:

    Class1 obj = new Class1();

    面向接口编程后,是这样的:

    //Class1 :IClass1
    IClass1 obj = new Class1();

    应用控制反转、依赖注入,是类似这样的: 

    public class Test
    {
        IClass1 obj;//类内只有接口
        public Test(IClass obj)
        {
            this.obj = obj;//你会给我一个啥实例?给点提示好不好?呵呵,给啥用啥,没得挑!
        }
        ...
    }
    //对象实例要靠类外面创建,再传递进来(注入)
    Test test = new Test(new Class1());
    

    这种使用对象实例方式,不经过类自身构造,无法控制,而只能听由外部或调用方安排,即所谓控制反转了。

     

     

     

     

     

     

     

     

     

     

    ***以上摘自他人,仅留存个人笔记使用

     

     

     

     

    展开全文
  • 算法-反转字符串与反转单词

    千次阅读 2017-08-15 04:24:41
    首先题目说的很明确,就是反转字符串,不是打印,也不是创建一个新的字符串,而是改变原数据,最简单的思路就是将第一个字符和最后一个交换,第二个和倒数第二个交换,依次循环,函数可以返回一个标志位,也可以都...
  • 反转链表

    2019-07-16 16:53:34
    下面的函数自己写的,不知道为通不过,检查了很多遍了。。。哎 /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class...
  • Spirng框架解析01 前言:Spring框架一个轻量级的企业级开发的一站式解决方案! ...IoC:控制反转,在Spring框架中指的将对象的创建权移交给容器(ApplicationContext容器).重点,容器来负...
  • 啥是IOC ?啥是DI ?

    2019-09-27 20:31:49
    IOC (inverse of controll)控制反转:所谓控制反转就是把创建对象(bean),和维护对象(bean)的关系的权利从程序中转移到spring的容器(applicationContext.xml)2、DI什么? Di(dependency injection)依赖注入:...
  • 之前只是知道Spring的精髓是依赖注入,控制反转,也只是知道这些名词而已,没有理解到精髓,今天看了...依赖反转,从字面理解就是把依赖倒过来了呗,那原来依赖正着的时候是啥样的呢? 正着的时候是上层建筑依赖下...
  • Splay 区间反转

    2018-10-01 11:47:00
    这个好像用O(n)的吧……(这次vector,set也救不了你了) 我们来使用splay解决这个问题。我们既然要反转一段区间,那我们肯定要把这个区间弄到一个地方。我们想一下上次所讲的删除操作,我们把要删除的数的...
  • 可能有些同学不明白,为要图片反转(不是旋转哦),我们在游戏开发中,为了节省图片资源(空间) 有可能会使用到图片反转,例如,一个人物图片,面向左,或右,如果不能实现图片反转的情况下,就需要两张图片了,...
  • Spring的控制反转

    2017-09-24 00:32:54
    先简单介绍一下Spring↓ Spring一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架。它属于一种一站式框架,对于javaee的每一层它都提供自己的解决技术。web层使用SpringMVC,...
  • Spring中的Ioc、DI到底是啥

    万次阅读 多人点赞 2017-11-07 11:01:14
    Ioc 控制反转Ioc(Inversion of control)控制反转,这里的控制指把控制权从应用程序中剥离出来。ioc它可以把创建对象和查找依赖对象的权限交给Ioc容器控制,而不是传统的由这些对象的使用方(消费者)进行创建初始化...
  • spring框架是啥?

    2019-06-23 09:35:00
    反转控制 Spring的基础,Inversion Of Control 简单说就是创建对象由以前的程序员自己new 构造方法来调用,变成了交由Spring创建对象 DI 依赖注入 Dependency Inject. 简单地说就是拿到的对象的属性,已经被注入好...
  • 依赖注入和控制反转

    2018-11-15 16:54:15
    反转和正传表示?自从干了编程,不知道你们有没有发现,我反正发现了,我的头一天比一天变大了。 Ioc-Inversion of Control,控制反转 DI-Dependency Injection,依赖注入 1.如何理解Ioc/DI 要想理解这两个...
  • 将偶数二进制反转

    2017-10-18 17:32:51
    将偶数二进制反转,那为不是奇数呢,因为奇数二进制本身就是对齐的,反转反转不了。这段代码前面比较繁琐的就是算出整数最高位多少,有点冗余了,但是囿于水平和时间,暂时只考虑到了这中方法,若有更好的方法...
  • 同《会计》科目一样,今年的...究竟考了些?下面跟随高顿CPA老师一探究竟。20年CPA《税法》真题及答案解析!考试考什么?用真题来回答,以下高顿CPA老师为大家整理的20年CPA《税法》考试真题,各考生可以自己回...
  • 控制反转编程思想的定义 控制反转就是我们经常听...传统的编程思想应用程序在运行的过程中可能会需要其他类的对象,这时候应用程序会先创建需要的类对象,也就是说应用程序在运行时需要,自己动手通过new创建出...
  • 原标题:java单链表反转(花了半个多小时的作品)首先我们要搞清楚链表是啥玩意儿?先看看定义:讲链表之前我们先说说Java内存的分配情况:我们new对象的时候,会在java堆中为对象分配内存,当我们调用方法的时候,会...
  • 递归反转链表理解

    千次阅读 2019-05-08 10:18:05
    反转链表就像在教室里,让所有同学(假设有N排)回头,看向后面的黑板。链表中结点的指向用同学们的眼睛朝向代表。此时,老师已经在后面的黑板旁边,让最后一排(链表头)回头,若这一排回头不管别的同学,那后面...
  • 这道题的要求只通过一次遍历完成,就拿题目中的例子来说,变换的2,3,4这三个点,我们需要找到第一个开始变换结点的前一个结点,只要让pre向后走m-1步即可,为要减1呢,因为题目中从1开始计数的,这里只走了1...
  • 反转链表—leetcode206

    2020-05-14 23:35:15
    思路1:迭代法,代码写起来感觉都刚刚好,又有逻辑的,核心就是把扫描到的节点不断的前置,就是把cur->head = newhead 然后把newhead更新为cur,newhead=cur /** * Definition for...
  • 定义 高层模块不应该依赖底层模块,两者都应该依赖其抽象; 抽象不应该依赖细节,细节应该依赖抽象; 解释首先我们去理解依赖反转字面所表达的意思,依赖正如...世间万物皆有因果,我们还是先看看反转是啥玩意.大家日
  • 啥是IOC,DI,AOP

    2020-06-28 18:53:54
    相关文章也特别多,自己对这些知识进行归纳总结,更简单的描述下玩意。 IOC, DI, AOP玩意,为要有这三个东西 这三面向对象编程的一种思想,也Spring框架的最主要的三个核心。为了编写出更易于...
  • 吐槽的技巧——反转

    2019-01-01 18:21:24
    《吐槽大会》已经播到第三季了,看了这么多期下来,我也在想,我看的究竟是啥,笑的究竟是什么。仔细想想,笑的原因可能只有两个字——反转。 在一个人有槽点的情况下,运用反转的手法,可以把吐槽隐含在一个段子里...
  • 啥是依赖注入,什么又控制反转,咋说才简单又专业咧,哈哈 控制反转和依赖注入基本一个意思 控制反转主要说 构造和初始化对象及其依赖的过程应该交给某个更通用的层次的组件来负责,反转也就意味着某种...
  • 控制反转:控制反转是将组件间的依赖关系从程序内部提到外部来管理; 举例:到餐馆吃饭之前吃的套餐,菜是厨师定的,换成点菜,吃自己说了算 反射:直观理解就是根据到达地找到出发地和来源 举例:有点像摸烤鸭...
  • WPF图片的反转

    2010-04-13 14:37:00
    在做摄像头图像采集时遇到了一个问题,采集到的图像反转了,结果采集到的图像就好比我们在照镜子,跟现实世界的方向完全相反的,显示人或场景的时候还没发现奇怪的,可能平时看镜子多了,但显示字的时候就发现...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 242
精华内容 96
关键字:

反转是啥