spring的IOC和DI

时间:2022-07-25
本文章向大家介绍spring的IOC和DI,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

IOC是什么?

Ioc—Inversion of Control,即“控制反转”,是一种设计思想。而Spring IOC是应用了该设计思想,能过IOC容器来间接管理bean。

IOC解决什么问题?

IOC主要是起到一个解耦的作用,使程序更加灵活,主要思想是将设计好的程序对象由原来程序来主动控制交给IOC容器控制,反转就是将控制权交给容器来统一管理,而非我们从代码层面手动去控制,当需要获取该对象的时候直接到spring容器中去获取就可以了。所谓反转则是将原来需要手动new 对象(正转),交由spring IOC容器进行控制(创建、赋值、销毁等),所称反转。即

手动正转: Object xx = new Object();

IOC反转 Object xx = IOC容器创建;

个人理解:IOC就类似于父母没时间带孩子,让爷爷奶奶带(IOC),爷爷奶奶负责小孩子的吃喝玩耍,父母只负责接送,而爷爷奶奶就类似于IOC。

DI是什么?

DI的全称是:Dependency Injection(依赖注入),组件之间依赖关系由容器在运行期决定,通过DI可以为对象注入相对应的信息。就比如当将对象中的setter赋上某些值或者将对象的值赋到别外一个对象中,该行业简单DI。

个人理解:你需要挂一副画,将钉子打到墙上,这个打到墙上的行为称为DI。

IOC与DI关系

IOC是一种思想,而DI是该思想的具体实现,spring通过组件之间的依赖关系由容器在需要的时候进行注入相关的对象信息。Spring 的DI有三种实现:set注入、构造器注入、静态工厂注入、实例工厂注入

代码下载:https://gitee.com/hong99/spring/issues/I1N1DF

源码实现

/**
 * @Auther: csh
 * @Date: 2020/7/7 17:56
 * @Description:用户信息
 */
public class User implements Serializable {
    private String userName;
    private int age;

    public User() {
    }

    public User(String userName, int age) {
        this.userName = userName;
        this.age = age;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + ''' +
                ", age=" + age +
                '}';
    }
}
/**
 * @Auther: csh
 * @Date: 2020/7/7 17:56
 * @Description:用户信息
 */
public class User2 implements Serializable {
    private String userName;
    private int age;

    public User2() {
    }

    public User2(String userName, int age) {
        this.userName = userName;
        this.age = age;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + ''' +
                ", age=" + age +
                '}';
    }
}
public interface MessageService { 
   String getMessage();
   }
@Service("messageService")public class MessageServiceImpl implements MessageService {
    public String getMessage() { 
           return "hello world";    
           }
   
/**
 * @Auther: csh
 * @Date: 2020/7/7 11:44
 * @Description:
 */
public class IocTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile*.xml");
        System.out.println("context 已启动!");
        //setter实现
        User user = context.getBean(User.class,"user");
        System.out.println("user信息:"+user.toString());
        //构造方法获取
        User2 user2 = context.getBean(User2.class, "user2");
        System.out.println("user信息:"+user2.toString());
        //自动注解方式
        MessageService service = context.getBean(MessageService.class);
        //打印service的信息
        System.out.println(service.getMessage());
    }

}

配置文件:

applicationfile-arg.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--通过构造方法注入-->
    <bean id="user2" class="com.hong.spring.ioc.entity.User2" >
        <constructor-arg name="age" value="111" />
        <constructor-arg name="userName" value="csh2" />
    </bean>
</beans>

applicationfile-scan.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--通过构造方法注入-->
    <bean id="user2" class="com.hong.spring.ioc.entity.User2" >
        <constructor-arg name="age" value="111" />
        <constructor-arg name="userName" value="csh2" />
    </bean>
</beans>

applicationfile-setter.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--通过属性注入-->
    <bean id="user" class="com.hong.spring.ioc.entity.User" >
        <property name="age" value="20" />
        <property name="userName" value="csh" />
    </bean>
</beans>

结果

context 已启动!
user信息:User{userName='csh', age=20}
user信息:User{userName='csh2', age=111}
hello world

代码下载:https://gitee.com/hong99/spring/issues/I1N1DF

总结

IOC的思想其实就是进行解耦,使程序更加灵活,而DI就是IOC的具体实现,主要通过注入方式直接将对IOC 的容器是spring bean通过类图发现,ApplicationContext是整个spring的入口也是核心(心脏),它是通BeanFactory的一种实现,当然ApplicationContext的实现也非常多,可以下图参照:

参考文献:

https://www.martinfowler.com/articles/injection.html

https://www.iteye.com/blog/jinnianshilongnian-1413846

https://caojiele.com/2019/03/28/spring-ioc/

https://www.javazhiyin.com/61040.html

循环依赖:

https://www.jianshu.com/p/6c359768b1dc