浅谈SpringIOC – 01
路漫漫其修远兮,吾将上下而求索
0. Spring是啥
Spring其实就是指的Spring Framework,它是一个框架。官方对其描述是如下:
Spring Framework为现代基于Java的企业应用程序提供了一个全面的编程和配置模型。Spring的一个关键元素是应用程序级别的基础设施支持,主要专注于企业应用程序的“管道”,以便团队可以专注于应用程序级的业务逻辑,而无需与特定部署环境产生不必要的联系
我个人对于以上的理解是,Spring Framework就是一套框架,使用它来写代码,我们就可以更专注于程序的业务逻辑,而对于业务之间的依赖,可以通过Spring Framework帮我们统一管理。其中的框架包含了:IOC(控制反转)、AOP(切面编程)、事务、数据绑定、验证等等(https://docs.spring.io/spring-framework/docs/current/reference/html/)
1. Spring IOC是啥
对于Spring Framework有了一点概念之后,我们需要知道它主要是帮我们做了些什么,如何帮助我们简化企业应用程序开发的呢。那就不得不提其最为核心的Spring IOC了。先看看官方对于IOC的描述
IOC(Inversion of Control 控制反转)也称为依赖注入(DI),这是一个过程,其中对象仅通过构造函数参数、工厂方法的参数或者在对象实例被构造或者从工厂返回后再对象实例上设置的属性来定义他们的依赖项(即它们需要用到哪些对象),然后容器在创建bean时注入这些依赖项。这个过程基本上是bean本身的逆过程(因此得名,控制反转)。
也就是说,我们之前需要一个对象时,需要自己在代码中创建,即通过new一个对象的方式,但是现在我们只需要在Spring IOC中配置好我们哪些对象依赖了哪些对象,这样Spring容器在创建bean(也就是对象)的时候,就会帮我们注入所依赖的对象。我们就不用在代码中去new创建了,只需要在Spring 中配置就可以了。其实它就相当于一个大工厂,对于在万物皆对象的Java中,有了Spring之后,我们就不用担心对象之间的复杂依赖关系了,所有对象的创建和维护都由Spring容器来管理,这样也可以降低程序的耦合性。
2. Spring环境搭建
实践是检验真理的唯一标准 。好了,大概了解了理论之后,就来动手实践一下吧。
2.1 新建一个Maven项目
首先创建一个普通maven项目,并在pom文件中,添加好spring所需依赖,这里有一些依赖包并不是必要的,但为了以后方便使用,也直接先导入到依赖中来。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>top.xiateman</groupId>
<artifactId>spring-ioc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<org.springframework.version>5.3.10</org.springframework.version>
<commons-logging.version>1.2</commons-logging.version>
<junit.version>4.12</junit.version>
</properties>
<dependencies>
<!-- Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Spring beans包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Spring 容器包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- junit 单元测试依耐 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
确定好所有依赖都导进来之后,就可以继续编写代码了
2.2 传统代码编写
我们设想一个场景,就是用户去买水果,它们分别需要对应的是 买水果的人(用户),卖水果的人(业务层),水果(持久化层)
我们先写一个水果类的接口(面向接口编程嘛)
/**
* Fruit.java
*/
public interface Fruit {
/**
* 获取水果的方法
*/
public void get();
}
接着编写水果的实现类,苹果、橘子、香蕉
/**
* Apple.java
*/
public class Apple implements Fruit{
public void get() {
System.out.println("苹果");
}
}
/**
* Orange.java
*/
public class Orange implements Fruit{
public void get() {
System.out.println("橙子");
}
}
/**
* Banana.java
*/
public class Banana implements Fruit{
public void get() {
System.out.println("香蕉");
}
}
然后再编写一个业务类,来实现具体的获取水果的业务
/**
* UserService.java
*/
public class UserService {
private Fruit fruit = new Apple();
public void getFruit(){
fruit.get();
}
}
用户类
/**
* User.java
*/
public class User {
public static void main(String[] args) {
UserService userService = new UserService();
userService.getFruit();
}
}
以上的情况就是我们传统的方式,可以看到业务层中对于Fruit的实现类产生了严重的耦合性,如果现在用户想获取一个Orange,则我们也需要直接修改业务中的代码,这不符合开闭原则。而且如果涉及的业务比较多的话,直接更改代码也会带来其他的风险与成本,所以我们需要把业务中的具体对象控制,交给用户来定义。我们可以修改一下业务类
public class UserService {
private Fruit fruit;
//通过set方法来“注入”具体的水果类
public void setFruit(Fruit fruit){
this.fruit = fruit;
}
public void getFruit(){
fruit.get();
}
}
具体的水果类,在用户调用的时候,由用户来控制实现
public class User {
public static void main(String[] args) {
UserService userService = new UserService();
//注入具体的水果实现类
userService.setFruit(new Orange());
userService.getFruit();
}
}
这样一来,我们的业务类就无需再改动了,用户需要获取什么水果,由它来自己定义,用户来掌控具体实现的主动权,而我们在业务中只需要提供这些选择给予用户即可。前后的改动主要体现在对于业务层来说,之后的代码无需改动,因为我们已经把主动权交给了用户,用户想要什么,它就“注入”什么。
其实我们上面所讲的,实际上就是IOC的核心思想,也就是所谓的控制反转。
2.3 SpringIOC代码编写
现在我们来体验一下通过Spring IOC实际的流程和实现效果
首先先在resource目录下创建一个applicationContext.xml文件,用于配置Spring容器
<?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 id="apple" class="top.xiateman.service.Apple"></bean>
<bean id="orange" class="top.xiateman.service.Orange"></bean>
<bean id="banana" class="top.xiateman.service.Banana"></bean>
<bean id="userService" class="top.xiateman.service.UserService">
//这里相当于为setFruit()方法中,注入一个banana的对象,ref表示引用容器中id为banana的bean
<property name="fruit" ref="banana"></property>
</bean>
</beans>
然后我们再通过直接中IOC容器中来获取到我们所需要的对象实例
public class User {
public static void main(String[] args) {
//Spring容器加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取我们所需要的bean(对象实例)
UserService userService = context.getBean("userService",UserService.class);
userService.getFruit();
}
}
通过以上我们可以了解到,现在我们已经是将主要的控制权交给了Spring IOC容器,我们先在配置文件中(注册)配置好我们所编写好的对象,用户则只需要直接从Spring 容器中获取所需的对象实例即可。如果用户想更改获取的实例对象,只需在配置文件中修改对应的配置,而无需再去修改代码。这样就大大减少了代码之间的耦合性。可以只通过修改配置文件的方式,来获取到不同的具体实现。
2.4 Spring IOC的好处
通过上面的例子我们可以体会到,在没有不通过Spring的时候,我们对象之间的耦合性比较大,对象之间产生了强依赖,一旦需求有所变动的话,则会牵涉到很多代码,这无疑会大大增加我们的工作量,每一次都需要去更改代码。而使用了SpringIOC之后,我们则将所有的对象交由Spring来管理控制,我们对象之间的依赖需要的具体实现则只需要在配置文件中配置即可,从而无需去更改代码了。
3. 总结
Spring IOC的本质就是将控制权从程序代码中剥离开来,业务的具体实现不再是直接从代码中来实现,而是通过SpringIOC这个第三方的容器,来帮我们管理和创建我们业务中所需要的具体对象实例,这样就大大减低代码中,对象之间依赖的耦合度。
参考文章:
https://blog.csdn.net/qq_37084904/article/details/108633797
https://www.zhihu.com/question/23277575/answer/1073420019
文章内容由个人理解所编写,存在不足之处,仅供参考。
多读多看多写。。。