深入谈谈 Java IOC 和 DI
阅读原文时间:2023年07月08日阅读:1

1.前言

  不得不说, IOC和DI 在写代码时经常用到。还有个就是在面试时 ,面试官老喜欢问 IOC 和DI是什么的问题,都快被问吐了,

可是,仍然会让许多人说的支支吾吾。

  为什么?

第一,因为这个知识实在是太基础了,忽略了操作的叫法,即便开发时老是在使用这个知识点,但是并不知道一直写的这个原来是叫这个啊!
第二,不知道底层原理,谁不知道IOC是控制反转 ,DI是依赖注入?那么面试官来了句为什么?怎么用?那岂不是就凉凉了?

2.定义:

IOC ,英文全称是Inverse of Control,控制反转。
DI,英文全称是Dependency Injection ,依赖注入。

3.总结

(1)IOC是控制反转 ,就是将依赖类的控制权从容器类中移除,将其移到容器类外部去,使用容器类之前,需要从外部将依赖类注入进来。
(2)那么注入依赖类的过程就是DI,意为依赖注入。
(3)能够将依赖类注入容器类的方式共有4种,但是DI依赖注入只占其中的3种,
  分别是构造函数注入【也称构造器注入】、setter注入【也称属性注入】、接口注入【具有侵入性,不建议使用】。
  还有一种是使用javabean容器注入。
(4)而初始化Javabean的容器方式有两种,分别是
  低级容器 XMLBeanFactory【实例对象类型是BeanFactory】、
  高级容器 ClassPathXmlApplicationContext【实例对象类型是ApplicationContext】
  分别将依赖类和容器类使用XML文件注册javabean,然后在容器类的标签内配置注入依赖类的信息,
  可以直接使用属性 p:
  格式是p:【属性名】-ref=“【依赖类的标签id】”
  也可以使用里面使用标签配置

4.不使用IOC

这里演示不使用IOC的写法

目录结构

依赖类

package com.example.javabaisc.ioc;

/**
* 依赖类
*/
public class MDependency {
public String food(){
return "苹果";
}
}

容器类

package com.example.javabaisc.ioc;

/**
* 容器类
*/
public class MContainer {
public void eat(){
System.out.println("饿了,有什么吃的?");
//实例依赖类
MDependency m = new MDependency();
System.out.println(m.food());
}
}

测试类

package com.example.javabaisc.ioc;

import org.junit.Test;

public class IOCTest {

@Test  
public void t(){  
    //实例容器类  
    MContainer mContainer = new MContainer();  
    mContainer.eat();  
}  

}

打印结果

5.构造函数注入

目录结构

依赖类

package com.example.javabaisc.ioc;

/**
* 依赖类
*/
public class MDependency {
public String food(){
return "苹果";
}
}

容器类

package com.example.javabaisc.ioc;

/**
* 容器类
*/
public class MContainer {
//存储 依赖类对象
private final MDependency m;

//有参构造器  
public MContainer(MDependency mDependency){  
    this.m = mDependency;  
}

public void eat(){  
    System.out.println("饿了,有什么吃的?");  
    System.out.println(m.food());  
}  

}

测试类

package com.example.javabaisc.ioc;

import org.junit.Test;

public class IOCTest {

@Test  
public void t(){  
    //实例依赖类  
    MDependency mDependency = new MDependency();  
    //实例容器类,并将依赖类对象作为参数注入  
    MContainer mContainer = new MContainer(mDependency);  
    mContainer.eat();  
}  

}

打印结果

6.setter注入

目录结构

依赖类

容器类

package com.example.javabaisc.ioc;

/**
* 容器类
*/
public class MContainer {
//存储 依赖类对象
private MDependency m;

//setter方法  
public void setM(MDependency m) {  
    this.m = m;  
}

public void eat(){  
    System.out.println("饿了,有什么吃的?");  
    System.out.println(m.food());  
}  

}

测试类

package com.example.javabaisc.ioc;

import org.junit.Test;

public class IOCTest {

@Test  
public void t(){  
    //实例依赖类  
    MDependency mDependency = new MDependency();  
    //实例容器类  
    MContainer mContainer = new MContainer();  
    //调用set方法将依赖类对象作为参数注入  
    mContainer.setM(mDependency);  
    //  
    mContainer.eat();  
}  

}

打印结果

7.接口注入

接口

package com.example.javabaisc.ioc;

public interface MDependencyInterface {
//注入依赖类对象
void food(MDependency mDependency);
}

依赖类

package com.example.javabaisc.ioc;

/**
* 依赖类
*/
public class MDependency {
public String food(){
return "苹果";
}
}

容器类

package com.example.javabaisc.ioc;

/**
* 容器类
*/
public class MContainer implements MDependencyInterface {
//存储 依赖类对象
private MDependency m;

//重写接口方法【实现接口】  
@Override  
public void food(MDependency foodname) {  
    m = foodname;  
}

public void eat() {  
    System.out.println("饿了,有什么吃的?");  
    System.out.println(m.food());  
}

}

测试类

package com.example.javabaisc.ioc;

import org.junit.Test;

public class IOCTest {

@Test  
public void t(){  
    //实例依赖类  
    MDependency mDependency = new MDependency();  
    //实例容器类  
    MContainer mContainer = new MContainer();  
    //调用接口方法将依赖类对象作为参数注入  
    mContainer.food(mDependency);  
    //  
    mContainer.eat();  
}  

}

打印结果

8.javabean容器注入

目录结构

javabean配置xml文件


http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="mDependency" class="com.example.javabaisc.ioc.MDependency"/>  
<!--写法一 -->  
<bean id="mContainer" class="com.example.javabaisc.ioc.MContainer" p:m-ref="mDependency"/>  
<!--写法二 -->  
<!--    <bean id="mContainer" class="com.example.javabaisc.ioc.MContainer">-->  
<!--        <property name="m" ref="mDependency"/>-->  
<!--    </bean>-->

依赖类

package com.example.javabaisc.ioc;

/**
* 依赖类
*/
public class MDependency {
public String food(){
return "苹果";
}
}

容器类

package com.example.javabaisc.ioc;

/**
* 容器类
*/
public class MContainer {
//存储 依赖类对象
private MDependency m;

public void eat() {  
    System.out.println("饿了,有什么吃的?");  
    System.out.println(m.food());  
}

//这是xml文件的javabean使用setter方式将依赖类对象注入进来  
public void setM(MDependency m) {  
    this.m = m;  
}

}

测试类

package com.example.javabaisc.ioc;

import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class IOCTest {
@Test
public void t() {
//低级容器【被抛弃了,不建议使用】
//初始化xml文件里的javabean
// BeanFactory javabean = new XmlBeanFactory(new ClassPathResource("iocConfig.xml"));
//高级容器
//全局初始化xml文件里的javabean
ApplicationContext javabean = new ClassPathXmlApplicationContext("iocConfig.xml");
//实例容器类
MContainer mContainer = (MContainer) javabean.getBean("mContainer");
mContainer.eat();

}  

}

打印结果