免费预览已结束,剩余5页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Spring的IoC控制反转与DI依赖注入详解文章分类:Java编程 学习Spring,所有教程都是从IoC和DI开始的,但是大部分教程对它们的介绍都很抽象,要是之前没系统的学习过设计模式的话理解起来就非常吃力。所以在这里我尽我的能力来解释这两个概念。 首先的重点,IoC并不是Spring特有的,它是一种设计模式,事实上只要掌握了原理,自己也可以写出一个IoC的实现方法。 一、DI(Dependency Injection)依赖注入可以称为IoC(Inversion of Control)控制反转,但是IoC不等于就是DI 这一点是很多初学者很容易产生错误的一个概念,因为很多教程都把DI和IoC放在一起说,就像堆和堆栈一样,容易让初学者以为他们就是同一个东西,这个是需要纠正的。 简单的解释,就是IoC包括了DI,但是IoC还包括了另外一个叫做DL(Dependency Lookup)依赖查找的功能。你可以先简单的把IoC当作是某种操作,DI是这种操作的写入方式,而DL是查找方式,这样可能容易区分一点。 DL之所以很少有人提起,是因为我们平时很少用到,所以也就慢慢被遗忘了,但是这也不代表它就不存在了。可惜我自己也对DL没有去花时间了解,只是知道有这么个东西,所以在这暂时也没法去详细介绍了,如果有高手的话请指点一下! 二、什么叫做IoC(Inversion of Control)控制反转 这一段是纯理论的介绍,从别的地方直接抄过来的,先看一遍,不懂也没关系,下面我会举例来说明: 引用什么是Inversion of Control 控制反转。在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。 IoC的原理 不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。其原理是基于OO设计原则的The Holly wood Principle:Dont call us, well call you(别找我,我会来找你的)。也就是说,所有的组件都是被动的(Passive),所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,这就是反转。 如果你只需要看这段文字介绍就能理解什么叫IoC了,那下面的那些也就不用看了,大侠! 如果你也跟我一样属于笨的那种,那么可以看一下我下面的介绍: 我们沿用之前的HelloWorld的例子来介绍IoC。 假设我要跟我们家的邻居去打招呼,但是我又懒得出门,所以我干脆造了一个机器人代替我去打招呼了(这得要多宅的一个人啊! 宁可造个机器人也不想出个门)。 1、首先我们传统的编程方式是这样的: 先建立一个Robot类,然后类里面实现一个喊话的方法,然后实现方法里创建一个机器人的实例来调用喊话: Robot类: Java代码 1. packagecom.iteye.bolide74.action; 2. 3. publicclassRobot 4. publicStringname; 5. publicStringcolor; 6. publicdoubleheight; 7. publicdoublewidth; 8. publicdoubleweight; 9. 10. publicRobot(Stringname,Stringcolor,doubleheight,doublewidth, 11. doubleweight) 12. =name; 13. this.color=color; 14. this.height=height; 15. this.width=width; 16. this.weight=weight; 17. 18. 19. publicvoidSpeak(Stringmsg) 20. System.out.println(msg); 21. 22. package com.iteye.bolide74.action;public class Robot public String name;public String color;public double height;public double width;public double weight;public Robot(String name, String color, double height, double width,double weight) = name;this.color = color;this.height = height;this.width = width;this.weight = weight;public void Speak(String msg) System.out.println(msg);实现类: Java代码 1. packagecom.iteye.bolide74.tester; 2. 3. importcom.iteye.bolide74.action.Robot; 4. 5. publicclassIoCTester 6. publicstaticvoidmain(Stringargs) 7. Robotrobot0=newRobot(robot0,black,80.000,40.0000,1000.0000); 8. robot0.Speak(Hello,World!); 9. 10. package com.iteye.bolide74.tester;import com.iteye.bolide74.action.Robot;public class IoCTester public static void main(String args) Robot robot0 = new Robot(robot0, black, 80.000, 40.0000, 1000.0000);robot0.Speak(Hello,World!);优点:方便简单啊!随便学个一天JAVA就会用啊! 缺点:写代码倒是方便了,但是以后维护起来就超级麻烦。既然是机器人那么制造的时候势必还会涉及它的名字、颜色、高矮胖瘦之类的参数。假设我要造N个黑色的机器人去给一楼的邻居打招呼;白色的去二楼;红色的去三楼等等。如果某天发现红色的油漆没了需要换成蓝色,那岂不是得翻出每个红色机器人的实现类,然后一个个的去改掉这个机器人实例的颜色? 太累了! 2、使用简单工厂和静态工厂模式来创建机器人: 用简单工厂模式来创建,那就相对简单方便一些了,我们会在工厂类里事先写好一些常用类型的机器人,然后只要用机器人的编号来获得相应的机器人就行了。 还是调用那个Robot类不变,只改实现类: Java代码 1. packagecom.iteye.bolide74.tester; 2. 3. importcom.iteye.bolide74.action.Robot; 4. 5. classRobotFactory 6. publicRobotgetRobot(introbotType) 7. Robotrobot; 8. switch(robotType) 9. case0: 10. robot=newRobot(robot0,black,80.000,40.0000,1000.0000); 11. break; 12. case1: 13. robot=newRobot(robot1,white,90.000,30.0000,800.0000); 14. break; 15. default: 16. robot=newRobot(defaultRobot,red,10.000,10.0000,300.0000); 17. break; 18. 19. returnrobot; 20. 21. 22. 23. publicclassIoCTester 24. publicstaticvoidmain(Stringargs) 25. RobotFactoryrobotFactory=newRobotFactory(); 26. Robotrobot=robotFactory.getRobot(0); 27. robot.Speak(Hello,World!Mynameis+); 28. 29. package com.iteye.bolide74.tester;import com.iteye.bolide74.action.Robot;class RobotFactory public Robot getRobot(int robotType) Robot robot;switch (robotType) case 0:robot = new Robot(robot0, black, 80.000, 40.0000, 1000.0000);break;case 1:robot = new Robot(robot1, white, 90.000, 30.0000, 800.0000);break;default:robot = new Robot(defaultRobot, red, 10.000, 10.0000, 300.0000);break;return robot;public class IoCTester public static void main(String args) RobotFactory robotFactory = new RobotFactory();Robot robot = robotFactory.getRobot(0);robot.Speak(Hello,World! My name is + );这样的话后期维护就方便很多了,当有一天需要把已经造好的所有红色机器人换成蓝色,那就只要在getRobot方法里相应的new Robot()里的red参数换成blue就行了。简单么? 但是我觉得为了这么一个单一的类多写一个工厂太麻烦了,有没有办法省略这个工厂呢?答案是肯定的,我们可以直接把getRobot这个获取实例的方法写在Robot类里面就不需要新建专门的工厂类了,这里新建一个Robot2类来与原先的Robot类区分开: Java代码 1. packagecom.iteye.bolide74.action; 2. 3. publicclassRobot2 4. publicStringname; 5. publicStringcolor; 6. publicdoubleheight; 7. publicdoublewidth; 8. publicdoubleweight; 9. 10. privateRobot2(Stringname,Stringcolor,doubleheight,doublewidth, 11. doubleweight) 12. =name; 13. this.color=color; 14. this.height=height; 15. this.width=width; 16. this.weight=weight; 17. 18. 19. publicstaticRobot2getRobot(introbotType) 20. Robot2robot2; 21. switch(robotType) 22. case0: 23. robot2=newRobot2(robot0,black,80.000,40.0000,1000.0000); 24. break; 25. case1: 26. robot2=newRobot2(robot1,white,90.000,30.0000,800.0000); 27. break; 28. default: 29. robot2=newRobot2(defaultRobot,red,10.000,10.0000,300.0000); 30. break; 31. 32. returnrobot2; 33. 34. publicvoidSpeak(Stringmsg) 35. System.out.println(msg+,我是+); 36. 37. package com.iteye.bolide74.action;public class Robot2 public String name;public String color;public double height;public double width;public double weight;private Robot2(String name, String color, double height, double width,double weight) = name;this.color = color;this.height = height;this.width = width;this.weight = weight;public static Robot2 getRobot(int robotType) Robot2 robot2;switch (robotType) case 0:robot2 = new Robot2(robot0, black, 80.000, 40.0000, 1000.0000);break;case 1:robot2 = new Robot2(robot1, white, 90.000, 30.0000, 800.0000);break;default:robot2 = new Robot2(defaultRobot, red, 10.000, 10.0000, 300.0000);break;return robot2;public void Speak(String msg) System.out.println(msg + ,我是 + );实现类 Java代码 1. packagecom.iteye.bolide74.tester; 2. 3. importcom.iteye.bolide74.action.Robot2; 4. 5. publicclassIoCTester 6. publicstaticvoidmain(Stringargs) 7. Robot2robot2=Robot2.getRobot(1); 8. robot2.Speak(Hello,world!); 9. 10. package com.iteye.bolide74.tester;import com.iteye.bolide74.action.Robot2;public class IoCTester public static void main(String args) Robot2 robot2 = Robot2.getRobot(1);robot2.Speak(Hello,world!);以上就是静态工厂的实现方式了! 注意!这里有两个细节: 1) Robot2的构造方法是private的,这样的好处就是所有Robot2的使用者或者说是实现类在获取机器人的时候,只能通过getRobot2来获取,这样就实现了规范化,而不是有些地方是直接new的,有些地方是用getRobot方法来的(一个项目,不一定就是一个程序员写到老的.)。 2) Robot2获取实例的getRobot方法是static静态的(所以才叫静态工厂嘛)!由于Robot2的构造函数是private的了,不能直接new一个实例,那就更加不可能调用需要实例化才能使用的getRobot方法了,所以必须要设置为static方法,就可以无需实例化直接调用! 现在用了以上两种工厂方法,只要在需要机器人的时候在getRobot(int robotType)里设进想要的机器人的型号,机器人工厂就会自动送过来我想要的机器人了! 不过现在又出现了一种状况,就是我的GF正好在家,那么我就不用这么麻烦的造机器人了,我只要叫我女朋友去招呼就行了。(TNND就这种宅男+使唤癖,能有GF就有鬼了!) 那么再用这个简单工厂和静态工厂模式就不适用了,毕竟GF不是机器人(我看以这人的脾气其实很有可能GF也是机器人.),那么就得再写一个People类,然后再在这个类里实现Speak方法,然后再新建一个Girlfriend实例来实现speak方法打招呼。你也觉得这样太累了吧?毕竟People类和Robot类都是用来Speak而已,要是来回切换不同的类去Speak的话就得重复建立不同的实例和不同的Speak方法,还是很麻烦! 3、抽象工厂模式(误)多亏yelinsen05的指正,我再查了一下相关资料,这第三种方式其实还是简单工厂模式,误人子弟了.sorry!关于真正的抽象工厂模式,我下回再介绍。学艺不精,献丑了. 真正的抽象工厂介绍请移步看我另外一篇博文:/blog/1001900 现在为了解决简单工厂和静态工厂模式的缺陷,我们可以把Speak这个方法(或者可以称为功能模块)抽取出来,作为一个接口来实现,这样只要People类和Robot类都实现这个接口,就能够通用了。 Java代码 1. packagecom.iteye.bolide74.impl; 2. 3. publicinterfaceISpeaker 4. publicvoidSpeak(Stringmsg); 5. package com.iteye.bolide74.impl;public interface ISpeaker public void Speak(String msg);接下来是新的Robot类和People类,它们都同时实现了ISpeaker这个接口,两者都用了不同的Speak内容来区分人类和机器人说话方式的不同: Java代码 1. packagecom.iteye.bolide74.action; 2. 3. importcom.iteye.bolide74.impl.ISpeaker; 4. 5. publicclassRobotimplementsISpeaker 6. publicStringname; 7. publicStringcolor; 8. publicdoubleheight; 9. publicdoublewidth; 10. publicdoubleweight; 11. 12. publicRobot(Stringname,Stringcolor,doubleheight,doublewidth, 13. doubleweight) 14. =name; 15. this.color=color; 16. this.height=height; 17. this.width=width; 18. this.weight=weight; 19. 20. 21. Override22. publicvoidSpeak(Stringmsg) 23. System.out.println(msg+,我是++,我的体重为+this.weight); 24. 25. package com.iteye.bolide74.action;import com.iteye.bolide74.impl.ISpeaker;public class Robot implements ISpeaker public String name;public String color;public double height;public double width;public double weight;public Robot(String name, String color, double height, double width,double weight) = name;this.color = color;this.height = height;this.width = width;this.weight = weight;Overridepublic void Speak(String msg) System.out.println(msg + ,我是 + + ,我的体重为 + this.weight);Java代码 1. packagecom.iteye.bolide74.action; 2. 3. importcom.iteye.bolide74.impl.ISpeaker; 4. 5. publicclassPeopleimplementsISpeaker 6. publicStringname; 7. publicdoubleheight; 8. publicdoubleweight; 9. 10. publicPeople(Stringname,doubleheight,doubleweight) 11. =name; 12. this.height=height; 13. this.weight=weight; 14. 15. 16. Override17. publicvoidSpeak(Stringmsg) 18. System.out.println(msg+,我是++,我就不告诉你我有多重!); 19. 20. package com.iteye.bolide74.action;import com.iteye.bolide74.impl.ISpeaker;public class People implements ISpeaker public String name;public double height;public double weight;public People(String name, double height, double weight) = name;this.height = height;this.weight = weight;Overridepublic void Speak(String msg) System.out.println(msg + ,我是 + + ,我就不告诉你我有多重!);接下来就是工厂类和实现类了。这个工厂类就不是生产具体的实例对象了,而是生产一个通用的能够Speak的抽象实例(某个能打招呼的东西,或许是人类,或许是机器人) Java代码 1. packagecom.iteye.bolide74.tester; 2. 3. importcom.iteye.bolide74.action.People; 4. importcom.iteye.bolide74.action.Robot; 5. importcom.iteye.bolide74.impl.ISpeaker; 6. 7. classSpeakerFactory 8. publicISpeakergetSpeaker(intspeakerType) 9. ISpeakerspeaker; 10. switch(speakerType) 11. case0: 12. speaker=newRobot(robot0,black,80.000,40.0000,1000.0000); 13. break; 14. case1: 15. speaker=newPeople(GirlFriend,1.64,99.99); 16. break; 17. default: 18. speaker=newRobot(defaultRobot,red,10.000,10.0000, 19. 300.0000); 20. break; 21. 22. returnspeaker; 23. 24. 25. 26. publicclassIoCTester 27. publicstaticvoidmain(Stringargs) 28. SpeakerFactoryspeakerFactory=newSpeakerFactory(); 29. ISpeakerspeaker=speakerFactory.getSpeaker(1); 30. speaker.Speak(Hello,World!); 31. 32. package com.iteye.bolide74.tester;import com.iteye.bolide74.action.People;import com.iteye.bolide74.action.Robot;import com.iteye.bolide74.impl.ISpeaker;class SpeakerFactory public ISpeaker getSpeaker(int speakerType) ISpeaker speaker;switch (speakerType) case 0:speaker = new Robot(robot0, black, 80.000, 40.0000, 1000.0000);break;case 1:speaker = new People(GirlFriend, 1.64, 99.99);break;default:speaker = new Robot(defaultRobot, red, 10.000, 10.0000,300.0000);break;return speaker;public class IoCTester public static void main(String args) SpeakerFactory speakerFactory = new SpeakerFactory();ISpeaker speaker = speakerFactory.getSpeaker(1);speaker.Speak(Hello,World!);输出结果: 引用Hello,World!,我是GirlFriend,我就不告诉你我有多重!如此一来的话就很方便了,我们不用再像之前的简单工厂
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 生物农药施药器械标准
- 农林牧渔行业宠物医院报告:从激进扩张走到稳健发展
- 膀胱肿瘤患者的艺术治疗
- 2026年农村夯土墙建筑热工性能改善技术
- 草莓基质育苗繁育流程
- 2026年茶艺室对外开放服务管理办法
- 2026年城市级建筑信息模型全生命周期应用规范
- 全员安全生产责任制考核实施细则
- 2026年生物实验室实验动物尸体处理规范
- 2026年油耗管理与节能减排讨论会
- 2026长沙海关缉私局警务辅助人员招聘6人考试备考试题及答案解析
- 2026第一季度湖北丹江大数据集团有限公司下属子公司招聘5人笔试备考试题及答案解析
- 2026年寿光市双创物业管理服务有限公司公开招聘(6人)笔试备考题库及答案详解
- GB/T 47322-2026建筑火灾升温条件下电缆耐火性能试验方法
- 2026年广西真龙彩印包装有限公司招聘笔试参考题库附带答案详解
- 2026云南防务装备有限公司社会招聘1人考试模拟试题及答案解析
- 《JBT 2184-2007液压元件 型号编制方法》专题研究报告
- 2026校招:东明石化集团面试题及答案
- 金融科技产品开发与运维手册(标准版)
- 广西工商职业技术学院招聘考试笔试试题附答案
- 传媒公司员工培训课件
评论
0/150
提交评论