• 控制反转(IoC)-解析与实现


    控制反转(Inversion of Control)缩写:IoC是面向对象编程中框架级别里的一个重要的概念,

    可以说Spring框架的核心就是基于IoC原理的。

    这个概念到底是什么呢?

    这么讲吧,一个系统的运作肯定不是简单的几个类就可以实现的,它往往需要多个类的合作来实现业务逻辑

    。这就使得每个对象都需要与其合作的对象具有相互的关系(依赖关系)。在早前编程中所需要的依赖对象

    是通过自身去创建得到的,而现在是通过一个容器来统一管理这些依赖关系。在这整个过程中,对象获得其他对象引用的方式其实就是IoC。

    IoC的本质是什么?

    控制权的转移。IoC原理是基于面向对象中的设计原则的The Hollywood Principle:Don't call us,we'll call you(别找我,我会来找你的)。

    可以这样讲,所有组件的初始化和调用都是由容器负责。在传统实现中类之间的关系是由类自己控制的(需要使用其他类时就自己创建),

    但是在IoC中,组件处在容器中,由容器统一管理和调度。这就是"控制反转"的概念所在:控制权由应用代码转移到了容器中,即控制权的转移。

    那如何实现IoC这种思想的呢?

    实现IoC思想的方式主要有两种:依赖注入和依赖查找。

    下面就以依赖注入为例讲解一下:

     1 1.先定义一个部门接口:
     2 
     3 public interface IDepartService {
     4     //通过员工编号获得部门名字
     5     public String getDepartNameByUser(int userId);
     6 }
     7 
     8 2.实现该接口:
     9 public class DepartServiceImpl implements IDepartService {
    10 
    11     @Override
    12     public String getDepartNameByUser(int userId) {
    13         if(userId==1){
    14             return "IT部门";
    15         }
    16         return "";
    17     }
    18 }
    19 3.定义一个用户类,该类中要维持部门对象的引用:
    20 
    21 public class UserServiceImpl {
    22     private IDepartService departService;
    23     
    24     public void printInfo(int userId){
    25         System.out.print(getUserName(userId));
    26         System.out.println(departService.getDepartNameByUser(userId));
    27     }
    28     
    29     public String getUserName(int userId){
    30         if(userId==1){
    31             return "张三 ";
    32         }
    33         return "";
    34     }
    35 }

    在用户类中,我们没有看到关于创建DepartService对象的语句。这里面我们没有采用常见的set注入或者构造方法注入,

    而是采用反射的方法直接注入并执行的,要实现这个效果的话,我们需要定义一个容器,来管理他们的关系。

    4.定义容器,我们在容器中先获取配置文件:
    public class Container {
        ......
        private void loadConfig() {
            // TODO Auto-generated method stub
            InputStream is = Container.class.getResourceAsStream("/ioc.properties");
            properties = new Properties();
            try {
                properties.load(is);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    
        public Object get(String name) {
            String className = (String) properties.get(name);
            return Class.forName(className).newInstance();
                ......
        }
    
        public void inject(Object obj) {
            Field[] fields = obj.getClass().getDeclaredFields();
                ......
                for (Field field : fields) {
                    field.setAccessible(true);
                    field.set(obj, get(field.getName()));
                }
               ......
        }
    }
    在上述中,首先获取配置文件中已配置好的依赖关系,然后采用反射技术根据依赖关系进行创建相应的对象
    5.其中ioc.properties的内容为:
    departService=com.service.impl.DepartServiceImpl
    6.查看入口方法:
    public static void main(String[] args) {
            UserServiceImpl user=new UserServiceImpl();
        
            Container container=new Container();
            container.inject(user);
            user.printInfo(1);
    }

    7.查看结果:

    总结:可以说IoC这个思想是一个很伟大的思想,现在很多大神甚至将它归为GoF中(因为IoC出现的比较晚,错过了GoF“四人组”的《Design Patterns: Elements of Reusable Object-Oriented Software》)。

  • 相关阅读:
    VM网络故障问题
    Weblogic无法创建域报段错误排查过程记录
    xmind8 Pro序列号
    vs2015下载地址(安装包丢失或损坏)
    复旦大学数学学院20级高等代数I期中考试大题的高等代数II解法及其推广
    复旦高等代数I(21级)每周一题
    Nginx alias root 和 try_files 基本使用
    Nginx location 和 proxy_pass路径配置详解
    (PMP)第7版
    scheduler源码分析——preempt抢占
  • 原文地址:https://www.cnblogs.com/RoseVorchid/p/5967012.html
Copyright © 2020-2023  润新知