2019独角兽企业重金招聘Python工程师标准>>>

以下整理自http://jinnianshilongnian.iteye.com/blog/1413846,如有侵权立即删除。

Ioc

Ioc(Inversion of Control),即控制反转。不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。 传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;IoC 容器控制了对象(主要控制了外部资源获取,不只是对象包括比如文件等)。
传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

Ioc 容器

IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IoC容器进行组装。在Spring中BeanFactory是IoC容器的实际代表者。

Spring IoC容器如何知道哪些是它管理的对象呢?这就需要配置文件,Spring IoC容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配。一般使用基于xml配置文件进行配置元数据,而且Spring与配置文件完全解耦的,可以使用其他任何可能的方式进行配置元数据,比如注解、基于java文件的、基于属性文件的配置都可以。

Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。简单说, BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。

容器实现一览:

• XmlBeanFactory:BeanFactory实现,提供基本的IoC容器功能,可以从classpath或文件系统等获取资源;
(1) File file = new File("fileSystemConfig.xml");
Resource resource = new FileSystemResource(file);
BeanFactory beanFactory = new XmlBeanFactory(resource);

(2)Resource resource = new ClassPathResource("classpath.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Deprecated. as of Spring 3.1 in favor of DefaultListableBeanFactory and XmlBeanDefinitionReader

• ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");

• FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件。
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");

ApplicationContext接口获取Bean方法简介:

• Object getBean(String name) 根据名称返回一个Bean,客户端需要自己进行类型转换;
• T getBean(String name, Class<T> requiredType) 根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常;
• T getBean(Class<T> requiredType) 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,如果没有或有多于一个Bean存在容器将抛出异常;
• Map<String, T> getBeansOfType(Class<T> type) 根据指定的类型返回一个键值为名字和值为Bean对象的 Map,如果没有Bean对象存在则返回空的Map。

示例:
项目结构图,注意fileSystemConfig.xml的位置。用于文件系统配置的读取

HelloApi.java和HelloImpl.java是一个简单的接口及其实现,打印一句Hello World!,bean.xml和fileSystemConfig.xml内容相同,都只有一句简单的对bean的配置:<bean id="hello" class="cn.nevo.service.impl.HelloImpl"></bean>

测试代码演示了使用不同的Ioc容器实现去读取类路径配置文件和文件系统文件的方式:

public class HelloServiceTest {@SuppressWarnings("deprecation")@Testpublic void testXmlBeanFactoryBaseOnFileSystem() {// 1.准备配置文件,从文件系统获取配置文件,默认是相对路径,可以指定绝对路径File file = new File("fileSystemConfig.xml");Resource resource = new FileSystemResource(file);// 2.初始化容器BeanFactory beanFactory = new XmlBeanFactory(resource);// 2、从容器中获取BeanHelloApi helloApi = beanFactory.getBean("hello", HelloApi.class);// 3、执行业务逻辑helloApi.sayHello();}@SuppressWarnings("deprecation")@Testpublic void testXmlBeanFactoryBaseOnClassPath() {// 1.准备配置文件,从当前类加载路径中获取配置文件Resource resource = new ClassPathResource("bean.xml");// 2.初始化容器BeanFactory beanFactory = new XmlBeanFactory(resource);// 2、从容器中获取BeanHelloApi helloApi = beanFactory.getBean("hello", HelloApi.class);// 3、执行业务逻辑helloApi.sayHello();}@Testpublic void testClassPathXmlApplicationContextBaseOnClassPath() {// 1.准备配置文件,从当前类加载路径中获取配置文件// 2.初始化容器BeanFactory beanFactory = new ClassPathXmlApplicationContext("bean.xml");// 2、从容器中获取BeanHelloApi helloApi = beanFactory.getBean("hello", HelloApi.class);// 3、执行业务逻辑helloApi.sayHello();}@Testpublic void testFileSystemApplicationContextBaseOnFileSystem() {// 1.准备配置文件,从文件系统获取配置文件,默认是相对路径,可以指定绝对路径// 2.初始化容器BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");// 2、从容器中获取BeanHelloApi helloApi = beanFactory.getBean("hello", HelloApi.class);// 3、执行业务逻辑helloApi.sayHello();}
}

IoC容器到底是如何工作。在此我们以xml配置方式来分析一下:
一、准备配置文件:在配置文件中声明Bean定义也就是为Bean配置元数据。
二、由IoC容器进行解析元数据: IoC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IoC容器根据BeanDefinition进行实例化、配置及组装Bean。
三、实例化IoC容器:也就是实例化BeanFactory的各种实现,由客户端实例化容器,获取需要的Bean。

XML配置文件的结构

<beans>  <import resource=”resource1.xml”/>  <bean id=”bean1”class=””></bean>  <bean id=”bean2”class=””></bean>  <bean name=”bean2”class=””></bean>  <alias alias="bean3" name="bean2"/>  <import resource=”resource2.xml”/>
</beans>

1、<bean>标签主要用来进行Bean定义;
2、alias用于定义Bean别名的;
3、import用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“config1.xml”, config2.xml})传给ApplicationContext实现进行加载多个配置文件,那一个更适合由用户决定;这两种方式都是通过调用Bean Definition Reader 读取Bean定义,内部实现没有任何区别。<import>标签可以放在<beans>下的任何位置,没有顺序关系。

Bean

由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean, Bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。那IoC怎样确定如何实例化Bean、管理Bean之间的依赖关系以及管理Bean呢?这就需要配置元数据,在Spring中由BeanDefinition代表,后边会详细介绍,配置元数据指定如何实例化Bean、如何组装Bean等。

Bean的配置

Spring IoC容器目的就是管理Bean,这些Bean将根据配置文件中的Bean定义进行创建,而Bean定义在容器内部由BeanDefinition对象表示,该定义主要包含以下信息:
● 全限定类名(FQN):用于定义Bean的实现类;
● Bean行为定义:这些定义了Bean在容器中的行为;包括作用域(单例、原型创建)、是否惰性初始化及生命周期等;
● Bean创建方式定义:说明是通过构造器还是工厂方法创建Bean;
● Bean之间关系定义:即对其他bean的引用,也就是依赖关系定义,这些引用bean也可以称之为同事bean 或依赖bean,也就是依赖注入。

Bean定义只有“全限定类名”在当使用构造器或静态工厂方法进行实例化bean时是必须的,其他都是可选的定义。难道Spring只能通过配置方式来创建Bean吗?回答当然不是,某些SingletonBeanRegistry接口实现类实现也允许将那些非BeanFactory创建的、已有的用户对象注册到容器中,这些对象必须是共享的,比如使用DefaultListableBeanFactory 的registerSingleton() 方法。不过建议采用元数据定义。

BeanDefinition

spring可以通过xml配置文件定义bean,beanFactory可以创建、查找配置文件中定义的这些bean,spring内部是如何将配置文件中所定义的bean变成可以让beanFactory创建与管理的呢?这是依靠BeanDefinition进行实现。BeanDefinition是一个接口,它描述了一个bean的实例,保存了bean的定义信息,是bean在内存中的描述形式。xml配置文件所定义的每个bean在内存中都有对应的Bedifinition对象进行描述。BeanFactory在查找,创建及管理bean时,会先查找其在内存中所保存的BeanDefinition,然后再根据BeanDefinition中的bean描述内容创建bean或返回所需的bean信息。

根据面向接口编程的原则,spring定义了接口BeanDefinitionRegistry注册管理所有的Bedifinition,实现此接口就可以管理bean的定义,DefaultListableBeanFactory类实现了此接口,因此DefaultListableBeanFactory类及其子类具有管理beanDefinition的功能。

Spring读取分析配置文件,根据配置文件中的定义,为这些bean创建对应的BeanDifinition,并将BeanDifinition注册至beanFactory中(具体表现为注册在DefaultListableBeanFactory类型的beanFactory)。当用户需要使用bean时,将传入bean的名称或类型给beanFactory,beanFactory从其所保存的beanDefinition中查找,当找到符合条件的beanDefinition后,则将根据beanDefinition中的bean信息创建bean对象,并返回给用户。

实例化Bean

Spring IoC容器如何实例化Bean呢?
传统应用程序可以通过new和反射方式进行实例化Bean。而Spring IoC容器则需要根据Bean定义里的配置元数据使用反射机制来创建Bean。在Spring IoC容器中根据Bean定义创建Bean主要有以下几种方式:
1、使用构造器实例化Bean,这是最简单的方式,Spring IoC容器即能使用默认空构造器也能使用有参数构造器两种方式创建Bean
2、使用静态工厂方式实例化Bean,使用这种方式除了指定必须的class属性,还要指定factory-method属性来指定实例化Bean的方法,而且使用静态工厂方法也允许指定方法参数,spring IoC容器将调用此属性指定的方法来获取Bean
3、使用实例工厂方法实例化Bean,使用这种方式不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法,而且使用实例工厂方法允许指定方法参数,方式和使用构造器方式一样

示例:
1、构造器实例化Bean:

package cn.nevo.service.impl;import cn.nevo.service.HelloApi;public class HelloImpl implements HelloApi {private String message;public HelloImpl() {this.message = "Hello World!";}public HelloImpl(String message) {this.message = message;}@Overridepublic void sayHello() {System.out.println(message);}
}

bean.xml

<!-- 使用默认构造参数实例化bean --><bean id="hello" class="cn.nevo.service.impl.HelloImpl"></bean><!-- 使用有参构造参数实例化bean --><bean id="hello2" class="cn.nevo.service.impl.HelloImpl"><constructor-arg index="0" value="New Hello World!"/></bean>

测试

public class HelloServiceTest {@Testpublic void testClassPathXmlApplicationContextBaseOnClassPath() {// 1.准备配置文件,从当前类加载路径中获取配置文件// 2.初始化容器BeanFactory beanFactory = new ClassPathXmlApplicationContext("bean.xml");// 2、从容器中获取BeanHelloApi helloApi = beanFactory.getBean("hello", HelloApi.class);HelloApi helloApi2 = beanFactory.getBean("hello2", HelloApi.class);// 3、执行业务逻辑helloApi.sayHello();helloApi2.sayHello();}
}

2、静态工厂方式实例化Bean
返回HelloImpl实例的静态工厂类HelloImplStaticFactory.java

package cn.nevo.service.impl.staticfactory;import cn.nevo.service.HelloApi;
import cn.nevo.service.impl.HelloImpl;public class HelloImplStaticFactory {public static HelloApi getInstance(String message) {return new HelloImpl(message);}
}

bean.xml

<!-- 使用静态工厂方法实例化bean --><bean id="statichello" class="cn.nevo.service.impl.staticfactory.HelloImplStaticFactory" factory-method="getInstance"><constructor-arg index="0" value="static factory instance"/></bean>

测试

HelloApi helloApi3 = beanFactory.getBean("statichello", HelloApi.class);helloApi3.sayHello();

3、实例工厂方式实例化Bean
用于产生HelloImpl实例的HelloImplInstanceFactory.java

package cn.nevo.service.impl.instancefactory;import cn.nevo.service.HelloApi;
import cn.nevo.service.impl.HelloImpl;public class HelloImplInstanceFactory {public HelloApi getInstance(String message) {return new HelloImpl(message);}
}

bean.xml

<!-- 使用实例工厂方法实例化bean --><bean id="instancehello" class="cn.nevo.service.impl.instancefactory.HelloImplInstanceFactory"/><bean id="instance" factory-bean="instancehello" factory-method="getInstance"><constructor-arg index="0" value="instance factory"/></bean>

测试

HelloApi helloApi4 = beanFactory.getBean("instance", HelloApi.class);helloApi4.sayHello();

转载于:https://my.oschina.net/xiaomaoandhong/blog/69970

Spring Ioc (Inversion of Control)相关推荐

  1. Spring——IOC(Inversion of Control)容器(2)

    IOC(Inversion of Control)容器(2) 文章目录 IOC(Inversion of Control)容器(2) 1.IOC 操作 Bean 管理(FactoryBean) 2.I ...

  2. Java学习笔记-对IoC(Inversion of Control)的基本认识

    目录 基本认识 实例 自己的感悟 基本认识 Ioc:Inversion of Control 控制反转.依赖注入 控制:控制对象(Java Bean)的创建以及销毁(生命周期) 反转:将对象的控制权交 ...

  3. 什么是控制反转(Inversion of Control)

    [2020.11 最后编辑] 要点:IoC是对框架特征的一般性描述:每一种框架用途不一,永远不要问某个框架"哪些方面的控制被反转了呢?"这种愚蠢的问题.JUnit是Java语言著名 ...

  4. springIOC(Inversion of Control)控制反转

    基本概念 IOC与大家熟知的依赖注入同理,这是一个通过依赖注入对象的过程 也就是说,它们所使用的对象,是通过构造函数参数,工厂方法的参数或这是从工厂方法的构造函数或返回值的对象实例设置的属性,然后容器 ...

  5. [Js-Spring]Spring与IoC(控制反转,Inversion of Control)

    控制反转(Ioc,Inversion of Control),是一个概念,一种思想.指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理.控制反转就是对对象控制权的转移,从 ...

  6. 谈谈对Spring IOC(控制反转)的理解--转

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  7. 谈谈对Spring IOC(控制反转)的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  8. Spring IOC(控制反转)的理解

    本文大部分来自:https://www.cnblogs.com/Mr-Rocker/p/7721824.html 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注 ...

  9. 【SSM框架系列】Spring IoC(控制反转) DI(依赖注入)

    Spring是什么 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Orie ...

最新文章

  1. javascript js异步加载
  2. Kolla 让 OpenStack 部署更贴心
  3. Maven+Struts2+MyBatis+Spring搭建教程
  4. (chap6 Http首部) 请求首部字段 Acceptx-Charsetx-Encodingxx-Language
  5. jboss resin tomcat 相关
  6. ASP.NET Core 运行原理解剖[4]:进入HttpContext的世界
  7. LeetCode DD-2020006. 简单游戏(前缀和)
  8. 视觉SLAM笔记(46) 基本的 VO
  9. 中国工业信息安全大会召开,开发新技术与新模式,推动工业互联网安全发展
  10. perf script 执行时间_在Python中准确地测量代码执行时间
  11. 描绘质量属性的六个常见属性场景。
  12. 树莓派 wiringpi 读取引脚_树莓派驱动的无人驾驶开发记录--驱动电机
  13. 折腾黑苹果的正确潜入姿势(系统版本:macOS Catalina 10.15)
  14. 苹果手机无法验证应用怎么办_App Store 提示“需要验证”无法下载应用怎么办?...
  15. 2019念念不忘,2020必有回响!!!
  16. 基于ZStack3.0.1(CC2530)和ST7735S的HAL_LCD驱动替换(一)
  17. 【操作说明】4G网络摄像机国标GB28181协议视频平台EasyGBS如何配置告警白名单?
  18. Python 从无到有搭建WebUI自动化测试框架
  19. Monkey测试(APP稳定性)
  20. WGAN(wasserstein GAN)

热门文章

  1. 毫米波雷达数据处理_毫米波雷达开启4D时代,助力几何伙伴抢滩自动驾驶量产...
  2. html5相对父元素定位,layer弹出层设置相对父级元素定位
  3. linux web文件夹权限设置,WEB文件目录权限设置与修改方法
  4. linux执行指定程序的命令,linux 下使用指定的用户来执行命令
  5. 华科计算机考研2022年分数线,2022年华中科技大学软件工程考研分数线、参考书、上岸前辈初复试经验...
  6. hubliderx如选择相同单词_高考英语,十六种高效单词记忆法,建议人手一份!
  7. 获取浏览器高度_QQ浏览器违法收集用户信息,你的浏览器还安全吗?
  8. python文字识别库_python做文字识别一行代码都不用!
  9. php俄罗斯方块代码,[原创]Matlab做的俄罗斯方块(含代码)
  10. (4) hibernate增删查改+批量操作+类似Mybatis动态sql