Spring IoC

85 阅读2分钟

1. Spring IoC 简介

1.1 什么是 Spring IoC?

IoC:Inversion of Control,中文译为“控制反转”。它不是什么技术,而是一种思想:将原先自己实例化的对象交给 IoC 容器去实现。

控制反转可以拆分成“控制”和“反转”两个词来理解

  • 控制:指的是对象创建的权利
    • 就是我们平常用的最多的 new 关键字
  • 反转:指的是把控制权交给外部的容器
    • 就是说我们不需要写 new 关键字来创建对象了,而是通过 IoC 容器来帮助我们实例化对象,以后我们用到哪个对象,就跟 IoC 容器要即可

1.2 使用 IoC 带来了哪些好处呢?

IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。所以带来的好处有:

  • 对象之间的耦合度或者说依赖程度降低
  • 资源集中管理,实现资源的可配置和易管理

1.3 IoC 和 DI 的区别

IoC 是一种思想,将对象创建的权利交给 IoC 容器(Spring 框架)来管理。

DI:Dependency Injection,中文译为“依赖注入”,它是实现 IoC 最常见以及最合理的方式。

在 Spring 框架中,有三种注入方式(其实有四种,只不过接口注入的方式已经被废弃了)

  • set 方法注入
public interface UserDao {
    void insert();
}
public class UserDaoImpl implements UserDao {
    @Override
    public void insert() {
        System.out.println("插入用户...");
    }
}
public interface UserService {
    void insert();
}
public class UserServiceImpl implements UserService {

    UserDao userDao;
  
		// set 方法注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void insert() {
        userDao.insert();
    }
}
public class Demo1 {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");

        System.out.println("spring 容器启动成功");

        UserService service = context.getBean("userService", UserService.class);
        service.insert();

    }
}
<?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="userDao" class="com.fyl.springboot.ioc.dao.UserDaoImpl"/>

    <bean id="userService" class="com.fyl.springboot.ioc.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>
</beans>
  • 构造器注入

以上面 set 注入的代码为基础,只需要修改 UserServiceImpl 和 beans.xml 即可

public class UserServiceImpl implements UserService {

    UserDao userDao;
		
  	// 构造器注入
  	public UserServiceImpl(UserDaoImpl userDao) {
        this.userDao = userDao;
    }

    @Override
    public void insert() {
        userDao.insert();
    }
}
<?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="userDao" class="com.fyl.springboot.ioc.dao.UserDaoImpl"/>

    <bean id="userService" class="com.fyl.springboot.ioc.service.UserServiceImpl">
        <constructor-arg ref="userDao"/>
    </bean>
</beans>
  • 注解方式

@Autowired 默认按类型装配

@Qualifier 和 @Autowired 配合使用,可以指定 bean 的名称

@Resource 默认按名称装配,当找不到与名称匹配的 bean 时,才会按类型装配


注解的方式改动的代码有点多:

首先 beans.xml 里的内容跟前两个已经完全不一样了

其次 UserServiceImpl 和 UserDaoImpl 都需要加上 @Component 注解

@Component
public class UserDaoImpl implements UserDao {
    @Override
    public void insert() {
        System.out.println("插入用户...");
    }
}
@Component
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void insert() {
        userDao.insert();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

  	<!-- base-package 项目启动后,会扫描这个包下所有的 @Component 注解的类,注册到 Spring IoC 容器中 -->
    <context:component-scan base-package="com.fyl.springboot.ioc"/>
    <context:annotation-config/>
</beans>

2. 源码分析