什么是DI(依赖注入),依赖注入的原理

这篇文章主要介绍了Spring当中的依赖注入(DI),以及他的简单实现原理,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

什么是依赖注入?

  • Dependency Injection。它是 spring 框架核心 ioc 的具体实现。
  • 我们的程序在编写时,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。通过容器只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。
  • 那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

依赖注入的原理

所谓的依赖注入其实就是通过反射给成员变量赋值,这里的成员变量就是我们所说的依赖。比如TestController当中有个TestService对象,他需要依赖TestService对象当中的方法,那么TestService就是TestController的依赖。

这里就考验到了通过反射我们有几种方式可以给TestService赋值,一共有如下三种:

  1. 通过构造器给变量赋值
  2. 通过set方法给变量赋值
  3. 直接给属性赋值

下面我们直接通过案例来理解:

下面是正常的一个controller调用service的过程,一般我们在TestService这里都会使用一个@Autowired或者@Resource注解,表示由spring进行注入,Spring扫描注解的时候就知道这个变量需要注入,于是他便会去容器当中寻找该对象的实例,然后通过反射将其注入到变量当中。

public class TestController {

    private TestService testService;

    public TestController() {
        System.out.println("TestController初始化了");
    }

    public TestController(TestService testService) {
        this.testService = testService;
    }

    public void setTestService(TestService testService) {
        this.testService = testService;
    }

    public void method1() {
        testService.method1();
    }
}

然后service代码如下:

public class TestService {

    public TestService() {
        System.out.println("TestService初始化了");
    }

    public void method1() {
        System.out.println("method1方法执行了");
    }
}

(1)通过构造器给变量赋值:

@Test
public void test5() throws Exception {
    Class cls = Class.forName("com.gzl.cn.controller.TestController");
    Constructor constructor = cls.getConstructor(TestService.class);
    TestController testController = (TestController)constructor.newInstance(new TestService());
    testController.method1();
}

运行结果:

(2)通过set方法给变量赋值:

public static void main(String[] args) throws Exception{
    Class cls = Class.forName("com.gzl.cn.controller.TestController");
    // 根据方法名和参数类型找到对应的set方法
    Method mtd = cls.getMethod("setTestService", TestService.class);
    // 创建TestController的实例
    TestController testController = (TestController)cls.newInstance();
     执行TestController实例的这个方法,正常来说TestService不是new的,他会看看容器有没有,有的话取容器的
    TestService testService = new TestService();
    mtd.invoke(testController, testService);
     这时候已经完成属性的注入了
    testController.method1();
}

运行结果:

(3)直接给属性赋值:

@Test
public void test6() throws Exception {
    Class cls = Class.forName("com.gzl.cn.controller.TestController");
    TestController testController = (TestController) cls.newInstance();
    // 这时候假如直接访问,会异常,因为testService属性此刻还为空
    //testController.method1();

    // 这里注意要使用getDeclaredField,不要用getField,因为testService属性并不是public
    Field testServiceField = cls.getDeclaredField("testService");
    // 这里要设置true,不然修改private修饰符的属性会异常
    testServiceField.setAccessible(true);
    testServiceField.set(testController, new TestService());
    testController.method1();
}

运行结果:

依赖注入本质上就是基于这三种反射注入的方式进行的注入的,只不过给我们提供了相应的注解,方便我们使用,并且他还能够很好的结合IOC容器来使用!

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怪 咖@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值