Spring控制反转(Ioc)和依赖注入(DI)

为什么需要控制反转

我们经常在service层需要调用dao层的方法,在controller层调用service层的方法,在学习spring之前,我们使用 new 对象 的方法进行方法调用

java 复制代码
// dao
public interface UserDao {
    public void save();
}
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("user dao save ...");
    }
}
// service
public interface UserService {
    public void save();
}
public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoImpl();
    public void save() {
        System.out.println("user service ...");
        userDao.save();
    }
}
  • 业务层需要调用数据层的方法,就需要在业务层new数据层的对象,代码耦合度偏高
  • 为解决这个问题,Spring提出控制反转这一核心概念,使用对象时,在程序中不再使用new产生对象,转换为由"外部"提供对象

控制反转是什么

Spring控制反转(IoC)是一种设计模式,用于将控制权从代码本身转移到外部容器。

  • 控制:对象的创建权
  • 反转:对象的创建权由程序内部(new 对象) 转移到外部(Spring Ioc 容器)
  • 在Spring框架中,我们可以通过配置文件或注解来描述这些对象,并将它们装配到容器中。这样,当我们需要访问某个对象时,我们不再需要显式地创建它,而是可以在容器中查找它并获取对它的引用。

Spring和Ioc的关系

  • IoC是Spring框架的核心概念之一,它通过实现依赖注入(DI)来实现对象之间的解耦和管理。
  • Spring技术对IOC思想进行了实现,他提供了一个容器,称为IOC容器,用来充当IOC思想中的"外部"
  • Spring的IoC容器负责创建、管理和维护应用程序中所需要的对象及其之间的关系。
  • 创建或被管理的对象在IOC容器中统称为 Bean

依赖注入是什么?

依赖注入 即DI(Dependency Injection),它是一种软件设计模式,用于管理对象之间的关系和依赖,在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。

  • 我们可以根据需求建立起依赖关系,如上述代码,业务层需要依赖数据层,UserService就要和UserDao建立依赖关系

依赖注入常见的三种方式

  • 构造函数注入(Constructor Injection):通过构造函数将依赖对象传递给Bean。
  • 属性注入(Setter Injection):通过属性的setter方法将依赖对象注入到Bean中。
  • 注解注入(Annotation Injection):使用注解(如@Autowired、@Resource)注入依赖对象。

修改上述代码,删除service中使用new的方式创建的dao对象

java 复制代码
// service
public interface UserService {
    public void save();
}
public class UserServiceImpl implements UserService {
    private UserDao userDao ;
    public void save() {
        System.out.println("user service ...");
        userDao.save();
    }
}

构造函数注入

  • UserServiceImpl中添加一个构造函数接收一个UserDao对象,并将其分配userDao字段
java 复制代码
    // UserServiceImpl 中添加构造函数
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

可以使用XML配置文件或注解来指定依赖项的注入方式。

此处使用XML配置文件进行构造函数注入

xml 复制代码
<bean id="userService" class="com.example.UserServiceImpl">
    <constructor-arg ref="userDao" />
</bean>
​
<bean id="userDao" class="com.example.UserDao" />
​
  • bean-id :bean的唯一标识名
  • class:指定 bean 的类型,配置bean的全路径类名,与具体java类一致
  • constructor-arg: 来指定构造函数参数,ref 属性指定了依赖的 dao Bean,ref的值与bean的标识名一致

setter注入

在 UserServiceImpl 中添加一个Setter方法接收 UserDao对象,并将其分配给userDao字段

java 复制代码
// 添加set方法
public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

使用XML配置文件进行set注入

xml 复制代码
<bean id="userService" class="com.example.UserServiceImpl">
    <property name="userDao" ref="userDao" />
</bean>
​
<bean id="userDao" class="com.example.UserDao" />
​
  • property: 用于来指定set注入的属性依赖项
  • name:指定要注入的属性名称,Spring的IOC容器在获取到名称后,将首字母大写,前面加set找对应的setUserDao()方法进行对象注入,所以 name的值应与 java类中对应字段的值一致
  • ref:属性指定了依赖的 userDao Bean。Spring将会在IOC容器中找到id为userDao的Bean对象给userService进行注入

注解注入

在上述UserDaoImpl类上添加@Component注解

java 复制代码
@Component("userDao")
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("user dao save ..." );
    }
}
  • @Component:类似注册了一个bean,id为 userDao

在UserServiceImpl 中添加字段注解:@Autowired ,添加类注解@Component

java 复制代码
@Component
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao ;
    public void save() {
        System.out.println("user service ...");
        userDao.save();
    }
}
​

XML配置文件配置组件扫描

xml 复制代码
<context:component-scan base-package="com.example" />
  • 使用<context:component-scan>元素来指定要扫描的包,使Spring容器能够自动检测到带有@Autowired注解的依赖项。

在实际开发中,我们大多数情况下使用注解的方式进行开发

相关推荐
小菜yh2 小时前
关于Redis
java·数据库·spring boot·redis·spring·缓存
爱上语文4 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
荆州克莱4 小时前
springcloud整合nacos、sentinal、springcloud-gateway,springboot security、oauth2总结
spring boot·spring·spring cloud·css3·技术
拾光师10 小时前
spring获取当前request
java·后端·spring
xujinwei_gingko11 小时前
Spring IOC容器Bean对象管理-Java Config方式
java·spring
Xua305512 小时前
浅谈Spring Cloud:认识微服务
spring·spring cloud·微服务
JOJO___14 小时前
Spring IoC 配置类 总结
java·后端·spring·java-ee
黄昏_15 小时前
苍穹外卖Day01-2
java·spring
亚林瓜子15 小时前
Jackson注解屏蔽某些字段读取权限
spring·json·jackson