spring IOC原理

IOC原理:

  1. IOC是什么? 
  2. IOC容器是什么?(IOC容器就是依赖注入技术的核心bean的集合。)
  3. 为什么有IOC?
  4. 要实现IOC需要哪些必要条件?

一般大家提到spring都知道他的2大功能,一个是IOC叫控制反转,更准确的应该叫依赖注入,另一个便是AOP,这里不讨论AOP。

那么如何实现IOC,早期注解还不是很流行的时候,大家肯定配置过spring的配置文件,applicationContext.xml(spring设计实现的源头),

例如:

<?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"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
 default-autowire="byName" default-lazy-init="true">
<bean     class="bean的完全限定名"
          name/id="bean在容器内的唯一名称"
            scope="bean的生命周期"
            lazy-init="是否为延迟加载"
            init-method="bean的setter被调用之后调用该方法进行初始化"
            destroy-method="容器在销毁该Bean后的调用的方法"
            abstract="是否为抽象Bean,spring对于抽象bean不产生实例,主要用于继承"
            parent="父Bean的名称,会继承父Bean的属性,与Java的Class无任何关系"
            factory-method="工厂方法的名字"
            factory-bean="工厂Bean的名字"
            depends-on ="依赖Bean的名字,保证初始化顺序。” > 

            <!-- Constructor-arg给属性赋值写法一 -->
            <constructor-arg type="int" value="10"/>
            <!-- Constructor-arg给属性赋值写法二 -->
            <constructor-arg name="age" value="10"/>
            <!-- Constructor-arg给属性赋值写法三 -->
            <constructor-arg index="0" value="10"/>

            <!-- Properties给属性赋值写法一 -->
            <property name="bean1">
                 <ref bean="另外一个bean的id"/>
            </property>
            <!-- Properties给属性赋值写法二 -->
            <property name="bean1" ref="另外一个bean的id"/>
            <!-- Properties给属性赋值写法三 -->
            <property name="age" value="10"/>
</bean> 

或者通过注解:

@Component  进行配置bean;  @Autowired进行bean注入。

通过配置我们知道<beans>标签下还有多个<bean>,同时bean下面还有<constructor-arg>和<property>,这2个属性分别对应构造器注入和setter注入(这2种是spring推荐的方式)

另外还有通过bean工厂方式注入的,并不推荐。

  • 这些bean装入容器的时候,<bean>标签下的各种属性(例如:class、id、scope等等属性)该怎么办?
  • 另外分析上面的红色加粗字体,一个体现的是多个bean,一个体现的是bean的注入存在引用关系。既然,IOC容器是装入bean的容器,如果是你,你该怎么将bean装入这个容器呢?
  • 既然是一个容器(能称作容器的必要条件是什么?),里面的bean我们是不是随时可以取用?容器中的bean是不是该有有效时间(对象的生命周期)?

先看下面的几个例子:

public class ClassB {
    
    private ClassA classA;

    public ClassB(ClassA classA) {
        this.classA = classA;
    }
    
    public String getStr() {
        return classA.getStr();
    }
    
//    public static void main(String[] args) {
//        ClassA classA = new ClassA();
//        ClassB classB = new ClassB(classA);
//        classB.getStr();
//    }
}

 类B通过构造方法能够获取到类A,从依赖上来讲,类B的创建需要依赖类A,这个是从代码上体现,尤其是main方法中,类B进行

实例的时候必须先获取一个类A的实例(不要纠结无参构造,实际生产中存在这样的关系,B类的功能必须依赖A类),这里体现的

就是类B依赖类A,这就是依赖的体现,现在将main方法中的显示构造

ClassA classA = new ClassA();
ClassB classB = new ClassB(classA);//配置到spring配置文件中,我们就可以不用自己去实例化这个类B就可以直接使用

替换通过spring配置文件进行配置,这就是注入

现在,我们从实现配置文件出发开始模拟实现IOC功能(多个bean,并且bean之间有依赖注入关系),

  1. 定义一个配置文件(applicationContext.xml),文件名要有一定的限制(为后面准确读取特定文件准备)ResourceLoader
  2. 获取到这个文件,并且能够读取到里面的内容 XmlBeanDefinitionReader
  3. 文件中的内容要想正确读取,需要一定的格式支持,定义一个数据格式BeanDefinition,格式定义了能够读取的属性(例如:class、id、scope等等属性)
  4. 读取到bean以及bean中的属性,并且正确创建这个bean,我们通过AutowireCapableBeanFactory进行bean的装配
  5. 正确读取到单个的bean和bean之间的引用关系,我们需要 HierarchicalBeanFactory 进行关系的维系。
  6. 将多个bean进行集中管理通过 ListableBeanFactory进行集合管理

实现的流程大致如图:

以上就是演变过程,其中定义的接口都是spring源码中的结构,spring  beans包中包含以上所有内容,但是整个的协作过程

体现在spring context包中,spring core包中包含了实现以上功能的底层实现。

其中:

bean的定义:

 

 

 

bean的解析:

 

bean的创建:

  • ListableBeanFactory(可列表)
  • HierarchicalBeanFactory(层级关系)
  • AutowireCapableBeanFactory(自动装配)

这3个接口都是继承自 BeanFactory(很重要)这个顶级接口,最终落地实现类 DefaultListableBeanFactory

类层级关系如图:

  

 

协作过程在ApplicationContext接口中,

 

 

 最终实现类为 AbstractApplicationContext(核心方法 refresh(),该类为抽象类,部分可定制化内容由实际实现子类完成)

 

posted @ 2020-05-26 10:37  杨敏86  阅读(209)  评论(0编辑  收藏  举报