浅析Spring IOC、依赖注入(DI)和依赖查找(DL)

为什么要用IOC?

第一:对象的实例化不是一件简单的事情,比如对象的关系比较复杂,依赖关系往往需要程序员去维护,这是一件非常头疼的事。 

第二:解耦,由容器去维护具体的对象 

第三:托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分过程交给容器,应用程序则无需去关心类是如何完成代理的

控制反转(Inverse of Control)

控制反转即IoC(Incersion of Control),从字面上理解就是控制反转,将对在自身对象中的一个内置对象的控制权反转。所谓的反转,即把内置对象的控制权反转给一个容器,而应用程序只需要提供对象的类型即可。

这是一种解耦的设计思想,并不是什么具体的技术。基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。实现IOC的技术手段:DI(依赖注入)和 DL(依赖查找),Spring中的核心机制就是DI(依赖注入)。通俗来说就是ServiceImpl类中,有Dao 对象,那就是ServiceImpl依赖了Dao。

这里引用3张图就非常明显表示IOC容器的作用:解耦

 
软件系统中耦合的对象
 
IOC解耦过程
 
拿掉IOC容器后的各个对象

依赖注入(Depedency Injection)

意思是自身对象中的内置对象是通过注入的方式进行创建。依赖注入有两种实现方式:Setter方式(传值方式)和构造器方式(引用方式)。

容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造子传递给需要的对象。

相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。

依赖查找(Dependency Lookup)

谷歌中还有个资料表明:依赖查找也有两种类型:依赖拖拽(DP)和上下文化依赖查找(CDL)。

http://what-when-how.com/Tutorial/SpringFramework3/SpringFramework300052.html

依赖拖拽 (Dependency Pull)

依赖拖拽:注入的对象如何与组件发生联系,这个过程就是通过依赖拖拽实现 。(较少有使用)

依赖拖拽示例代码:

public class DependencyPullDemo {

    public static void main(String[] args) {

        BeanFactory beanFactory = getBeanFactory();

        MessageService messageService = (MessageService) beanFactory.getBean("service");

        messageService.execute();

    }

    private static BeanFactory getBeanFactory() {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        BeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);

        reader.loadBeanDefinitions(new ClassPathResource("/META-INF/spring/ioc-pull-context.properties"));

        return beanFactory;

    }

}

而通常对注入对象的配置可以通过一个 xml 文件完成。

依赖拖拽这种方式对对象进行集中管理。

上下文依赖查找(Contextualized Dependency Lookup)

在某些方面跟依赖拖拽类似,但是上下文依赖查找中,查找的过程是在容器管理的资源中进行的,而不是从集中注册表中,并且通常是作用在某些设置点上。

public class ContextualizedDependencyLookupDemo

    private static Set<ManagedComponent> components = new HashSet<ManagedComponent>();  

    private static class MessageServiceComponent implements ManagedComponent{ 

        private MessageService messageService;  

        public void lookup(BeanFactory beanFactory) { 

            this.messageService = (MessageService) beanFactory.getBean("service"); 

        } 

    }

}

使用依赖拖拽与上下文依赖查找本质的区别是:上下文依赖查找是在业务组件代码中进行的,而依赖拖拽是从一个集中的注册处,特定的地点执行。

Dependency Pull To a Java developer, Dependency Pull is the most familiar type of IoC. In Dependency Pull,dependencies are pulled from a registry as required.

对于Java开发人员来说,依赖拖拽是最常见的IoC类型。在依赖拖拽中,根据需要从注册表中提取依赖项。

 Anyone who has ever written code to access an EJB(2.1 or prior versions) has used Dependency Pull (i.e., via the JNDI API to look up an EJB component).

任何编写过访问EJB(2.1或更早版本)的代码的人都使用过依赖拖拽(即,通过JNDI API查找EJB组件)。

这里再加上一个依赖拖拽的Demo:

Spring-DependencyPullDemo

总结:

依赖查找(Dependency Lookup):容器中的受控对象通过容器的API来查找自己所依赖的资源和协作对象。这种方式虽然降低了对象间的依赖,但是同时也使用到了容器的API,造成了我们无法在容器外使用和测试对象。 依赖查找是一种更加传统的IoC实现方式。

依赖注入(Dependency Injection):依赖注入就是将服务注入到使用它的地方。对象只提供普通的方法让容器去决定依赖关系,容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造子传递给需要的对象。

相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,

也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。

这就是我对IOC、DI和DL的理解。本质就是把类的内置对象的控制权交给了容器。

参考文章:

IOC:https://blog.csdn.net/java_lyvee/article/details/83514583

依赖拖拽:http://www.voidcn.com/article/p-upbcskxv-bmm.htmlhttps://www.xuebuyuan.com/zh-hant/1903214.html

依赖查找JNDI例子:https://blog.csdn.net/beijiguangyong/article/details/43347351

依赖注入:https://blog.csdn.net/Baple/article/details/53667767

图片引用:https://www.cnblogs.com/Nouno/p/5706103.html

网上发现接近40%的文章写到IOC就是DI,在这明确说明这是错误的说法。


本人才疏学浅,以上纯属个人理解,如有不对,还望批评指正。



作者:vince_zww
链接:https://www.jianshu.com/p/26654a18d1fe
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/yaphetsfang/p/13065026.html