控制反转的类型

控制反转(IOC)旨在提供一种更简单的机制,来设置组件的依赖项,并在整个生命周期管理这些依赖项。通常,控制反转可以分成两种子类型:依赖注入(DI)和依赖查找(DL),这些子类型各自又可以被进一步分解为 IOC 服务的具体实现

1. 依赖查找

1.1 依赖拉取

依赖拉取(Dependency Pull),即根据需要,从注册表中提取依赖项,以下代码显示了基于 Spring 的依赖拉取

public class DependencyPull {public static void main(String[] args) {ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring/app-context.xml");ctx.getBean("renderer", MessageRenderer.class);}
}
1.2 上下文依赖查找

上下文依赖查找(contextualized dependency lookup,CDL),同样属于依赖查找的子类型,和依赖拉取有点类似,但在 CDL 中,查找是针对管理资源的容器执行的,这个容器通常由应用程序服务器或框架(Tomcat、JBoss、Spring)提供,比如以下代码显示了一个提供依赖查找服务的容器接口

public interface Container {// 根据key获取相应的依赖项Object getDependency(String key);
}

CDL 通过让组件实现以下代码接口来进行工作

public interface ManagedComponent {void performLookup(Container container);
}

组件需要实现该接口,当容器准备好将依赖项传递给组件时,会依次调用每个组件的 performLookup() 方法,然后组件就可以使用 Container 接口查找所需的依赖项

public class ContextualizedDependencyLookup implements ManagedComponent {private Dependency dependency;@Overridepublic void performLookup(Container container) {this.dependency = (Dependency) container.getDependency("myDependency");}@Overridepublic String toString() {return dependency.toString();}
}

2. 依赖注入

2.1 构造函数注入

当在组件的构造函数中提供依赖项时,就会发生构造函数依赖注入

public class ConstructorInjection {private Dependency dependency;public ConstructorInjection(Dependency dependency) {this.dependency = dependency;}@Overridepublic String toString() {return dependency.toString();}
}
2.2 setter 函数注入

Ioc 容器通过 JavaBean 样式的 setter 方法注入组件的依赖项

public class SetterInjection {private Dependency dependency;public void setDependency(Dependency dependency) {this.dependency = dependency;}@Overridepublic String toString() {return dependency.toString();}
}

在 Spring 中,还支持另一种被称为字段注入(field injection)的注入类型,在后面学习使用 @Autowire 注解进行自动装配时将介绍该注入类型

Spring 中的控制反转

1. Bean 和 BeanFactory

Spring 的依赖注入容器的核心是 BeanFactory,它负责管理组件,包括依赖项以及它们的生命周期。如果我们想获得一个组件(Bean),就必须创建一个实现了 BeanFactory 接口的实例,并对其进行配置

虽然 BeanFactory 可以通过编程方式配置,但更常见的做法是使用某种配置文件在外部对其进行配置。Bean 配置可以由实现 BeanDefinition 接口的类的实例来表示,对于任何实现了 BeanDefinitionReader 接口的 BeanFactory 实现类来说,都可以使用 PropertiesBeanDefinitionReader 或 XmlBeanDefinitionReader 从配置文件读取 BeanDefinition 数据

定义一组接口:

public interface Oracle {String output();
}public class OracleImpl implements Oracle {@Overridepublic String output() {return "hello world";}
}

接下来我们来看一看,Spring 的 BeanFactory 如何被初始化并用于获取 Bean 实例

public class XmlConfigWithBeanFactory {public static void main(String[] args) {// DefaultListableBeanFactory是Spring提供的两个主要BeanFactory实现之一DefaultListableBeanFactory factory = new DefaultListableBeanFactory();XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);// 使用XmlBeanDefinitionReader从XML文件读取BeanDefinition信息rdr.loadBeanDefinitions(new ClassPathResource("spring/xml-bean-factory-config.xml"));// 使用在XML配置文件中配置的名称oracle来获取beanOracle oracle = (Oracle) factory.getBean("oracle");System.out.println(oracle.getInfo());}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="oracle" name="oracle" class="com.example.OracleImpl"/></beans>

ApplicationContext 接口是 BeanFactory 的一个扩展,除了 DI 服务外,还提供其他如事务和 AOP 等服务。在开发基于 Spring 的应用程序时,建议通过 ApplicationContext 接口与 Spring 交互

2. 设置 Spring 配置

2.1 XML 配置

对于 XML 配置,需要声明应用程序需要的由 Spring 提供的名称空间基础信息,下面所示配置仅声明用于定义 bean 的名称空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="provider" class="com.example.HelloWorldMessageProvider"/><bean id="render" class="com.example.StandardOutMessageRender"p:messageProvider-ref="provider"/></beans>
2.2 注解配置

要想在应用程序使用 Spring 的注解支持,需要在 XML 配置中声明

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.example" /></beans>

<context:component-scan> 标记告诉 Spring 扫描代码,从而找到 @Component 等注解注入的 bean,以及支持在指定包(及其所有子包)下使用 @Autowire 等注解的 bean

2.3 Java 配置

配置类使用 @Configuration 注解,并包含用 @Bean 注解的方法,这些方法由 IOC 容器直接调用来实例化 bean,bean 名称与用于创建它的方法的名称相同

@Configuration
public class HelloWorldConfiguration {@Beanpublic MessageProvider provider() {return new HelloWorldMessageProvider();}@Beanpublic MessageRender render() {StandardOutMessageRender render = new StandardOutMessageRender();render.setMessageProvider(provider());return render;}
}

如果想从该类中读取配置信息,需要一个不同的 ApplicationContext 实现

public class HelloWorldSpringAnnotated {public static void main(String[] args) {AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);MessageRender render = ctx.getBean("render", MessageRender.class);render.render();}
}

3. setter 注入

使用 XML 配置来配置 setter 注入,需要在 <bean> 标记下指定 <property> 标记,为其注入一个依赖项

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="provider" class="com.example.HelloWorldMessageProvider"/><bean id="render" class="com.example.StandardOutMessageRender"><property name="messageProvider" ref="provider"/></bean></beans>

如果使用注解,只需要向 setter 方法添加一个 @Autowired 注解

@Service("render")
public class StandardOutMessageRender implements MessageRender {...@Override@Autowiredpublic void setMessageProvider(MessageProvider messageProvider) {this.messageProvider = messageProvider;}
}

4. 构造函数注入

public class ConfigurableMessageProvider implements MessageProvider {private String message;public ConfigurableMessageProvider(String message) {this.message = message;}@Overridepublic String getMessage() {return null;}
}

使用 XML 方式注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="oracle" name="oracle" class="com.example.OracleImpl"/><!-- 使用 <constructor-arg> 标记 --><bean id="messageProvider" class="com.example.ConfigurableMessageProvider"><constructor-arg value="hello world" /></bean><!-- 使用c名称空间 --><bean id="provider" class="com.example.ConfigurableMessageProvider"c:message="hello world"/></beans>

使用注解方式

@Service
public class ConfigurableMessageProvider implements MessageProvider {private String message;@Autowiredpublic ConfigurableMessageProvider(@Value("hello world") String message) {this.message = message;}@Overridepublic String getMessage() {return null;}
}

Spring 控制反转和依赖注入相关推荐

  1. Spring控制反转和依赖注入

    (1)为什么使用控制反转和依赖注入 调用者不用去关心被调用者的实现,不需要调用者亲自创建被调用者的实例,这些操作都交给框架去完成. 这种设计思想就是控制反转(Inversion of Control, ...

  2. Spring控制反转和依赖注入的好处

    要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversion Principle ). 什么是依赖 ...

  3. Spring控制反转(依赖注入)的最简单说明

    1.常规方式实现实例化 1.1已有角色如下: 一个接口Interface,两个接口实现类InstatnceA.InstanceB,一个调用类User 1.2当前实例化InstanceA如下: Inte ...

  4. spring控制反转与依赖注入

    1)什么是控制反转 传统的编程思路是,当我需要某个对象时,我便自己去实例化调用它 .而控制反转则是,当我需要某个对象时,自然有人帮我们实例化它 .简单的来说,这是一种衣来张口,饭来伸手式的控制模式,这 ...

  5. Spring 控制反转和依赖注入简介

    文章目录 1.介绍 2.什么是控制反转? 3.什么是依赖注入? 4.Spring IoC 容器 5.基于构造函数的依赖注入 6.基于Setter的依赖注入 7.基于字段的依赖注入 8.自动装配依赖 9 ...

  6. Spring容器,控制反转,依赖注入

    Spring boot学习之旅,为更好督促自己学习以记之,仅供参考. spring容器 程序启动的时候会创建spring容器,扫描给spring容器一个清单,比如:@Controller, @Bean ...

  7. Spring框架中的控制反转和依赖注入

    控制反转: 控制反转是用来降低代码之间的耦合度的,基本思想就是借助"第三方"实现具有依赖对象的解耦. 为什么需要控制反转,因为项目中对象或多或少存在耦合.控制反转的关键在于Ioc容 ...

  8. SSM框架—Spring基础—控制反转和依赖注入(概念)

    控制反转: 控制反转(IoC)是面向对象编程的一个设计原则,用于降低代码耦合度 在传统面向对象编程中,获取对象的方式是用关键字"new"主动创建一个对象,也就是说,应用程序掌握着对 ...

  9. Spring的控制反转与依赖注入

    学习过Spring的都知道Spring有三大核心的概念,分别是控制反转(IOC).依赖注入(DI)和面向切面编程(AOP).今天就来聊聊我对控制反转和依赖注入的了解,至于面向切面编程放到后面讲解. 一 ...

最新文章

  1. 符号说明表怎么做_教会你的孩子正确使用标点符号
  2. phaser java_【Java并发编程实战】-----“J.U.C”:Phaser
  3. 2021-2025年中国电气石手镯行业市场供需与战略研究报告
  4. 不止是替代 看南天信息与浪潮的金融国产化实践
  5. 深入了解VPP关键技术有哪些?
  6. N卡A卡流处理器的区别解析
  7. 【数学建模】最优化模型
  8. python setup.py install没反应_花了两天,终于把 Python 的 setup.py 给整明白了
  9. SpringCloud 第十二章 Gateway新一代网关
  10. html简单实现自动轮播代码怎么写,HTML图片轮播代码怎么写?
  11. 抽象类和接口的区别(之二)
  12. 超火的微信小说小程序源码-自带采集带安装教程
  13. 安卓搞机玩机-什么是“锁 ” BL锁 屏幕锁 账号锁 设备锁等分析
  14. 大型软件开发中的流程与规范
  15. table 表格合并行或列
  16. anki android自动同步,解决Anki服务器同步问题:坚果云 Floder sync (亲测有效)
  17. CSS的类名命名规范
  18. 【js原生调用Node.js】使用spawn如果cwd不存在会报错
  19. 数值计算之 线搜索法,Armijo,Wolfe,Goldstein条件,回溯法
  20. javaweb学习笔记(五)

热门文章

  1. zabbix agent安装步骤
  2. mysql清空数据库所有表的命令_mysql清空表数据命令是什么?_数据库,mysql,清空表数据...
  3. 高级语言与计算机硬件有关吗,计算机高级语言是与计算机硬件有关的语言。
  4. Java 静态成员变量
  5. win无法访问别的计算机,无法访问共享文件应怎么办?电脑无法访问别人共享的文件解决办法...
  6. 专转本计算机ppt考点,PowerPoint的基本操作(江苏专转本计算机.ppt
  7. 2019年中国税务机关确保减税降费政策落地
  8. nvm安装以及nvm安装之后报错npm/node不是内部外部命令,nvm use 报错乱码
  9. Python数组字典排序sorted()与sort()用法
  10. ssh 链接突然中断