首先,我们看一下spring 官方对 IOC 容器的解释(spring.io):
1.1. Introduction to the Spring IoC Container and BeansThis chapter covers the Spring framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.
1.1. spring IOC 容器本章覆盖 spring IOC 架构实现的简单原则。IOC 也称为 依赖注入(DI).具体依赖通过3种方法来定义,分别是 构造器参数,工厂方法参数或者是静态配置文件属性的方式(xml)。然后再创建bean的时候,将定义的依赖注入到bean实体中。这个过程就是依赖注入(IOC).
我们从以下几个方面加深对 spring IOC 容器的理解:
- 依赖注入方式
- spring bean 概览
- 定制一个bean
- 容器扩展点
- 注解的容器配置
- JSR-330 标准注解
- Environment 抽象
- ApplicationContext 的扩展功能
- BeanFactory
这幅图就反映了spring容器的高层抽象,你的业务实体(POJOS)和一些定制化的元数据(xml方式,java方式或者是properties 方式)通过spring容器进行组装,然后spring容器产生一个完全体的bean,随后通过 容器 来管理这些bean的生命周期。
我们引出第一个问题,我们的配置元数据(Configuration metadata)可以通过哪些方式加载:
依赖加载方式As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application.
spring IOC 容器会消费配置元数据。配置元数据的作用就是,你作为开发者,通过元数据告诉 spring 容器,我需要你怎样实例化,配置,集成管理我应用的对象。
spring 官方文档告诉我们,配置元数据的作用类似于做菜的菜谱,而我们的 pojo业务实体 就像是原材料,而spring IOC 容器的功能则是厨师,我们通过把菜谱和原材料告诉厨师,它就可以帮我们做出符合我们要求的菜肴(唯一有区别的一点,spring ioc容器会帮我们管理bean的整个生命周期,而厨师却不会帮我们送菜和收拾盘子。。)
- XML 配置方式(基础配置方式)
- 注解 配置方式(始于 spring 2.5 版本)
- Java annotation 配置方式(始于 spring 3.0 版本)
传统标准的xml结构的元数据配置方式:
当我们定义完我们的 bean 配置文件后,我们就可以“命令”容器去按我们的“菜谱”去实例化了:
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
有朋友可能会有疑问,这些所谓的xml文件,spring是如何加载的呢,这个问题其实就涉及到 spring 的另一个主题了 spring resource 抽象,这是一个全新的主题,在后续的文章中继续给大家分享。
当我们让 spring IOC 容器帮我们初始化完了bean实例,如何去使用它们呢,很简单,只需要:
// 取回配置的实例 PetStoreService service = context.getBean("petStore", PetStoreService.class); // 使用配置的实例 ListuserList = service.getUsernameList();
然而大多数情况下,在我们的应用开发中,都使用注解方式(@Autowired)增加了取实例的透明性。
spring bean 概览我们所定义的静态配置元数据对象,实际上在程序运行时,都会以 BeanDefinition 对象的形式存在。
通常意义上,BeanDefinition 都包含如下 4 个部分的关键信息:
- 包限定类名(A package-qualified class name)
- bean 的行为属性定义(Bean behavioral configuration elements):如 scope,lifecycle 等
- bean 的引用名(References to other beans that are needed for the bean to do its work)
- 其他的配置信息(Other configuration settings to set in the newly created object ):如数据库连接池的最大连接数等
通常,有3种实例化bean的方式可供我们选择:
通过构造器实例化通过静态工厂方法实例化
public class ClientService { private static ClientService clientService = new ClientService(); private ClientService() {} public static ClientService createInstance() { return clientService; } }通过实例化工厂方法
public class DefaultServiceLocator { private static ClientService clientService = new ClientServiceImpl(); public ClientService createClientServiceInstance() { return clientService; } }
第三种方法的 FactoryBean 通常用于定制复杂bean对象,这个我们专门叙述
定义好bean之后,我们可以抛出以下问题:
- 我们的bean是如何被spring IOC 容器加载的
- 是在什么阶段加载的
依赖注入(DI)有两种主要的方式:
- 构造器注入方式(Constructor-based Dependency Injection)
- setter方法注入方式(Setter-based Dependency Injection)
构造器注入方式The container then injects those dependencies when it creates the bean
bean 的依赖是在 spring容器 创建 bean 的阶段被注入进去的。
同学们可以想一想如何解决循环依赖的问题,这个也是面试的必考点。
package x.y; public class ThingOne { public ThingOne(ThingTwo thingTwo, ThingThree thingThree) { // ... } }
setter方法注入方式
TIPS : 依赖反转 IOC 的含义:
Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.
在依赖注入模式下的代码风格是非常简洁的,在为对象注入依赖的时候更关注解耦的方面。事实上,一个对象不会感知到它的依赖存在,也不知道依赖的位置和依赖的类(作者:实际上都是由 spring 容器 来统一关系,相当于中介功能)。结果就是,你的类可以更方便的测试。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)