【Spring】谈谈IOC和DI

本文详细介绍了控制反转(IOC)和依赖注入(DI)的概念,展示了Spring容器中bean的管理,包括不同scope的理解,以及XML配置、注解@Autowired和@Resource的区别。重点讲解了构造方法注入和set注入的实践,并阐述了Spring IOC容器的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,有很多人都说DI就是IOC,其实看你怎么理解了。
如下我们看到ApplicationContext有这么多的实现类,每一种都相当于一个DI,实现了IOC的思想。
在这里插入图片描述

1、什么是IOC和DI

以前用对象是自己是通过new 来获取,现在 通过spring容器来进行创建并通过注入的方式来获取。这个创建对象的控制权由调用者自己变成了spring容器
在这里插入图片描述
依赖注入(DI)一般由三种方式进行注入(构造方法、set、注解)

2、bean的一些元素

由IOC容器管理的称为bean,Spring容器启动的时候就加载了bean对象

2.1、scope

总共有六个,分别是:

  • singleton:单个对象实例,spring默认创建的对象的方式就是单例的
  • prototype:原型,任意数量的对象实例
  • request
  • session
  • application
  • websocket
2.2、自动注入bean(bean对象中注入引入的bean)
2.2.1、xml方式

前提:有两个类一个是Address,一个是User,其中User中有一个成员变量Address

public class User {
    private String userName;
    private Address address;
    public User(){
        System.out.println("user无参构造");
    }
    public Address getAddress() {
        return address;
    }
    public User setAddress(Address address) {
        this.address = address;
        return this;
    }

    public String getUserName() {
        return userName;
    }

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

方式一:

    <bean id="user" class="com.guang.spring.ioc.Model.User"  autowire="byName">
        <property name="userName" value="liguang"></property>
    </bean>
    <bean id="address" class="com.guang.spring.ioc.Model.Address">
        <property name="address" value="北京"></property>
    </bean>

方式二:

   <bean id="user" class="com.guang.spring.ioc.Model.User">
        <property name="userName" value="liguang"></property>
        <property name="address" ref="address"></property>
    </bean>

方式一的结果和方式二相同,只不过是autowire=“byName” 代替了 <property name="address" ref="address"></property>,通过set方法的名字自己注入。

2.2.2、注解@Autowired

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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="user" class="com.guang.spring.ioc.Model.User"></bean>
    <bean id="address" class="com.guang.spring.ioc.Model.Address"></bean>
    <!--开启注解-->
    <context:annotation-config/>
</beans>

User类中

    @Autowired
    private Address address;

以上同样能实现自动注入

2.2.3、@Resource和Autowired区别
  • 都是用来自动装配的,都可以放在属性字段上
  • @Autowired通过byType的方式实现,如果@Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value=“xxx”)
  • @Resource默认通过byname的方式实现,如果查找不到名字,则通过byType实现,如果两个都找不到就报错
  • @Autowired是Spring自己的注解,但是@Resource是jdk的注解,只不过Spring都支持

上面所说的byname其实就是根据bean下的id值找到对应java中的set名

3、Spring常用的依赖注入方式(DI)(bean注入到Spring容器中)

介绍之前建议快速过一下官网 https://docs.spring.io/spring-framework/docs/5.2.13.RELEASE/spring-framework-reference/core.html#beans-basics

3.1 构造方法注入

maven项目 pom:

       <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.3</version>
        </dependency>

User类:

package com.guang.spring.ioc.Model;
public class User {
    private String userName;
    public User(String userName){
        this.userName=userName;
    }
    public String getUserName() {
        return userName;
    }
    public void show(){
        System.out.println("name="+userName);
    }
}

beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--使用Spring来创建对象,在Spring中这些都称为bean
    User user=new User();
    id=变量名
    class=new 对象;
    -->
    <bean id="user" class="com.guang.spring.ioc.Model.User">
        <constructor-arg name="userName" value="guangge"></constructor-arg>
    </bean>
</beans>

测试类:

public class MyTest {
    public static void main(String[] args) {
        //配置文件的地址,并且可以传多个,获取Spring上下文对象
        // context 就相当于Spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //我们的对象现在都在Spring中管理了,我们要使用,直接去里面取出来
        User user = context.getBean("user",User.class);
        user.show();
    }
}

结果:
在这里插入图片描述

3.2 set注入(重要 )

User

package com.guang.spring.ioc.Model;
public class User {
    private String userName;
    public User(){
        System.out.println("user无参构造");
    }

    public String getUserName() {
        return userName;
    }

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

    public void show(){
        System.out.println("name="+userName);
    }
}

beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--使用Spring来创建对象,在Spring中这些都称为bean
    User user=new User();
    id=变量名
    class=new 对象;
    -->
    <bean id="user" class="com.guang.spring.ioc.Model.User">
        <property name="userName" value="liguang"></property>
    </bean>
</beans>

结果:
在这里插入图片描述
注意:
(1)name属性值与类中的成员变量名以及set方法的参数名都无关,只与对应的set方法名有关 如上name为userName 那么对应的set也要为setUserName
(2)如果通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上,否则spring没有办法实例化对象,导致报错。

3.3 Spring IOC容器

(1)BeanFactory 容器
提供了配置框架的基本功能
(2)ApplicationContext
它实现了BeanFactory ,增加了新的功能,我们上面用到的ClassPathXmlApplicationContext和ClassPathXmlApplicationContext都是ApplicationContext

后记

上述方式注册bean,我们在开发中不会这么用,一般就用@controller @service等注解都解决了,这里只是剖析原理

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值