【Spring】重新认识 IoC

前言

IoC (Inversion of control) 并不是Spring特有的概念。

IoC

维基百科的解释:
In software engineering, inversion of control (IoC) is a programming principle. IoC inverts the flow of control as compared to traditional control flow.
在软件工程中,IOC(控制反转)是一种编程原则。和传统的控制流程相比,IoC颠倒了控制流程。

In IoC, custom-written portions of a computer program receive the flow of control from a generic framework.
在IoC中,程序的自定义编写部分接收一种来自通用框架的控制流程。

A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code.
与传统的过程编程相比,采用这种设计的软件架构将控制反转:在传统编程中,表示程序目的的自定义代码调用可重用库来处理一般任务,但在控制反转中,框架调用自定义,或特定于任务的代码。

来源:https://en.wikipedia.org/wiki/Inversion_of_control

IoC的主要实现策略

由于自己确实对其他IoC容器了解不多,这儿的依赖查找依赖注入只有以Spring来自我理解了。
由于Spring确实也是非常完善的IOC容器,所以理解完全没有问题。

依赖查找

为了便于理解,用Spring来举例,使用BeanFactory或者ApplicationContext的方法,如“getBeanByName”之类,来获取到我们托管到容器中的资源(如Bean),这个就是依赖查找。

依赖注入

为了便于理解,用Spring来举例,使用@Autowired来获取到我们托管到容器中的资源,这个就是依赖注入。
或者使用@Inject实现注入,@Inject是JSR330 (Dependency Injection for Java)中的规范,需要导入import javax.inject.Inject; 实现注入。

依赖查找 VS 依赖注入

|类型|依赖处理|实现便利性|代码侵入性|API依赖性|可读性|
| ---- | ---- | ---- |---- | ---- |---- | ---- |
| 依赖查找 | 主动获取 | 相对繁琐 |侵入业务逻辑 | 依赖容器API |良好 |
| 依赖注入 | 被动提供 | 相对便利 |低侵入性 | 不依赖容器API |一般 |
注:这里所谓的主被动只是相对的,依赖注入也需要主动注入,但是其他的对象获取大部分被容器做了。

IoC容器的职责

通用职责

  1. 依赖处理
    • 依赖查找
    • 依赖注入
  2. 生命周期管理
    • 容器
    • 托管的资源(Java Beans 或其他资源)

容器的生命周期:容器的启动、运行、停止、销毁等生命周期管理。
托管的资源的生命周期:指容器管理的资源的注册,初始化,销毁等生命周期管理。
这里托管的资源不仅仅指JavaBean,因为Spring容器管理的资源还有:如Spring Event的Listener,它并不是一个Bean,也不是一个POJO。

  1. 配置
    • 容器
    • 外部化配置
    • 托管的资源(Java Beans 或其他资源)

IoC容器的实现

IoC并不是Spring的专利,我之前一直认为Spring创造的IoC。实在是错了好多年。

主要实现

  1. Java SE
    • Java Beans
    • Java ServiceLoader SPI
    • JNDI(Java Naming and Directory Interface)
  2. Java EE
    • EJB(Enterprise Java Beans)
    • Servlet
  3. 开源
    • Apache Avalon(http://avalon.apache.org
    • PicoContainer(http://picocontainer.com
    • Google Guice(https://github.com/google/guice
    • Spring Framework(https://spring.io/projects/spring-framework

基础IoC容器:JavaBeans

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.util.stream.Stream;

public class JavaBeansDemo {

    public static void main(String[] args) throws IntrospectionException {

        // stopClass 排除(截止)类
        BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
        // 属性描述符 PropertyDescriptor

        // 所有 Java 类均继承 java.lang.Object
        // class 属性来自于 Object#getClass() 方法
        Stream.of(beanInfo.getPropertyDescriptors())
                .forEach(propertyDescriptor -> {
//                    propertyDescriptor.getReadMethod(); // Getter 方法
//                    propertyDescriptor.getWriteMethod(); // Setter 方法
                    System.out.println(propertyDescriptor);
                });

        // 输出 User 定义的方法 MethodDescriptor
        Stream.of(beanInfo.getMethodDescriptors()).forEach(System.out::println);

    }
}

public class Person {
    private String name;
    private Integer age;
    //getter setter
}

输出:

java.beans.PropertyDescriptor[name=age; propertyType=class java.lang.Integer; readMethod=public java.lang.Integer org.jamie.Person.getAge(); writeMethod=public void org.jamie.Person.setAge(java.lang.Integer)]
java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String org.jamie.Person.getName(); writeMethod=public void org.jamie.Person.setName(java.lang.String)]

总结

这里的IOC整理是由于自己以前对IOC的误解,基于小马哥的讲解,自己的学习笔记。
我对IOC的理解是:

IOC最核心的功能:本来是我们主动控制一些资源,我们把这种控制权交给一种组件,这种组件可以帮我们管理这些资源,我们需要使用它的时候,从IOC容器中通过2种方式(依赖查找,依赖注入)来获取到资源。

原文地址:https://www.cnblogs.com/1626ace/p/15035592.html