SpringIOC原理分析

目录

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的依赖注入


1.什么是IOC/DI技术

参考博客:http://jinnianshilongnian.iteye.com/blog/1413846,觉得写的比较好就直接拿过来了

1.1 IOC介绍

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

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

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

1.2 DI介绍

DI—Dependency Injection,即“依赖注入”组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

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

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

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

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

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

1.3 IOC和DI的关系

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

2.怎么使用IOC这个技术

IOC功能在开发中如何使用,主要分为注册bean和注入bean两个部分,有三种方式去使用IOC技术,下面分别简单介绍一下:

2.1  利用注解来注册和注入bean

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();		
	}
}

2.2  在Java代码中进行显示的装配

用@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!";
    }
}

 2.3  利用XML进行注册bean

Spring使用XMl装配Bean,已经有很久的历史了,曾经xml是主要装配bean的方式,

但现在使用JavaConfig方式装配Bean很受提倡。现在很多企业还是比较习惯使用XML装配组件,下面我们就简单介绍一下使用XML装配Bean的实现吧。

借助构造器注入初始化bean:

注入引用:


    


注入字面量:

 
  
   
   
        
              ,,,
              >...
             
       
   


设置引用属性:
      

 


这里name是属性名,ref是引用的bean
注入字面量到属性中:

    
    
     
          
                 第一句
                  第二句
                 第三句
          
     

3.IOC技术的内部原理是什么

参考博客:https://www.cnblogs.com/ITtangtang/p/3978349.html

这里将IOC的整个过程分为两大部分,IOC容器初始化的过程以及依赖注入的过程,在讲解原理的时候主要根据这两大步来介绍

下面先来一张IOC容器组成部分图

                                             SpringIOC原理分析_第1张图片        

3.1 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时才触发。

3.2 IOC的依赖注入

你可能感兴趣的:(SpringIOC原理分析)