ioc 订阅
国际奥林匹克委员会,简称为国际奥委会,是一个国际性的、非政府的、非赢利的组织。是奥林匹克运动的领导机构,它于1981年9月17日得到瑞士联邦议会的承认,确认其为无限期存在的具有法人资格的国际机构。总部位于瑞士洛桑。由法国人皮埃尔·德·顾拜旦建立,首任主席是泽麦特里乌斯·维凯拉斯。据2017年01月16日《人民日报》(海外版)第06版介绍,国际奥委会有100个委员和32个荣誉委员。 [1]  1894年6月23日,国际奥委会在巴黎召开的国际体育代表大会上成立,发起人是法国的教育家皮埃尔·德·顾拜旦男爵。成立之初总部设在巴黎,1914年第一次世界大战爆发,为避战火,1915年4月10日迁入有“国际文化城”之称的瑞士洛桑。国际奥委会根据现代奥林匹克运动创始人顾拜旦的理想,恢复奥林匹克运动的目的,在于增强各国运动员之间的友谊与团结,促进世界和平以及各国人民之间的相互了解,发展世界体育运动。《奥林匹克宪章》明文规定,国际奥委会的宗旨是:鼓励组织和发展体育运动和组织竞赛;在奥林匹克理想指导下,鼓舞和领导体育运动,从而促进和加强各国运动员之间的友谊。国际奥委会组织举办奥林匹克运动会、青年奥林匹克运动会、冬季奥林匹克运动会、残疾人奥林匹克运动会。它组织的首届夏季奥运会于1896年于希腊雅典举行,首届冬奥会于1924年在法国霞慕尼举行。在2018世界品牌500强排行榜中,国际奥林匹克委员会排名第125位。 [2] 展开全文
国际奥林匹克委员会,简称为国际奥委会,是一个国际性的、非政府的、非赢利的组织。是奥林匹克运动的领导机构,它于1981年9月17日得到瑞士联邦议会的承认,确认其为无限期存在的具有法人资格的国际机构。总部位于瑞士洛桑。由法国人皮埃尔·德·顾拜旦建立,首任主席是泽麦特里乌斯·维凯拉斯。据2017年01月16日《人民日报》(海外版)第06版介绍,国际奥委会有100个委员和32个荣誉委员。 [1]  1894年6月23日,国际奥委会在巴黎召开的国际体育代表大会上成立,发起人是法国的教育家皮埃尔·德·顾拜旦男爵。成立之初总部设在巴黎,1914年第一次世界大战爆发,为避战火,1915年4月10日迁入有“国际文化城”之称的瑞士洛桑。国际奥委会根据现代奥林匹克运动创始人顾拜旦的理想,恢复奥林匹克运动的目的,在于增强各国运动员之间的友谊与团结,促进世界和平以及各国人民之间的相互了解,发展世界体育运动。《奥林匹克宪章》明文规定,国际奥委会的宗旨是:鼓励组织和发展体育运动和组织竞赛;在奥林匹克理想指导下,鼓舞和领导体育运动,从而促进和加强各国运动员之间的友谊。国际奥委会组织举办奥林匹克运动会、青年奥林匹克运动会、冬季奥林匹克运动会、残疾人奥林匹克运动会。它组织的首届夏季奥运会于1896年于希腊雅典举行,首届冬奥会于1924年在法国霞慕尼举行。在2018世界品牌500强排行榜中,国际奥林匹克委员会排名第125位。 [2]
信息
创建者
皮埃尔·德·顾拜旦(法国人)
外文名
International Olympic Committee(英),Comité international olympique (法)
简    称
国际奥委会(IOC)
成    员
206国家和地区
总    部
瑞士洛桑(Lausanne)
中文名
国际奥林匹克委员会
官    网
http://www.olympic.org/
成立时间
1894年6月23日
现任主席
托马斯·巴赫
官方语言
英语、法语
国际奥林匹克委员会发展历程
1894年6月16日-24日,根据世界著名的国际体育活动家,法国人皮埃尔·德·顾拜旦的建议,来自法国、英国、希腊、瑞典、意大利、俄国(俄罗斯)、比利时、捷克斯洛伐克、新西兰、美国、阿根廷、匈牙利12个国家的49个体育组织的代表,在巴黎索邦神学院举行国际体育运动代表大会。在开幕式上,法国著名古希腊文化专家切奥多尔·莱拉赫发表演说,巴黎国家歌剧院合唱团为大会演唱了阿波罗颂歌,唤起了与会者对古奥运会的神往。 [3]  会议期间,又先后有21个国家致函,向大会表示支持和祝贺。这次会议通过了成立国际奥委会(成立时间1894年6月23日,成立时的名称是“奥林匹克运动会国际委员会”)的决议,并从79名正式代表中选出15人任第1届国际奥委会委员。大会还决定由奥运会举办国的国际奥委会委员担任国际奥委会主席。由于首届奥运会定于1896年在希腊首都雅典举行,因此希腊委员泽麦特里乌斯·维凯拉斯当选国际奥委会第一任主席,顾拜旦为秘书长。会议规定法语(现为英、法两种语言)为国际奥委会法定语言。大会还决定沿袭古奥运会传统,每四年举行一次运动会,还规定奥运会的比赛项目为田径、水上运动(包括帆船、划船、游泳)、击剑、摔跤、拳击、马术、射击、体操、球类运动等。第一届奥运会原定于1900年于巴黎举行,后来考虑希腊为古代奥运会发源地,在希腊举行比在巴黎意义更重大些,顾拜旦尊重了大家的意见。大会决定把第一届会期改在1896年,鉴于古代奥运会遗址奥林匹亚已成了一片废墟,会址改设在希腊首都雅典。奥运会最早始于古希腊的奥林匹亚由古代希腊人民为祭神和崇拜英雄而举行的一些竞赛活动逐渐发展形成的。举行的地点就在古希腊雅典城西南方向360公里外的奥林匹亚村举行,因此而得名。第一届古代奥运会于公元前776年举行,共举行过293次。后来罗马帝国的入侵古希腊后,由于罗马皇帝狄奥多西信奉基督教,禁止一切关于异教的活动,因此运动会在公元393年被罗马皇帝狄奥多西废除。 [1]  1889年,法国的顾拜旦男爵提出恢复奥林匹克运动的建议。第一届近代奥运会于1896年在希腊举行。以后每四年举行一次。即使其间因故不能举行,届数仍然依次照算(第6、12、13届未举行。第6届由于第一次世界大战的爆发未能举行,第12,13届则因为第二次世界大战的爆发未能举行)。至2016年,已经举行过31次奥运会,最近的一次是在巴西的里约热内卢举行的奥运会。1897年一家法文报纸首次称之为“国际奥林匹克委员会”,1901年正式改用现名。1914年第一次世界大战爆发,为避免战火洗劫,1915年4月10日总部从巴黎迁到瑞士洛桑。早在1922年,中国奥委会就得到了国际奥委会的承认。 [4]  中国曾派运动员参加了1932年、1936年和1948年的三次奥运会。新中国首次派队参加了1952年在赫尔辛基的第15届奥运会。但不久,当时的时任国际奥委会主席布伦戴奇把台湾列入了国际奥委会所承认的各国奥委会名单之中,企图制造“两个中国”。中国多次抗议交涉无效,于1958年声明中断与国际奥委会的关系。从1946年起,国际奥委会执委会分别与冬、夏季国际单项体育联合会之间不定期举行联席会议;从1952年起,国际奥委会执委会与国家奥委会之间也不定期举行联席会议。1975年,中国奥委会要求国际奥委会恢复在奥林匹克运动中的合法代表权。1979年10月,国际奥委会通过《名古屋决议》,恢复了中国奥委会在国际奥委会的权利,确认中国为“中国奥委会”,使用中华人民共和国国旗和国歌;同时规定设在台北的奥委会为“中华台北奥委会”,使用“不同于其使用的旗、徽和歌”。会址设在台北的奥委会改名为“CHINESE TAIPEI OLYMPIC COMMITTEE”。大陆方面自此将“CHINESE TAIPEI”翻译为“中国台北”。何振梁于1981年和1985年当选为国际奥委会委员和执委会委员。1985年,国际奥委会启动奥林匹克全球伙伴计划(TOP计划),四年一期,实施TOP营销计划实施以来,这项收入不断攀升,并逼近电视转播权收入。1986年,国际奥委会授予中国奥委会奥林匹克杯,以表彰中国对发展中国家,特别是对非洲国家体育援助作出的巨大贡献。1989年8月,何振梁当选为国际奥委会副主席,这是中国人首次担任这个职务。 [5]  1993年,中国奥委会曾向国际奥委会提出了北京举办2000年奥运会的申请,但最后以2票之差而落选。1993年6月20日,国际奥委会执委会决定暂时承认马其顿为其成员。同年9月,巴勒斯坦被接受为临时委员。1993年9月,布隆迪、佛得角、科摩罗群岛、圣多美和普林西比、多米尼加等被接纳为新成员。1994年6月,瑙鲁加入国际奥委会。1994年8月29日至9月3日,第12届奥林匹克代表大会在巴黎召开,它也是现代奥林匹克运动恢复100周年的庆祝活动的一部分。参加本届大会的代表共有3427人,其中:国际奥委会委员和名誉委员101人;来自 48个国际单项体联的代表132人;来自191个国家或地区奥委会的代表407人;运动员代表67人;记者代表738人。在大会上发言的共达439人次。1995年7月,柬埔寨、几内亚比绍加入国际奥委会。1996年,国际奥委会与联合国粮农组织(FAO)签署了合作协议,双方愿采取积极具体措施为全球农村地区的人口谋取福利。国际奥委会与奔驰汽车公司就在6个非洲国家体育发展签订了一项耗资600万马克的“非洲奥林匹克计划”。1997年和1998年间,国际奥委会曾通过中国奥委会的协助,两次向朝鲜民主主义人民共和国体育界提供了食品援助。另外,国际奥委会还向巴塞罗那市签署合同,帮助重建萨拉热窝的扎特拉体育设施。1997年3月5日,国际奥委会同美国广播公司(NBC)签署了价值23亿美元电视转播权合同。根据协议,国际奥委会授予NBC在美国境内转播2004年奥运会、2006年冬奥会和2008年奥运会的权利,5月,国际奥委会和悉尼奥运会组委会共同与欧洲广播公司(EBU)签署了价值3.5亿美元的合同。另外,国际奥委会还制定了一项“奥林匹克计划”(TDP),利用五环标志和各国奥委会的会徽和名称进行市场销售。这一计划的实施,使得各国奥委会、尤其是发展中国家奥委会均能从中受益。 [6]  1997年7月3日,国际奥委会主席萨马兰奇宣布香港将以"中国香港"的名义参加奥运会。1998年12月,帕劳、厄立特里亚加入国际奥委会。1999年1月6日,中国奥委会全会在北京召开,决定由北京再次代表中国申办2008年第29届奥运会。1999年2月,国际奥委会在洛桑召开了世界反兴奋剂大会。大会通过了《洛桑宣言》,决定成立一个世界性的、独立的世界反兴奋剂组织(WADA)。国际奥委会承诺向该机构提供2500万美元的资金。1999年10月,在雅典召开的国际奥委会执委会决定:每四年在奥运会的发祥地举办一届世界青年节。2000年3月6日,国际奥委会在巴黎授予中国女子足球队“妇女和体育奖”。2001年7月,在第112届国际奥委会全会上,北京赢得了2008年奥运会主办权。在国际奥委会的倡议之下,2001年第56届联合国代表大会通过了一项由世界上170多个国家提出的题为“通过体育和奥林匹克理想来建立一个和平和更加美好的世界”的决议,呼吁在2002年盐湖城冬季奥运会期间实现“奥林匹克休战”。2003年7月,第115届国际奥委会全会于在布拉格召开,经过两轮投票,温哥华最后以56票胜出成为2010年第21届冬季奥运会举办城市。2004年,印度尼西亚的国际奥委会委员哈桑因涉嫌在一起建设工程中进行非法活动被判刑。同年8月他被赶出了国际奥委会。2005年,前国际奥委会副主席、韩国人金云龙被迫辞职。起因是他已经由于涉嫌韩国的体育-金钱腐败案件而被停职。为了避免被奥委会驱逐他不得不选择辞职。2004年,保加利亚国际奥委会委员伊万·斯拉夫科夫涉嫌腐败活动,被赶出了国际奥委会。2005年12月,国际奥委会委员,法国前体育部长和1976年蒙特利尔奥运会110米栏金牌得主德鲁特因为腐败案件被停职。 [7]  2006年15日,韩国籍国际奥委会委员朴永圣因为涉嫌挪用公款,已经被暂时剥夺了委员资格。国际奥委会在一份声明中说,在国际奥委会道德委员会对朴永圣调查期间,朴永圣“一切与国际奥委会委员资格有关的权利都将被暂时剥夺”。2011年7月8日,鉴于荷属安的列斯群岛已于2010年10月10日正式解散,国际奥委会第123次全会据此取消荷属安的列斯群岛的国家奥委会资格,同时批准了一系列相应措施,以尽可能保护该国运动员的利益,尤其是参与2012年伦敦奥运会的相关权益。 [8]  2013年9月9日,国际奥委会第125次全会在阿根廷首都布宜诺斯艾利斯投票选出了新一任的国际奥委会主席。最终来自德国的托马斯·巴赫从6名候选人中胜出,成为第九任国际奥委会主席,任期8年。上一任主席雅克·罗格退休。同时经过两轮投票,东京获得2020年夏季奥运会主办权。这是东京在1964年首次举办夏季奥运会后再获举办权。 [9]  2013年12月7日,国际奥委会主席巴赫表示,如果印度不能遵守奥林匹克反腐败规定将面临被开除会籍的下场。 [10]  2014年5月9日,国际奥委会发布公告,美国全国广播公司(NBC)与其签署了一份价值75亿美元的协议,获得了从2021到2032年间奥运会的独家转播权。协议还要求,NBC需另外支付1亿美元,用于2015至2020年间多项体育运动的推广。进入21世纪,NBC便一直独享奥运会转播权,其在2011年签署的一份文件就以44亿美元取得了从2014到2020年间历届奥运会的转播权。 [11]  2015年12月,国国际奥委会在官方网站正式宣布了反腐监督热线——这在历史上是前所未有的。决定将从2016年开始,对各国际体育组织实施财政和管理审计,审计将在第三方独立组织的主持下进行,包括国际奥委会和奥林匹克运动会组织委员会也包括在内。 [12]  2014年12月8日,在摩纳哥国际奥委会第127次全会表决了这一名为《奥林匹克2020议程》的改革提案,获全票通过(104名国际奥委会委员96人与会、8人缺席)。国际奥委会的奥运改革拉开序幕。全会同时投票,正式接纳科索沃奥委会成为其成员。 [13]  新的申办体系下,国际奥委会将变“申办”为“邀请”,申办城市可于邀请阶段与国际奥委会进行探讨,并需将承办奥运会融入其自身的发展规划中,而不是反向为之,国际奥委会甚至允许跨城、跨境联合申办,只不过巴赫称那须得是“特殊情况下的特事特办”。在新的奥运设项规则下,国际奥委会变大项基础制为小项基础制,不再将设项局限于28个大项,而是通过规定运动员、官员和小项的总数上限来实现规模控制,其中夏季奥运会的“帽”是10500名运动员、310个小项,冬奥会则为2900名运动员和100个小项。东道主将在增项议题上拥有更多主动权。 [14-15]  2015年7月31日,国际奥委会第128次全会在吉隆坡举行,经过85位国际奥委会委员的投票,国际奥委会主席巴赫宣布,北京获得2022年冬季奥运会举办权。北京成为首个同时主办夏季奥运会和冬季奥运会的城市,瑞士西南部城市洛桑则获得了2020年青冬奥会的举办权。 [16]  2015年8月2日,通过由国际奥委会所有协会成员参与的投票决定,南苏丹得到国际奥委会的最终认可,成为奥林匹克大家庭的最新成员,也就是第206名成员国。 [17]  2016年6月3日,国际奥委会发表公报宣布组成难民奥林匹克运动队,以迎接即将到来的里约奥运会。这支难民奥林匹克运动队由10名运动员组成,其中包括5名南苏丹难民、2名叙利亚难民、2名刚果(金)难民和1名埃塞俄比亚难民。他们将参加里约奥运会田径、游泳和柔道等项目的比赛。 [18]  全会同时表决通过了空手道、滑板、竞技攀岩、冲浪和棒垒球这5大项运动进入2020年东京奥运会的竞赛项目。 [19]  2017年7月11日,国际奥委会130届全会举行投票,一致决定2024年和2028年夏季奥运会的承办城市将同时产生,唯一的悬念是两个申办城市洛杉矶和巴黎谁先举办。 [20]  2019年6月23日,国际奥委会在瑞士洛桑举行国际奥委会新总部的揭幕。 [21] 
收起全文
精华内容
参与话题
问答
  • IOC的相关理解总结

    万次阅读 多人点赞 2020-04-20 13:54:07
    一、对IOC和DI的基本认识 (一)理解IoC,即“控制反转” (二)IoC具体做什么? (三)理解IoC和DI的关系 二、对IOC容器初始化的理解 四、对DI依赖注入的理解(主要是) 参考书籍、文献和资料 一、对IOC和DI...

    目录

    当前没有去添加对应的源码,只是自己的一些总结,可能理解有错误或不到位,还请指出。

    一、对IOC和DI的基本认识

    (一)理解IoC,即“控制反转”

    (二)IoC具体做什么?

    (三)理解IoC和DI的关系

    二、对IOC容器初始化的理解

    三、对DI依赖注入的理解

    参考书籍、文献和资料


    当前没有去添加对应的源码,只是自己的一些总结,可能理解有错误或不到位,还请指出。

    一、对IOC和DI的基本认识

    (一)理解IoC,即“控制反转”

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

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

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

    (二)IoC具体做什么?

    IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。

    • 传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;
    • 有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
    • IoC对编程实现由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找

    (三)理解IoC和DI的关系

    DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

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

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

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

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

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

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

    二、对IOC容器初始化的理解

    IOC容器初始化的基本步骤主要是两个方面:

    • 初始化的入口由容器实现中的refresh()方法调用来完成。
    • 对Bean定义载入IOC容器使用的方法是loadBeanDefinition()。

    大致过程如下:

    • 通过ReasourceLoader来完成资源文件的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现,可以通过类路径、文件系统、URL等方式来定位资源
    • 如果XmlBeanFactory作为IOC容器,那么需要为它指定Bean定义的资源,也就是说Bean定义文件是通过抽象成Resource来被IOC容器处理,容器通过BeanDefinitionReader来完成定义信息的解析和Bean信息的注册,往往使用XmlBeanDefinitionReader来解析Bean的XML定义文件---实际的处理过程是委托给BeanDefinitionParserDelegate来完成的,从而得到Bean的定义信息,这些信息在Spring中使用BeanDefinition来表示(这个名字可以让我们想到loadBeanDefinition()、registerBeanDefinition()这些相关的方法,他们都是为处理BeanDefinition服务的)。
    • 解析得到BeanDefinition以后,需要在IOC容器中注册,这由IOC实现BeanDefinitionRegister接口来实现,注册过程就是在IOC容器内容维护一个HashMap来保存得到的BeanDefinition的过程,这个HashMap是IOC容器持有Bean信息的场所,以后Bean的操作都是围绕这个HashMap来实现
    • 之后我们通过BeanFactory和ApplicationContext来享受Spring IOC的服务了,在使用IOC容器的时候我们注意到,除了少量粘合代码,绝大多数以正确IOC风格编写的应用程序代码完全不关心如何到达工厂,因为容器将把这些对象与容器管理的其他对象钩在了一起,基本的策略是把工厂放到已知的地方,最好放在对预期使用的上下文有意义的地方,以及代码要实际访问工厂的地方。
    • Spring本身提供了对声明式载入Web应用程序用法的应用程序上下文,并将其存储在ServletContext的框架实现中

    三、对DI依赖注入的理解

    当Spring IOC容器完成了Bean定义资源的定位、载入和解析注册,IOC容器就可以管理Bean定义的相关数据了,但是此时IOC容器还没有对所管理的Bean进行依赖注入,依赖注入 在以下两种情况下发生:

    • 用户第一次调用getBean()方法时,IOC容器触发依赖注入。
    • 当用户在配置文件中将<bean>元素配置了lazy-init=false属性时,即让容器在解析注册Bean定义时进行预实例化,触发依赖注入。

    Beanfactory接口定义了Spring IOC容器的基本功能规范,是Spring IOC容器所应遵守的最低层和最基本的编程规范。BeanFactory接口中定义了几个getBean()方法,用于用户向IOC容器索取被管理的Bean的方法,通过分析其子类的具体实现来理解Spring IOC容器在用户索取Bean时如何完成依赖注入

    • getBean方法肯定不陌生,必经之路,然后调用doGetBean,进来以后首先会执行transformedBeanName找别名,看你的Bean上面是否起了别名。然后进行很重要的一步,getSingleton,这段代码就是从你的单例缓存池中获取Bean的实例。那么你第一次进来肯定是没有的,缓存里肯定是拿不到的。也就是一级缓存里是没有的。那么它怎么办呢?他会尝试去二级缓存中去拿,但是去二级缓存中拿并不是无条件的,首先要判断isSingletonCurrentlyInCreation(beanName)他要看你这个对象是否正在创建当中,如果不是直接就退出该方法,如果是的话,他就会去二级缓存earlySingletonObjects里面取,如果没拿到,它还接着判断allowEarlyReference这个东西是否为true。它的意思是说,是否允许让你从单例工厂对象缓存中去拿对象。默认为true。好了,此时如果进来那么就会通过singletonFactory.getObject()去单例工厂缓存中去拿。然后将缓存级别提升至二级缓存也就早期暴露的缓存。
    • getSingleton执行完以后会走dependsOn方法,判断是否有dependsOn标记的循环引用,有的话直接卡死,抛出异常。比如说A依赖于B,B依赖于A 通过dependsOn注解去指定。此时执行到这里就会抛出异常。这里所指并非是构造函数的循环依赖。
    • beforeSingletonCreation在这里方法里,就把你的对象标记为了早期暴露的对象,提前暴露对象用于创建Bean的实例
    • 紧接着就走创建Bean的流程开始。在创建Bean之前执行了一下resolveBeforeInstantiation。它的意思是说,代理AOPBean定义注册信息但是这里并不是实际去代理你的对象,因为对象还没有被创建。只是代理了Bean定义信息,还没有被实例化把Bean定义信息放进缓存,以便我想代理真正的目标对象的时候,直接去缓存里去拿。
    • 接下来就真正的走创建Bean流程,首先走进真正做事儿的方法doCreateBean然后找到createBeanInstance这个方法,在这里面它将为你创建你的Bean实例信息(Bean的实例)。如果说创建成功了,那么就把你的对象放入缓存中去(将创建好的提前曝光的对象放入singletonFactories三级缓存中)将对象从二级缓存中移除因为它已经不是提前暴露的对象了。但是。如果说在createBeanInstance这个方法中在创建Bean的时候它会去检测你的依赖关系,会去检测你的构造器。然后,如果说它在创建A对象的时候,发现了构造器里依赖了B,然后它又会重新走getBean的这个流程,当在走到这里的时候,又发现依赖了A此时就会抛出异常。为什么会抛出异常,因为,走getBean的时候他会去从你的单例缓存池中去拿,因为你这里的Bean还没有被创建好。自然不会被放进缓存中,所以它是在缓存中拿不到B对象的。反过来也是拿不到A对象的。造成了死循环故此直接抛异常。这就是为什么Spring IOC不能解决构造器循环依赖的原因因为你还没来的急放入缓存你的对象是不存在的。所以不能创建。同理@Bean标注的循环依赖方法也是不能解决的,跟这个同理。那么多例就更不能解决了。为什么?因为在走createBeanInstance的时候,会判断是否是单例的Bean定义信息mbd.isSingleton();如果是才会进来。所以多例的Bean压根就不会走进来,而是走了另一段逻辑,这里不做介绍。至此,构造器循环依赖和@Bean的循环依赖还有多例Bean的循环依赖为什么不能解决已经解释清楚。然后如果说,Bean创建成功了。那么会走后面的逻辑。
    • 将创建好的Bean放入缓存,addSingletonFactory方法就是将你创建好的Bean放入三级缓存中,并且移除早期暴露的对象。
    • 通过populateBean给属性赋值,我们知道,创建好的对象,并不是一个完整的对象,里面的属性还没有被赋值。所以这个方法就是为创建好的Bean为它的属性赋值。并且调用了我们实现的的XXXAware接口进行回调初始化,然后调用我们实现的Bean的后置处理器,给我们最后一次机会去修改Bean的属性

    参考书籍、文献和资料

    1.https://www.iteye.com/blog/jinnianshilongnian-1413846

    2.《Sring 5 核心原理与30个类手写实战》,谭勇徳,中国公信出版社,2019.

    展开全文
  • 浅谈 IOC 什么是 IOC

    万次阅读 多人点赞 2019-05-27 14:19:26
    本文以文字为主题,并没有代码案例,仅限于记录自己对于 IOC 的理解,文中也啥特别高深的东西,大牛和大佬可以忽略本文,以免浪费您宝贵的时间 什么是 IOCIOC (Inversion Of Control,控制倒转),是spring...

    本文以文字为主题,并没有代码案例,仅限于记录自己对于 IOC 的理解,文中也啥特别高深的东西,大牛和大佬可以忽略本文,以免浪费您宝贵的时间

    什么是 IOC ?

         IOC (Inversion Of Control,控制倒转),是spring的核心,贯穿始终,所谓IOC ,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。所有的类都会在spring容器中登记,告诉spring你是个什么,你需要什么,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

    IOC 的主要作用是什么?

         IOC 理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦,那么问题来了,什么是解耦呢?

    扩充话题

         解耦通俗地说就是两个东西原来互相影响,现在让他们独立发展,核心思想还是最小职责,每个地方都只做一件事情,只要一个地方负责了多项事情,就存在解耦的可能。在系统每个层次都可以体现解耦的思想,比如在架构层面把存储和业务逻辑解耦,把动态页面和静态页面解耦,在模块层面把业务模块和统计模块解耦,在代码层面把多个功能解耦等等。解耦的思想很好,但是没必要为了解耦而解耦,还是要从业务需求以及系统定位出发,满足一段时间内系统发展的需要即可。简单通俗的理解就是,电脑拔掉鼠标键盘显示器依然可以运行,这就是解耦。

    什么是控制反转?

         就相当于,假如有 a 和 b 两个对象,在注入 IOC 之前,a 依赖于 b 那么对象 a 在初始化或者运行到某一点的时候,自己必须主动去创建对象 b 或者使用已经创建的对象 b ,无论是创建还是使用对象 b ,控制权都在自己手上 ,而注入 IOC 之后就变了,对象 a 与对象 b 之间失去了直接联系,当对象 a 运行到需要对象 b 的时候,IOC 容器会主动创建一个对象 b 注入到对象 a 需要的地方。其实通过上边这个举例可以很明显的就看出来,对象 a 获得依赖对象 b 的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

    什么是依赖注入?

         依赖注入让 bean 与 bean 之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起,其实依赖注入和控制反转是同一个概念,不管是依赖注入,还是控制反转,都采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。相当于将需要的接口实现注入到需要它的类中,这可能就是“依赖注入”说法的来源了,其实上边控制反转中的例子已经将这两个都包括了

    IOC  可以给我们带来什么好处?

        IOC 的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理。

            第一,资源集中管理,实现资源的可配置和易管理

            第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度

        其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。IoC很好的体现了面向对象设计法则之一好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找

     

    展开全文
  • IOC

    千次阅读 2018-05-19 11:51:46
    [IOC] 1. ioc 简介 1.1 ioc 定义 ioc (Inversion of Control, 控制反转)把创建对象的操作交给框架,亦被称为 DI(Dependency Injection, 依赖注入)。 为什么叫做 “控制反转” 呢?之前,我们想要一个对象...

    [IOC]

    1. ioc 简介

    1.1 ioc 定义

    ioc (Inversion of Control, 控制反转)把创建对象的操作交给框架,亦被称为 DI(Dependency Injection, 依赖注入)。

    为什么叫做 “控制反转” 呢?之前,我们想要一个对象都是 new 出来的,天天需要 new 对象是不是感觉有点麻烦。有人就想到了,把这些简单重复的工作也交给框架做。本来需要我们向框架 “射入” 对象,现在框架自己能产生对象了,这不正是 控制反转 吗?于是,就有了这个响亮的名字。

    1.2 ioc 目标

    其实定义中已经把 ioc 的目标说清楚了。这里,再强调一下:把创建对象的操作交给框架,“解放程序员的生产力”。

    下面代码是 ioc 的使用用例,它可实现 customerService 变量的自动注入。本文的目标是实现 ioc ,也就是使得下面代码可用。

        // 使用了基于注解实现的 ioc 代码
        @Controller
        public class CustomerController {
    
            // 这里可以自动注入 CustomerService 对象
            @InJect
            private CustomerService customerService;
    
            ...
    
        }
    

    ioc 的实现主要有两种形式:1)声明式;2)注解。其中,声明式是基于 xml 配置文件来做的,这种方式对 jdk 版本无要求,兼容性强,但相注解方式较冗杂;而注解方式,需要 jdk1.5 以上(因为从 jdk1.5 才有了注解),但它更灵活、更简洁。鉴于现在很少有人在使用 jdk1.5 之前的版本,本文将基于注解实现 ioc

    2. ioc 实现

    2.1 实现关键

    1. 如何标识出类中哪些变量需要注入;
    2. 怎样生成可用于注入的对象实例以及如何存储它们;
    3. 何时注入;

    2.2 详细过程

    1) 创建注解 InJect 用它标识类中需要注入的属性;

        // InJect.java
        package top.inotwant.annocation;
    
        import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;
    
        @Target(ElementType.FIELD)  // 元注解,表示 InJect 作用于属性之上
        @Retention(RetentionPolicy.RUNTIME) // 元注解,用于描述 InJect 生存周期
        public @interface InJect {
        }

    2) 创建 Controller Service 注解,它们都作用于类上(比如,1.2 节中 @Controller 作用于 CustomerController 之上)。被它们修饰的类将要求产生对象实例,这个过程将会用到 反射,下面再详细描述该过程。(使用过 Spring 框架的是不是对这两个注解很熟悉)

        // Controller.java
        package top.inotwant.annocation;
    
        import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;
    
        @Target(ElementType.TYPE)   // 元注解,表示 Controller 作用于类之上
        @Retention(RetentionPolicy.RUNTIME)
        public @interface Controller {
    
        }
    
        // Service.java
        package top.inotwant.annocation;
    
        import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;
    
        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface Service {
    
        }

    3) 自定义类加载器加载包下的所有 java 文件,并从中获取被上面两个注解之一修饰的类的元类 Class<?> 有了这些元类,我们就可以使用反射产生对应的对象实例了。

    ClassUtil 工具类中的 loadClassSet(String packageName) 静态方法实现了该逻辑。它将返回 packageName 指定的包下所有类的元类。

    ClassHelper 帮助类实现了对上面两个注解之一修饰类的元类的抽取。

        // ClassUtil.java
        package top.inotwant.utils;
    
        import java.io.File;
        import java.io.FileFilter;
        import java.io.IOException;
        import java.net.JarURLConnection;
        import java.net.URL;
        import java.util.Enumeration;
        import java.util.HashSet;
        import java.util.Set;
        import java.util.jar.JarEntry;
        import java.util.jar.JarFile;
    
        public final class ClassUtil {
    
            /**
             * 获取类加载器
             */
            public static ClassLoader getClassLoader() {
                return Thread.currentThread().getContextClassLoader();
            }
    
            /**
             * 加载指定类
             */
            public static Class<?> loadClass(String className) {
                try {
                    // TODO 注意 class.forName 与 ClassLoader.loadClass 的区别(关于 static 是否静态初始化)
                    // 注意第二个参数,一定要设置为 true 。否则,在加载类时不会运行 static 块,这将影响一部分类的初始化。
                    return Class.forName(className, true, getClassLoader());
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
    
            /**
             * 加载包下所有类
             * @param packageName 为包名,比如 “top.inotwant.sample”
             */
            public static Set<Class<?>> loadClassSet(String packageName) {
                String packagePath = packageName.replace(".", "/");
                try {
                    Set<Class<?>> result = new HashSet<>();
                    // getResources 的使用请看 API
                    Enumeration<URL> resources = getClassLoader().getResources(packagePath);
                    while (resources.hasMoreElements()) {
                        URL currentURL = resources.nextElement();
                        if ("file".equals(currentURL.getProtocol())) {
                            String path = currentURL.getPath().replaceAll("%20", " ");
                            addClass(path, packageName, result);
                        } else if ("jar".equals(currentURL.getProtocol())) {    // 此处为了加载文件夹下 `jar` 中所包含的所有类文件,若不理解可忽略此处,不影响总体
                            JarURLConnection conn = (JarURLConnection) currentURL.openConnection();
                            JarFile jarFile = conn.getJarFile();
                            Enumeration<JarEntry> entries = jarFile.entries();
                            while (entries.hasMoreElements()) {
                                JarEntry jarEntry = entries.nextElement();
                                String jarEntryName = jarEntry.getName();
                                if (jarEntryName.endsWith(".class")) {
                                    String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                                    result.add(loadClass(className));
                                }
                            }
                        }
                    }
                    return result;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
    
            private static void addClass(String path, String packageName, Set<Class<?>> result) {
                File[] files = new File(path).listFiles(new FileFilter() {
                    @Override
                    public boolean accept(File file) {
                        return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
                    }
                });
                if (files != null) {
                    for (File file : files) {
                        if (file.isFile()) {
                            String subFileName = file.getName();
                            String className = subFileName.substring(0, subFileName.lastIndexOf("."));
                            result.add(loadClass(packageName + "." + className));
                        } else if (file.isDirectory()) {
                            // 递归
                            addClass(file.getAbsolutePath(), packageName + "." + file.getName(), result);
                        }
                    }
                }
            }
        }
    
    
        // ClassHelper.java
        package top.inotwant.helper;
    
        import top.inotwant.annocation.Controller;
        import top.inotwant.annocation.Service;
        import top.inotwant.utils.ClassUtil;
    
        import java.util.HashSet;
        import java.util.Set;
    
        /**
         * Class 帮助类
         */
        public final class ClassHelper {
    
            private static Set<Class<?>> CLASS_SET;
    
            static {
                String basePackage = "指定包";
                CLASS_SET = ClassUtil.loadClassSet(basePackage);
            }
    
            /**
             * 加载 base package 下的所有类
             */
            public static Set<Class<?>> getClassSet() {
                return CLASS_SET;
            }
    
            /**
             * 获取加载的由 service 标注的所有类
             */
            public static Set<Class<?>> getServiceClassSet() {
                Set<Class<?>> result = new HashSet<>();
                for (Class<?> clazz : CLASS_SET) {
                    if (clazz.isAnnotationPresent(Service.class))
                        result.add(clazz);
                }
                return result;
            }
    
            /**
             * 获取加载的由 controller 标注的所有类
             */
            public static Set<Class<?>> getControllerClassSet() {
                Set<Class<?>> result = new HashSet<>();
                for (Class<?> clazz : CLASS_SET) {
                    if (clazz.isAnnotationPresent(Controller.class))
                        result.add(clazz);
                }
                return result;
            }
    
            /**
             * 获取框架管理的 bean (包含, service controller)
             */
            public static Set<Class<?>> getBeanClassSet() {
                Set<Class<?>> result = new HashSet<>();
                result.addAll(getServiceClassSet());
                result.addAll(getControllerClassSet());
                return result;
            }
        }

    4) 利用上面的元类,使用反射生成它们对应的对象实例。

    BeanHelper 中的静态块中实现这个逻辑。这些对象实例中包含了可用于注入的(与 @Service 对应的),它们被存储在 map 中,以 <Class,Object> 键值对的形式,是不是很容易理解。

        // BeanHelper.java
        package top.inotwant.helper;
    
        import java.util.HashMap;
        import java.util.Map;
        import java.util.Set;
    
        /**
         * bean 帮助类
         */
        public final class BeanHelper {
    
            private final static Map<Class<?>, Object> BEAN_MAP = new HashMap<>();
    
            static {
                Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet();
                for (Class<?> clazz : beanClassSet) {
                    BEAN_MAP.put(clazz, getInstance(clazz));
                }
            }
    
            /**
             * 获取类对应的实例
             */
            @SuppressWarnings("unchecked")
            private static <T> T getInstance(Class<?> clazz) {
                try {
                    return (T) clazz.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
    
            /**
             * 获取 bean 映射
             */
            public static Map<Class<?>, Object> getBeanMap() {
                return BEAN_MAP;
            }
    
            /**
             * 获取 bean
             */
            @SuppressWarnings("unchecked")
            public static <T> T getBean(Class<T> clazz) {
                Object obj = BEAN_MAP.get(clazz);
                if (obj != null)
                    return (T) obj;
                else {
                    throw new RuntimeException("can't get bean by class: " + clazz.getSimpleName());
                }
            }
        }
    

    5) 注入

    IocHelper 帮助类的 static 块中完成最后一步 注入。其中的逻辑很简单,我们把所有的 bean 遍历一遍,每一次迭代查看该 bean 的各个属性是否标注 InJect 。如果标注了,就从 beanMap 中获取相应的对象实例进行注入。

        package top.inotwant.helper;
    
        import top.inotwant.annocation.InJect;
        import top.inotwant.utils.ArrayUtil;
        import top.inotwant.utils.CollectionUtil;
        import top.inotwant.utils.ReflectUtil;
    
        import java.lang.reflect.Field;
        import java.util.Map;
    
        /**
         * ioc 实现类
         */
        public final class IocHelper {
    
            static {
                Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
                if (CollectionUtil.isNotEmpty(beanMap)) {   // 判断集合是否为空
                    for (Map.Entry<Class<?>, Object> entry : beanMap.entrySet()) {
                        Class<?> clazz = entry.getKey();
                        Object obj = entry.getValue();
                        // TODO 切勿调成 getFields() ,它不能获取私有属性
                        Field[] fields = clazz.getDeclaredFields();
                        if (ArrayUtil.isNotEmpty(fields)) { // 判断数组是否
                            for (Field field : fields) {
                                if (field.isAnnotationPresent(InJect.class)) {
                                    Object newValue = BeanHelper.getBean(field.getType());
                                    ReflectUtil.modifyField(obj, field, newValue);  // 注入
                                }
                            }
                        }
                    }
                }
            }
    
        }

    6) 初始化 ioc

    前面 5 步已经实现了 ioc,并且可通过系统初始化时加载 IocHelper.class 让它起到作用(想一想为什么只需要加载一个类就可以?)。但是,我建议再创建如下一个类,让加载更集中、初始化的逻辑更清晰。

        package top.inotwant;
    
        import top.inotwant.helper.*;
        import top.inotwant.utils.ClassUtil;
    
        /**
         * 加载相关的 helper 类
         */
        public final class HelperLoader {
    
            public static void init() {
                Class<?>[] classes = {
                        ClassHelper.class,
                        BeanHelper.class,
                        IocHelper.class
                };
                for (Class<?> clazz : classes) {
                    ClassUtil.loadClass(clazz.getName());
                }
            }
        }

    至此,1.2 节中的代码已经可以使用。

    3. 参考

    架构探险(张勇)

    展开全文
  • Ioc

    2007-07-19 12:45:00
    控制反转(Ioc)模式(又称DI:Dependency Injection)就是Inversion of Control,控制反转。在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。 IoC(Inversion of ...
     控制反转Ioc模式(又称DI:Dependency Injection)就是Inversion of Control,控制反转。在Java开发中,IoC意味着将你设计好的交给系统去控制,而不是在你的类内部控制。这称为控制反转。
    

          IoC(Inversion of Control)是近年来兴起的一种思想,不仅仅是编程思想。主要是协调各组件间相互的依赖关系,同时大大提高了组件的可移植性,组件的重用机会也变得更多。在传统的实现中,由程序内部代码来控制程序之间的关系。我们经常使用new关键字来实现两组键间关系的组合,这种实现的方式会造成组件之间耦合(一个好的设计,不但要实现代码重用,还要将组件间关系解耦)。IoC很好的解决了该问题,它将实现组件间关系从程序内部提到外部容器来管理。也就是说由容器在运行期将组件间的某种依赖关系动态的注入组件中。控制程序间关系的实现交给了外部的容器来完成。即常说的好莱坞原则“Don't call us, we'll call you”。

          Ioc也有称为DI(Dependecy Injection 依赖注射),由Martin Fowler的一篇《Inversion of Control Containers and the Dependency Injection pattern》提出。


      分离关注( Separation of Concerns : SOC)是Ioc模式和AOP产生最原始动力,通过功能分解可得到关注点,这些关注可以是 组件Components, 方面Aspects或服务Services。

      从GoF设计模式中,我们已经习惯一种思维编程方式:Interface Driven Design 接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:

      AInterface a = new AInterfaceImp();

      AInterfaceImp是接口AInterface的一个子类,Ioc模式可以延缓接口的实现,根据需要实现,有个比喻:接口如同空的模型套,在必要时,需要向模型套注射石膏,这样才能成为一个模型实体,因此,我们将人为控制接口的实现成为“注射”。

      Ioc英文为 Inversion of Control,即反转模式,这里有著名的好莱坞理论:你呆着别动,到时我会找你。

      其实Ioc模式也是解决调用者和被调用者之间的一种关系,上述AInterface实现语句表明当前是在调用被调用者AInterfaceImp,由于被调用者名称写入了调用者的代码中,这产生了一个接口实现的原罪:彼此联系,调用者和被调用者有紧密联系,在UML中是用依赖 Dependency 表示。

      但是这种依赖在分离关注的思维下是不可忍耐的,必须切割,实现调用者和被调用者解耦,新的Ioc模式 Dependency Injection 模式由此产生了, Dependency Injection模式是依赖注射的意思,也就是将依赖先剥离,然后在适当时候再注射进入。

    一、Ioc模式(Dependency Injection模式)有三种:

          第一种类型 从JNDI或ServiceManager等获得被调用者,这里类似ServiceLocator模式。 1. EJB/J2EE,2. Avalon(Apache的一个复杂使用不多的项目)
          第二种类型 使用JavaBeans的setter方法 1. Spring Framework,2. WebWork/XWork
          第三种类型 在构造方法中实现依赖 1. PicoContainer,2. HiveMind

      有过EJB开发经验的人都知道,每个EJB的调用都需要通过JNDI寻找到工厂性质的Home接口,在我的教程EJB是什么章节中,我也是从依赖和工厂模式角度来阐述EJB的使用。

      在通常传统情况下,为了实现调用者和被调用者解耦,分离,一般是通过工厂模式实现的,下面将通过比较工厂模式和Ioc模式不同,加深理解Ioc模式。

    二、工厂模式和Ioc

      假设有两个类B 和 C:B作为调用者,C是被调用者,在B代码中存在对C的调用:

    public class B{
       private C comp;
      ......
    }
     

      实现comp实例有两种途径:单态工厂模式和Ioc。

    工厂模式实现如下:

    public class B{
       private C comp;
      private final static MyFactory myFactory = MyFactory.getInstance();

      public B(){
        this.comp = myFactory.createInstanceOfC();

      }
       public void someMethod(){
        this.comp.sayHello();
      }
      ......
    }
     

    特点:

    每次运行时,MyFactory可根据配置文件XML中定义的C子类实现,通过createInstanceOfC()生成C的具体实例。
    使用Ioc依赖性注射( Dependency Injection )实现Picocontainer如下,B类如同通常POJO类,如下:

    public class B{
       private C comp;
      public B(C comp){
        this.comp = comp;
       }
       public void someMethod(){
        this.comp.sayHello();
       }
      ......
    }
     

    假设C接口/类有有一个具体实现CImp类。当客户端调用B时,使用下列代码:

    public class client{
       public static void main( String[] args ) {
        DefaultPicoContainer container = new DefaultPicoContainer();
        container.registerComponentImplementation(CImp.class);
        container.registerComponentImplementation(B.class);
        B b = (B) container.getComponentInstance(B.class);
        b.someMethod();
       }
    }
     

      因此,当客户端调用B时,分别使用工厂模式和Ioc有不同的特点和区别:

      主要区别体现在B类的代码,如果使用Ioc,在B类代码中将不需要嵌入任何工厂模式等的代码,因为这些工厂模式其实还是与C有些间接的联系,这样,使用Ioc彻底解耦了B和C之间的联系。

      使用Ioc带来的代价是:需要在客户端或其它某处进行B和C之间联系的组装。

      所以,Ioc并没有消除B和C之间这样的联系,只是转移了这种联系。
      这种联系转移实际也是一种分离关注,它的影响巨大,它提供了AOP实现的可能。

    Ioc和AOP
      AOP我们已经知道是一种面向切面的编程方式,由于Ioc解放自由了B类,而且可以向B类实现注射C类具体实现,如果把B类想像成运行时的横向动作,无疑注入C类子类就是AOP中的一种Advice,如下图:

     

      通过下列代码说明如何使用Picocontainer实现AOP,该例程主要实现是记录logger功能,通过Picocontainer可以使用简单一行,使所有的应用类的记录功能激活。

    首先编制一个记录接口:

    public interface Logging {

      public void enableLogging(Log log);

    }
     

    有一个LogSwitcher类,主要用来激活具体应用中的记录功能:

    import org.apache.commons.logging.Log;
    public class LogSwitcher
    {
      protected Log m_log;
      public void enableLogging(Log log) {
        m_log = log;
        m_log.info("Logging Enabled");
      }
    }

    一般的普通应用JavaBeans都可以继承这个类,假设PicoUserManager是一个用户管理类,代码如下:

    public class PicoUserManager extends LogSwitcher
    {
      ..... //用户管理功能
    }
    public class PicoXXXX1Manager extends LogSwitcher
    {

      ..... //业务功能
    }
    public class PicoXXXX2Manager extends LogSwitcher
    {

      ..... //业务功能
    }
     

    注意LogSwitcher中Log实例是由外界赋予的,也就是说即将被外界注射进入,下面看看使用Picocontainer是如何注射Log的具体实例的。


    DefaultPicoContainer container = new DefaultPicoContainer();
    container.registerComponentImplementation(PicoUserManager.class);
    container.registerComponentImplementation(PicoXXXX1Manager.class);
    container.registerComponentImplementation(PicoXXXX2Manager.class);
    .....

    Logging logging = (Logging) container.getComponentMulticaster();

    logging.enableLogging(new SimpleLog("pico"));//激活log


     

      由上代码可见,通过使用简单一行logging.enableLogging()方法使所有的应用类的记录功能激活。这是不是类似AOP的advice实现?

      总之,使用Ioc模式,可以不管将来具体实现,完全在一个抽象层次进行描述和技术架构,因此,Ioc模式可以为容器、框架之类的软件实现提供了具体的实现手段,属于架构技术中一种重要的模式应用。J道的JdonSD框架也使用了Ioc模式。

    参考资料:

    Inversion of Control Containers and the Dependency Injection pattern
    A Brief Introduction to IoC
    Ioc容器的革命性优点
    Java企业系统架构选择考量
    IOC模式的思考和疑问

    三、IoC的几种实现类型

    (1)Type1接口注入

    通常做法是利用接口将调用者与实现者分离。
    public class Sport {
    private InterfaceBall ball; //InterfaceBall是定义的接口
    public void init() {
    //Basketball实现了InterfaceBall接口
    ball = (InterfaceBall) Class.forName("Basketball").newInstance();
    }
    }
    Sport类在编译期依赖于InterfaceBall的实现,为了将调用者与实现者分离,我们动态生成Basketball类并通了强制类型转换为InterfaceBall。Apache Avalon是一个典型的Type1型IoC容器。

    (2)setter方法注入

    在类中暴露setter方法来实现依赖关系。
    public class Sport {
    private InterfaceBall ball;
    public void setBall(InterfaceBall arg) {
    ball = arg;
    }
    }
    这种方式对已经习惯了JavaBean的程序员而言,更显直观。Spring就是实现了该类型的轻量级容器。

    (3)Type3构造子注入

    即通过构造方法完成依赖关系。
    public class Sport {
    private InterfaceBall ball;
    public Sport(InterfaceBall arg) {
    ball = arg;
    }
    }
    可以看到,通过类的构造方法建立依赖关系。由于Type3在构造期就形成了对象的依赖关系,即存对象的重用变的困难。有些框架需要组件提供一个默认的构造方法,此时就体现了Type3的局限性。通常所有的参数都是通过构造方法注入的,当对象间的依赖关系较多时,构造方法就显的比较复杂,不利于单元测试。PicoContainer就是实现了Type3依赖注入模式的轻量级容器。

     

     
    展开全文
  • ioc

    2018-09-23 09:29:14
    IOC:比如有一个类,在类中有一个非静态的方法,当我们要在另一个类中去调用这个类的方法,创建这个类的对象,使用对象点的方式去调用方法,创建类对象的过程是new出来的 而ioc不是通过new来创建对象,而是交给...
  • IoC

    2014-03-07 13:20:41
    IoC: Inversion of Control,控制反转, 控制权从应用程序转移到框架(如IoC容器),是框架共有特性   1、为什么需要IoC容器 1.1、应用程序主动控制对象的实例化及依赖装配  Java代码  ...
  • IOC

    2011-05-17 17:06:54
    IOC(控制反转,也叫依赖注入):是一种设计模式而不是编程技术。使用IOC后,我们不需要自己去创建某个类的实例,而由IOC容器去创建,当我们需要使用某个对象时,直接到容器中去获取就可以了。 ...
  • IoCIoC容器基本原理

    千次阅读 2019-06-02 22:10:51
    上一篇学习了IoC的基础知识,明白了IoC是什么,为什么需要使用IoC以及IoC和DI的区别,接下来让我们继续往下学习IoC容器的基本原理。 IoC容器的概念 IoC容器就是具有依赖注入功能的容器,IoC具有负责实例化,定位,...
  • spring ioc

    2019-04-06 14:17:56
    spring ioc什么是spring为什么使用springspring的IOCspring IOC有什么特点 什么是spring Spring是分层的Java SE/EE应用 full-stack轻量级开源框架,以IoC(Inverse Of Control:反转控制)和AOP(Aspect Oriented ...
  • IOC实现原理

    2019-10-15 21:53:17
    对Spring IOC的理解离不开对依赖反转模式的理解,我们知道,关于如何反转对依赖的控制,把控制权从具体业务对象手中转交到平台或者框架中,是解决面向对象系统设计复杂性和提高面向对象系统可测试性的一个有效的解决...
  • Spring原理/SpringMVC原理/IOC/AOP原理

    千次阅读 2019-05-27 10:03:34
    Spring原理/SpringMVC原理/IOC/IOP原理我的微型IOC框架实现 我的微型IOC框架实现 当你打开这本书的时候我要告诉你的第一句话就是认真把前言读完,因为前言概括的本书的大纲以及思想。 本书适合什么读者阅读呢?适合...
  • Spring IOC原理

    2018-09-29 09:44:00
    Spring IOC原理,类的继承关系,依赖注入和控制反转等关系
  • 定义IOC特性 /// <summary> /// IOC类型过滤特性 /// </summary> [AttributeUsage(AttributeTargets.Class)] public class IOCService :Attribute { public IOCService() { } } /// <summary>...
  • Spring5.X源码分析(IOC/AOP)

    万次阅读 2020-05-26 20:15:08
    本文重点考量IOC、AOP的源码实现以及它们之间的内在联系,忽略了其他的散项代码。 IOC加载的三个阶段具体做了那些事?AOP如何基于IOC执行的增强代码?
  • 【Spring-IOC基础】深入浅出Spring-IOC

    万次阅读 2020-04-20 16:20:03
    IOC(Inversion Of Control) 1.概念: 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency ...
  • IoC and Castle.IoC

    千次阅读 2008-03-31 16:51:00
    1. 什么是 IoC ?关于IoC的详细解释请看 Inversion of Control Containers and the Dependency Injection pattern (英文/中文),本文只会作一些简单介绍IoC(Inversion of Control),我们叫它"控制反转",也可以叫它...
  • 浅谈IOC--说清楚IOC是什么

    万次阅读 多人点赞 2018-03-29 16:22:44
    什么是IOC3.IOC也叫依赖注入(DI)4.IOC的优缺点5.IOC容器的技术剖析6.IOC容器的一些产品7.参考博文本文旨在用语言(非代码)说清楚IOC到底是什么,没有什么高深的技术,园中的老牛、大虾们看到这里可以绕行了,以免浪费...
  • SpringIoc

    2017-04-25 18:30:44
    SpringIoc就是控制反转或者叫依赖注入 :就是创建组件和使用分离 有Spring了就在appliContext.xml中配置创建组件 这个xml中的内容就是创建了一个String注入 这个xm中的内容就是创建了一个组件...
  • 架构师之路(39)---IoC框架

    万次阅读 多人点赞 2009-03-08 19:04:00
    1IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。 图1:软件系统中耦合的对象 如果我们打开机械式手表...
  • 谈谈对Spring IOC的理解

    2018-12-06 00:32:23
     学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring...
  • SpringIoc 实现原理

    万次阅读 多人点赞 2019-04-20 16:44:33
    什么是SpringIOC spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合 “控制反转”,不是什么技术,而是一种设计思想...

空空如也

1 2 3 4 5 ... 20
收藏数 86,377
精华内容 34,550
关键字:

ioc