1.SpringIOC
IOC 全称为 Inversion of Control,即控制反转,是一种设计思想,而不是一个具体的技术
控制: 指对象创建(实例化,管理)的权力
反转:将控制权交给外部环境(IOC容器)
1.1 IOC的原理
IOC(控制反转)的核心原理依赖于两个关键概念:依赖注入(Dependency Injection,DI)和控制反转(Inversion of Control,IOC)。
- 依赖注入(Dependency Injection,DI):
依赖注入是实现 IoC 的一种主要机制,它通过外部注入的方式将对象间的依赖关系解耦。具体而言,依赖注入通过构造函数、属性或方法参数的形式,将一个对象所依赖的其他对象传递给目标对象。这样,目标对象不再负责自己依赖对象的创建和管理,而是通过外部容器(如 IoC 容器)来注入所需的依赖,进而实现了系统中组件之间的解耦与灵活配置。
- 控制反转(Inversion of Control,IOC):
控制反转是 IoC 的核心思想,它将传统应用程序中的控制流程从应用程序本身“反转”到外部容器或框架。传统上,应用程序代码负责创建对象、管理依赖关系及生命周期等任务,而在 IOC模式下,这些职责被转交给外部容器或框架,容器负责对象的创建、依赖关系的解析及生命周期的管理,应用程序则专注于业务逻辑的实现。通过控制反转,开发者不再显式管理依赖注入,增强了系统的可扩展性、可测试性和灵活性。
1.2 IOC的作用
控制反转(IOC,Inversion of Control)是一种软件设计模式,可以将程序中控制流程和对象生命周期的责任从应用程序代码中转移至外部框架或容器,进而由容器管理对象的创建、配置、生命周期及销毁等过程。IOC模式的应用带来了以下几个核心优势:
- 低耦合:
IoC通过将对象之间的依赖关系外部化,解耦了组件间的直接依赖。组件不再依赖于具体的实现类,而是依赖于抽象接口或规范。借助IoC容器进行依赖注入(Dependency Injection),依赖关系的管理由容器统一处理,从而减少了代码层面的耦合度。
- 简化代码:
IoC容器能够自动管理对象的生命周期、依赖注入、初始化、销毁等操作,显著减少了开发者需要编写的样板代码。通过容器的管理,程序员可以专注于业务逻辑的实现,从而使代码更加简洁、清晰,并且易于扩展和维护。
- 高灵活性:
通过IOC,系统的依赖和配置信息被抽象并外部化,可以通过修改配置文件或注解轻松更改应用程序的行为和组件的交互方式。这使得系统能够快速适应需求变更或技术栈的更新,从而增强了系统的灵活性。不同的实现和配置可以无缝切换,减少了系统对硬编码实现的依赖。
- 高可测试性:
在IOC模式下,由于依赖关系由容器负责注入, 我们可以很轻松地将对象装配到单元测试或集成测试中。这种方式使得测试变得更加高效和独立,避免了复杂的手动配置过程。
总结:
控制反转(IOC)通过将对象创建、依赖关系管理及生命周期控制从应用代码中抽离出来,实现了模块化设计,减少了耦合,简化了代码,提升了灵活性和可拓展性。这使得IOC成为现代软件架构中广泛应用的核心设计思想之一。
1.3 IOC的实现
1.3.1使用步骤
1.创建maven项目并导入spring-context坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.28</version>
</dependency>
2.创建需要注入的类
public class users {
}
3.使用xml或注解的形式声明需要注入该类
<bean id=" " class = " "></bean>
<bean id="users" class="com.ape.pojo.users"></bean>
4.获取bean对象
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
users users = (users) context.getBean("users");
System.out.println(users);
}
5.运行结果
可以看到我们并没有去创建对象,而是从容器直接中获取了对象. 因此,被注入IOC容器的对象, 就叫做Spring中的Bean
1.3.2 实现原理
我们在创建ApplicationContext 的地方打上断点运行
会发现在context容器中 ,有一个beanFactory 工厂, 里面有一个beanDefinitionMap中存放了我们注入容器的bean对象信息. 实际上, 当我们用xml或注解声明了要注入的类以后,容器启动时,就会用beanFactory帮我们去创建好一个bean实例 , 过程详见Spring中Bean的生命周期
我们使用时直接用id去获取该对象即可
2.Spring DI
2.1 Spring DI的概述
DI(Dependecy Inject,中文释义:依赖注入)
是对IOC概念的不同角度的描述,是指应用程序在运行时,每一个bean对象都依赖IOC容器注入当前bean对象所需要的另外一个bean对象。(例如在MyBatis整合Spring时,SqlSessionFactoryBean 依赖IOC容器注入一个DataSource数据源bean);
2.2 注入方式
1.set注入
必须提供被注入属性/对象的setter方法!
<property 属性= " " > </property>
name:属性名
ref:注入的值的引用
value:注入的值
基本数据类型和string
public class Student {
private String sname;
private String ssex;
private int age;
//set方法省略
}
<bean id="student" class="com.ape.bean.Student">
<property name="sname" value="Mr.li"></property>
<property name="age" value="21"></property>
<property name="ssex" value="男"></property>
</bean>
输出:
JavaBean对象:
三层架构, 层层调用, 声明后并提供setter方法
public class StudentDaoImp implements IStudentDao {
@Override
public void save() {
System.out.println("===dao===");
}
}
public class StudentServiceimp implements IStudentService {
IStudentDao studentDao ;
public void setStudentDao(IStudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
public void save() {
System.out.println("===service===");
studentDao.save();
}
}
public class StudentControllerimp implements IStudentController {
//通过set方法实现DI注入
IStudentService studentService;
public void setStudentService(IStudentService studentService) {
this.studentService = studentService;
}
@Override
public void save() {
System.out.println("===controller===");
studentService.save();
}
}
xml文件中注入
<bean id="controller" class="com.ape.controller.StudentControllerimp">
<property name="studentService" ref="service"></property>
</bean>
<bean id="service" class="com.ape.service.StudentServiceimp">
<property name="studentDao" ref="dao"></property>
</bean>
<bean id="dao" class="com.ape.dao.StudentDaoImp"></bean>
运行结果
复杂类型
public class Teacher {
private List mylist;
private Set myset;
private String[] arr;
private Map mymap;
private Properties pop;
//setter方法省略
}
<bean id="teacher" class="com.ape.bean.Teacher">
<property name="mylist">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<property name="myset">
<set>
<value>4</value>
<value>5</value>
<value>6</value>
</set>
</property>
<property name="arr">
<array>
<value>7</value>
<value>8</value>
<value>9</value>
</array>
</property>
<property name="mymap">
<map>
<entry key="11" value="11"></entry>
<entry key="22" value="22"></entry>
<entry key="33" value="33"></entry>
</map>
</property>
<property name="pop">
<props>
<prop key="44">44</prop>
<prop key="55">55</prop>
<prop key="66">66</prop>
</props>
</property>
</bean>
运行结果
2.构造注入
<constructor-arg name=" " value=" "></constructor-arg>
属性:
name:属性名
type: 参数类型
index: 参数下标
ref:注入的值的引用
value:注入的值
基本类型和string
public class Student {
private String sname;
private String ssex;
private int age;
public Student(String sname, String ssex, int age) {
this.sname = sname;
this.ssex = ssex;
this.age = age;
}
public Student() {
}
}
<bean id="student1" class="com.ape.bean.Student">
<constructor-arg name="sname" value="Mr.li"></constructor-arg>
<constructor-arg name="age" value="21"></constructor-arg>
<constructor-arg name="ssex" value="男"></constructor-arg>
</bean>
运行结果
JavaBean对象
public class StudentDaoImp implements IStudentDao {
@Override
public void save() {
System.out.println("===dao===");
}
}
public class StudentServiceimp implements IStudentService {
IStudentDao studentDao ;
public StudentServiceimp(IStudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
public void save() {
System.out.println("===service===");
studentDao.save();
}
}
public class StudentControllerimp implements IStudentController {
//通过构造方法实现DI注入
IStudentService studentService;
public StudentControllerimp(IStudentService studentService) {
this.studentService = studentService;
}
@Override
public void save() {
System.out.println("===controller===");
studentService.save();
}
}
<bean id="controller" class="com.ape.controller.StudentControllerimp">
<constructor-arg name="studentService" ref="service"></constructor-arg>
</bean>
<bean id="service" class="com.ape.service.StudentServiceimp">
<constructor-arg name="studentDao" ref="dao"></constructor-arg>
</bean>
<bean id="dao" class="com.ape.dao.StudentDaoImp"></bean>
运行:
属性注入
使用成员属性注入 bean ,不推荐。原因:使用私有的成员属性变量,依靠反射实现,破坏封装,只能依靠IOC容器实现注入,不严谨;
总结
IOC ( Inversion of Control, 中文释义:控制反转) 是 spring框架的核心思想之一,主要用于解耦。 IOC 是指将创建对象的控制权转移给 spring框架进行管理。由 spring框架根据配置文件或注解等方式,创建 bean 对象并管理各个 bean 对象之间的依赖关系。使对象之间形成松散耦合的关系,实现解耦:
DI (Dependecy Inject,中文释义:依赖注入)则是对IOC概念的不同角度的描述,是指应用程序在运行时,每一个bean对象都依赖IOC容器注入当前bean对象所需要的另外一个bean对象。
.