Spring七大模块与强大的IOC
共 7003字,需浏览 15分钟
· 2021-02-15
点击上方 Java学习之道,选择 设为星标
Spring 是什么
Spring是由「Rod Johnson」创建的一个轻量级的控制反转(IOC)
和面向切面编程(AOP)
的开源优秀框架。
有以下几个优点:
❝1.贯彻控制反转(IOC)思想
2.贯彻面向切面编程(AOP)思想
3.贯彻依赖注入(DI)思想
4.支持事务的处理
5.表现出对框架整合的强大能力
❞
使用Spring能够简化软件开发的复杂性,并降低程序的耦合度。具体如何降低会在后面详述。
Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
同时Spring框架也是Spring Boot和Spring Cloud的基础。
Spring的七大组成部分
此部分先对Spring框架做一个简单的介绍,具体实现放到后文实现,以便于读者能更好的感悟Spring的强大。
Spring的七大组成模块如下:
2.1 核心容器(Spring Core)
Spring的核心包,即为Spring框架最基础的部分,支撑了整个Spring。core包提供了控制反转和依赖注入的特征实现。核心的思想是设计模式--工厂模式
,并借此消除了程序对单例模式的依赖,并且展现出了Spring消除耦合的能力,便是「分离了程序的配置和依赖关系」。
2.2 应用上下文模块(Spring Context)
对应UI和老式框架EJB和邮件的各种支持。执行Spring的IOC容器时所依赖的上下文对象,提供框架式的对象访问方法,也就是Spring启动时加载Spring所需要的数据结构并且填充数据,为运行准备好一个环境。
2.3 JDBC抽象和DAO模块(Spring DAO)
对应DAO层的支持,对多个持久化技术提供了集成支持,包括 Hibernate、 MyBatis、JPA、JDO;提供一个简化JDBC API操作的Spring JDBC框架。Spring面向DAO制定了一个通用的异常体系,屏蔽具体持久化技术的异常,使业务层和具体的持久化技术实现解耦。Spring提供了模板类简化各种持久化技术的使用。
2.4 对象/关系映射集成模块(Spring ORM)
全称为「Object Relational Mapping」,即对象关系映射,对数据库中的各种表映射成对象。开发人员就可以把对数据库的操作转化为对这些对象的操作。方便开发人员以面向对象的思想来实现对数据库的操作。
同时提供对各种框架的支持。
2.5 面向切面编程(Spring AOP)
AOP即为面向切面编程,是OOP面向对象编程的一种扩展补充。SpringAOP通过动态代理来实现AOP。
2.6 Spring的Web模块(Spring Web)
提供了远程调用和远程服务的支持,同时SpringWeb包含了Spring Web MVC。
2.7 Spring的MVC框架(Spring Web MVC)
对WEB和JSP等的各种支持
Spring有的人说是三大核心思想,但是控制反转其实也可以被成为依赖注入,所以说实际上,Spring框架是IOC和AOP思想的优秀产物。
IOC
IOC被成为控制反转,是一种很重要的思想,
下面我们通过一个案例来说明IOC的重要程度。
不使用IOC的思想来编写代码
/* DAO层的接口和实现 */
public interface UserDao {
void getUser();
}
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("dao层默认获取用户数据");
}
}
public class UserDaoMySQLImpl implements UserDao {
@Override
public void getUser() {
System.out.println("MySQL获取用户数据");
}
}
public class UserDaoOracleImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Oracle获取用户数据");
}
}
/* service层的接口和实现 */
public interface UserService {
void getUser();
}
import com.javastudyway.dao.UserDaoImpl;
public class UserServiceImpl implements UserService {
/* 如果是这样的编码,需求改变了之后,每次都要通过修改源码才能更换DAO层的实现 */
private UserDao userDao = new UserDaoImpl();
public void getUser(){
userDao.getUser();
}
}
/* 测试类 */
public class MyTest {
public static void main(String[] args) {
//用户实际调用业务层,dao层不需要接触
UserService userService = new UserServiceImpl();
userService.getUser();
/*输出结果:
* dao层默认获取用户数据
*/
}
}
如果需求改变需要使用其他的数据库来实现DAO层的查询用户数据,则每一次都要去修改ServiceImpl中的
「private UserDao userDao = new UserDaoImpl();」
这种编码方式显然不实际,所以这时候就来引出我们的IOC思想编码方式。
使用IOC的思想来编写
DAO层的代码不需要去改变,仅改动Service就能实现程序适应用户需求的改变。
import com.javastudyway.dao.UserDao;import com.javastudyway.dao.UserDaoImpl;
public class UserServiceImpl implements UserService {
//不在通过new直接创建出Dao对象
private UserDao userDao;
//新增一个set方法,通过set方法来实现接口的切换
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void getUser(){
userDao.getUser();
}
}
有人会想了,不就是多了个setter吗?这很常见啊。
值得注意的是这个setter他成功实现了程序的灵活性,用户需要使用DAO层的哪个接口就通过setter传入哪个接口即可。
在程序的使用中,将接口的选择权移交到用户手中,此即为控制反转。
下面再通过代码来演示:
import com.javastudyway.dao.UserDao;
public class UserServiceImpl implements UserService {
private UserDao userDao;
/* 利用set进行动态实现值的注入 */
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
public class MyTest {
public static void main(String[] args) {
//用户实际调用业务层,dao层不需要接触
UserService userService = new UserServiceImpl();
/*将接口强转成实现类,并且调用setter传入dao层实现 */
((UserServiceImpl)userService).
setUserDao(new UserDaoMySQLImpl());
userService.getUser();
}
}
如上,如果用户需要使用mysql的dao层实现就传入一个MySQL的dao层实现,要调用默认就传入一个默认的dao层实现即可。
如果用户的需求可能会改变我们的代码,选择只通过一个Setter就能让我们不用整个程序去修改代码,程序的维修代价瞬间降低了下来。这就是IOC的强大之处。
控制反转,控制权从程序员手上转移到了用户的手上。这种思想从本质上优化了程序,程序员不再需要手动去管理对象,系统的偶尔度也大大降低了。这也是Spring的底层基石思想。
Spring的简单使用
讲完基本的Spring IOC容器后,我们来用代码体验以下Spring的强大之处。
前文说过,Spring是一个容器,那么容器内部肯定就会存放对象,那么Spring的对象是如何来的呢?下面我们通过案例来演示。
maven依赖的导入
❝maven导入Spring依赖技巧:
直接导入webmvc的依赖即可,因为webmvc又依赖于spring所需要的个大模块的包
仅通过一个依赖就处理好了Spring所需要的依赖
❞
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
元数据
Spring IOC容器负责实例化,配置和组装Bean。容器通过读取配置元数据获取有关要实例化,配置和组装哪些对象的指令。Spring官方文档中给出三种使用元数据的方式:
配置元数据以XML Java注解 -- Spring2.5之后开始引入的配置元数据的技术 Java代码表示 -- Spring3.0开始提供的技术
最传统的配置就是通过 XML
文件来配置元数据。规范的一个XML配置文件的名称为:applicationContext.xml
,但其实这个文件就是一个配置多个bean的xml文件。
以下是Spring官方文档中给出的配置元数据的xml最基本格式:
<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">
<bean id="..." class="...">
bean>
<bean id="..." class="...">
bean>
beans>
我们可以在beans中配置多个bean,通过id来区分不同的bean,并在后面的class属性来指向不同的POJO。容器启动时会以此为我们每一个类创建一个单例的对象。
我们接下来通过POJO类的定义和实例化容器来获取对象来阐述容器和对象的使用。
/* POJO类 */
public class Hello {
//类中仅定义一个字段,str,重写toString并增加getter和setter
private String str;
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
接下来,为这个POJO来定义一个配置元数据。
<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">
<bean id="hello" class="com.javastudyway.pojo.Hello">
<property name="str" value="Spring" />
bean>
beans>
在 bean 这个标签的class属性中导向POJO类的全路径,IOC容器就会去寻找该类并创建一个单例对象,在实例化容器后我们就可以通过 id 的值来获取到这个对象。在 bean 中我们加入一个 property 的单闭合标签来为该对象赋值,name这个属性即类中的字段,value为该字段的值。
❝贴士:在编写application.xml时,IDEA会在上方提示:Application context not configured for this file
直接在IDEA中点击Create new application context...然后让IDEA自动为我们配置该文件的上下文对象即可。
❞
至此,我们的bean和元数据的配置就完成了。接下来我们在测试类中演示「容器的实例化」和「容器对象的获取」
import com.javastudyway.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取Spring的上下文对象,也就是实例化IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//对象现在都在Spring中管理,要使用直接在里面取,getBean()方法,传入的参数即为容器中bean的id
Hello hello1 = (Hello) context.getBean("hello");
Hello hello2 = (Hello) context.getBean("hello");
System.out.println(hello1);
System.out.println(hello1 == hello2);
//~:输出结果为:Hello{str='Spring'}
// true
//将刚刚在applicationContext.xml中配置的value赋值给了相应的name
}
}
从这个例子中,我们可以就可以了解到Spring容器的对象创建方式,流程就是,在程序启动时,Spring容器通过我们配置的元数据,在applicationContext.xml文件中去寻找各个bean,然后把我们配置的各个值注入到相应的字段中,然后返回一个单例对象。
该对象的对象名对应bean中配置的id,对象的类型对应bean中配置的class。
❝实例化容器:
Spring实例化容器通过 -- 接口ApplicationContext来获取,借助ClassPathXmlApplicationContext这个实现类来读取外部资源文件。提供给ApplicationContext构造函数的一个或多个位置路径是资源字符串,可让容器从各种外部资源(例如本地文件系统,Java等)中加载配置元数据CLASSPATH。
❞
这里有细心的人会发现这个POJO与前面讲到IOC的POJO有点类似了,都是仅仅定义一个属性字段但不赋值,然后借助setter去实现注入,Spring容器产生对象也是这种方式。所以说,Spring的基石思想是IOC。
总结
现在开始,我们已经不用再去程序中改动了,得益于IOC,现在要实现不同的操作,我们仅需要在 XML
配置文件中进行修改。Spring的IOC其实也就是 「Spring来搞定对象的创建,管理,装配」。
- | 更多精彩文章 -
公众号后台回复「手册」获取资料
▽加我微信,交个朋友 长按/扫码添加↑↑↑