美文网首页Java大数据
控制反转、依赖反转、依赖注入有什么区别和联系

控制反转、依赖反转、依赖注入有什么区别和联系

作者: Java弟中弟 | 来源:发表于2021-09-29 16:34 被阅读0次

    关于依赖注入如何理解,控制反转和依赖注入这两个概念有什么区别。,spring框架中的IOC跟这些概念有什么区别

    控制反转

    控制反转(Inversion of control)也就是IOC,spring经常会提到这个概念,可以先通过一个例子看下

    public class UserServiceTest {
        public static boolean doTest(){
            // ...
            return true;
        }
    
        public static void main(String[] args) {
            if (doTest()){
                System.out.println("success");
            }else {
                System.out.println("fail");
            }
        }
    }
    
    

    上面的代码中,所有流程由程序员控制,其实可以进行一定的抽象,利用框架来实现同样的功能,如下代码

    public abstract class TestCase {
        public void run(){
            if (doTest()){
                System.out.println("success");
            }else {
                System.out.println("fail");
            }
        }
        public abstract Boolean doTest();
    }
    
    public class TestApplication {
        private static final List<TestCase> testCaseList = new ArrayList<>();
    
       public static void doRegister(TestCase testCase){
           testCaseList.add(testCase);
       }
    
        public static void main(String[] args) {
            for (TestCase testCase:testCaseList){
                testCase.run();
            }
        }
    }
    
    

    使用这个简化版的工程后,只需要在框架预留的扩展点(TestCase中的doTest抽象函数),填充具体代码就可以实现之前的功能了,不需要写负责main函数了,具体如下

    public class UserServiceTest extends TestCase{
        @Override
        public Boolean doTest() {
    
            return true;
        }
    
        public  UserServiceTest(){
            //注册操作还可以通过配置的方式来实现,不需要程序员显示调用register()
            TestApplication.doRegister(new UserServiceTest());
        }
    }
    
    

    以上是控制反转的例子,框架提供了一个可扩展的代码骨架,用来组装对象、管理执行流程。开发者只需要在预留的扩展点上添加跟自己业务相关的代码,就可以利用框架来驱动整个程序流程的执行。

    这里的“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,开发者自己控制整个程序的执行流程,使用框架之后整个利用由框架来控制。控制反转并不是一种具体的实现技巧,而是一个比较笼统的思想,一般用来指导框架的顶层设计

    依赖注入

    依赖注入跟控制反转恰恰相反,它是一种具体的编码技巧。用一句话来概括就是:不通过new()的方式在类内部创建依赖对象,而是将依赖的类对象在外部创建好通过构造方法、函数参数等方式传递给类使用

    非依赖注入方式

    public class Notification {
        private MessageSender messageSender;
    
        public Notification(){
            this.messageSender = new MessageSender();
        }
    
        public void sendMessage(){
            messageSender.sendMessage();
        }
    }
    
    public class MessageSender {
        public void sendMessage(){
            //....
        }
    }
    
    

    依赖注入方式

    public class Notification {
        private MessageSender messageSender;
    
        public Notification(MessageSender messageSender){
            this.messageSender = messageSender;
        }
    
        public void sendMessage(){
            this.messageSender.sendMessage();
        }
    }
    
    

    通过依赖注入的方式将依赖的类对象传递进来,提高了代码的扩展性,可以灵活的替换依赖类,这样也比较符合开闭原则。我们还可以把MessageSender定义成接口,基于接口而非实现类编程,改造如下

    public class Notification {
        private MessageSender messageSender;
    
        public Notification(MessageSender messageSender){
            this.messageSender = messageSender;
        }
    
        public void sendMessage(){
            this.messageSender.sendMessage();
        }
    }
    
    public interface MessageSender {
         void sendMessage();
    }
    
    public class SmsSender implements MessageSender{
        @Override
        public void sendMessage() {
    
        }
    }
    
    

    上面的例子就是依赖注入,其实在日常的开发中非常常用

    依赖注入框架

    我们继续看下什么是依赖注入框架,继续使用刚才的例子来说明,在采用依赖注入实现的Notification中,不用在类内部通过new来创建MessageSender对象,但是创建对象、组装对象的工作仅仅被移动到了更上层的代码而已,具体如下

    public class Demo {
        public static void main(String[] args) {
            MessageSender smsSender = new SmsSender();
            Notification notification = new Notification(smsSender);
            notification.sendMessage();
        }
    }
    
    

    在实际的软件开发中,项目可能涉及到上百个类,类对象的创建和依赖会变得非常麻烦,所以像对象创建和依赖注入的工作,本身和业务无关,完全可以抽象成框架自动完成

    这个框架就是“依赖注入框架”。我们只需要通过依赖注入框架提供的扩展点,简单配置一下所有需要创建的类对象、类与类之间的依赖关系,就可以实现由框架来自动创建对象、管理对象的生命周期、依赖注入等原本需要程序员来做的事情。

    实际上,现成的依赖注入框架有很多,最典型的就是Spring

    依赖反转原则

    前面讲了控制反转、依赖注入、依赖注入框架,最后讲下依赖反转原则。依赖反转原则的英文翻译是 Dependency Inversion Principle,缩写为 DIP。中文翻译有时候也叫依赖倒置原则。

    主要的概念是:高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节 (details)依赖抽象(abstractions)。 所谓高层模块和低层模块的划分,简单来说就是,在调用链上,调用者属于高层,被调用者属于低层。在平时的业务代码开发中,高层模块依赖底层模块是没有任何问题的。实际上,这条原则主要还是用来指导框架层面的设计,跟前面讲到的控制反转类似。我们拿 Tomcat这个 Servlet 容器作为例子来解释一下。

    Tomcat 是运行 Java Web 应用程序的容器。我们编写的 Web 应用程序代码只需要部署在Tomcat 容器下,便可以被 Tomcat 容器调用执行。按照之前的划分原则,Tomcat 就是高层模块,我们编写的 Web 应用程序代码就是低层模块。Tomcat 和应用程序代码之间并没有直接的依赖关系,两者都依赖同一个“抽象”,也就是 Sevlet 规范。Servlet 规范不依 赖具体的 Tomcat 容器和应用程序的实现细节,而 Tomcat 容器和应用程序依赖 Servlet规范。

    不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之

    相关文章

      网友评论

        本文标题:控制反转、依赖反转、依赖注入有什么区别和联系

        本文链接:https://www.haomeiwen.com/subject/pqmjnltx.html