目录
1.什么是IOC/DI技术
1.1 IOC介绍
1.2 DI介绍
1.3 IOC和DI的关系
2.怎么使用IOC这个技术
2.1 利用注解来注册和注入bean
2.2 在Java代码中进行显示的装配
2.3 利用XML进行注册bean
3.IOC技术的内部原理是什么
3.1 IOC容器的初始化过程
3.2 IOC的依赖注入
参考博客:http://jinnianshilongnian.iteye.com/blog/1413846,觉得写的比较好就直接拿过来了
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
IOC功能在开发中如何使用,主要分为注册bean和注入bean两个部分,有三种方式去使用IOC技术,下面分别简单介绍一下:
1.首先在xml文件中定义要扫描的注解包
2.在需要注册为bean的类上加注解,这样就会自动注册成为bean啦
import org.springframework.stereotype.Component;
@Component("cD") //基于注解的注册bean
public class CD{
private String title="稻香";
private String artist="周杰伦";
public String play(){
return "播放"+artist+"唱的"+title;
}
}
3.当我们需要注入bean时,需要加上@Autowired
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("cdPlayer")
public class CDPlayer{
@Autowired
public CD cd;
public void play() {
System.out.println(cd.play());
}
}
测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("application.xml");
CDPlayer cdPlayer=(CDPlayer) ac.getBean("cdPlayer");
cdPlayer.play();
}
}
用@Configuration注解该类,等价 与XML中配置beans;用@Bean标注方法等价于XML中配置bean。
@Configuration
public class SpringConfig {
@Bean
public Service service(){
return new Service();
}
@Bean
public Client client(){
return new Client();
}
}
定义要注册bean的类
public class Client {
@Autowired
Service service;
public void invokeService(){
System.out.println("client invoke :" + service.sayHello());
}
}
class Service {
public String sayHello(){
return "HelloWord!";
}
}
Spring使用XMl装配Bean,已经有很久的历史了,曾经xml是主要装配bean的方式,
但现在使用JavaConfig方式装配Bean很受提倡。现在很多企业还是比较习惯使用XML装配组件,下面我们就简单介绍一下使用XML装配Bean的实现吧。
借助构造器注入初始化bean:
注入引用:
注入字面量:
,,,
>...
设置引用属性:
这里name是属性名,ref是引用的bean
注入字面量到属性中:
第一句
第二句
第三句
参考博客:https://www.cnblogs.com/ITtangtang/p/3978349.html
这里将IOC的整个过程分为两大部分,IOC容器初始化的过程以及依赖注入的过程,在讲解原理的时候主要根据这两大步来介绍
下面先来一张IOC容器组成部分图
IoC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。
(1)Resource资源的定位
这里Resource指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,对各种形式的BeanDefinition都提供了统一的接口。比如文件系统中的Bean定义信息可以使用FileSystemResource来抽象;类路径中的Bean定义信息可以使用ClassPathResource来抽象,等等。这个Resource定位过程其实就是IoC容器寻找Bean定义数据的过程
(2)BeanDefinition的载入
前面定位到了Resource之后,就载入Resource并启动BeanDefinition的解析,利用BeanDefinitionPaser进行解析,这个载入过程就是把定义好的Bean表示成容器内部的数据结构BeanDefinition。这个BeanDefinition实际上就是POJO对象在IoC容器中的抽象,通过这个BeanDefinition定义的数据结构,使IoC容器能够方便地对POJO对象也就是Bean进行管理。
(3)向IoC容器注册BeanDefinition
这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的,该注册过程把载入过程中解析得到的BeanDefinition向IoC容器进行注册。其实在IoC容器内部就是将BeanDefinition注入到一个HashMap中,IoC容器就是通过这个HashMap来持有这些BeanDefinition数据的。
额外说明
需要注意的是,这里说的IoC容器的初始化过程一般不包括依赖注入的实现。在Spring的设计中,Bean定义的载入和依赖注入是两个独立的过程,依赖注入一般发生在应用第一次通过getBean向容器索取Bean实例的时候。有一个例外就是当我们在Bean定义中指定的lazyinit属性(预实例化配置),那么这个Bean的依赖注入在IoC容器的初始化时就完成了,不需要等到初始化完成之后,第一次获取该Bean时才触发。