Spring IOC 和 DI

2020-04-30  本文已影响0人  树木有朋

IOC

在有 IOC 概念之前,我们要使用一个对象,通常会使用 Object obj = new Object(),这种实现方式存在以下问题:

  1. 高耦合。如果一个地方用到还好,假设项目中很多地方都要用到该对象,就会在每个地方去 new ,这样子呢就会和业务代码等紧耦合。
  2. 扩展性不好。如果以后实现方式有变化,那么可能就需要批量替换的方案,但是也会引来一定的风险,并且有些可能根本无法替换。

那么是否可以使用工厂模式取代 new 操作呢?这样子如果变更的话,只需要改变工厂方法的实现即可。其实这样只是将 new 对象的问题延迟到了工厂方法里而已。

那么我们是否可以不关心要使用的对象是如何创建的,当要用的时候就可以直接用呢?Spring IOC 就能做到。先不用去看 IOC 实现源码,我们大概来猜测一下,Spring IOC 做了哪些工作呢?

DI

DI 中文翻译为依赖注入,其中核心为 反射。下面我们使用自定义注解来模拟 Spring 的 Autowired。

  1. 先定义自定义注解类

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Autowired {
    }
    
  2. 定义 Controller

    public class TestController {
        @Autowired
        private TestService testService;
    
        public void print() {
            System.out.println(testService);
        }
    }
    
  3. 编写一个测试类

    public class TestControllerTest {
    
        @Test
        public void test() {
            TestController testController = new TestController();
            Field[] declaredFields = testController.getClass().getDeclaredFields();
            Arrays.stream(declaredFields).forEach(field -> {
                Autowired annotation = field.getAnnotation(Autowired.class);
                if (annotation != null) {
                    try {
                        field.setAccessible(true);
                        Class<?> type = field.getType();
                        // 该例子中使用的 type.getConstructor().newInstance();
                        // Spring 中使用的是 IOC 容器获取
                        Object o = type.getConstructor().newInstance();
                        field.set(testController, o);
                    } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
                testController.print();
            });
        }
    }
    

如上,便可以实现我们自定义的依赖注入,可以看到核心原理就是利用了 Java 的反射机制,只不过在本例中,我们通过 type.getConstructor().newInstance(); 创建类的实例,而在 Spring 中使用 IOC 容器管理。

上一篇 下一篇

猜你喜欢

热点阅读