一篇带你进入Spring的世界
前言
我的启蒙书籍是大一下学期从咸鱼买的《JavaWeb从入门到精通》(第二版),在这本书里我学了到了很多新技术。逛知乎偶然看到大家都在用Spring,就购买了《Spring实战》和《Spring Boot实战派》,开启了我的Spring学习之路。
我们上学期开了一门网络编程课,讲了servlet jsp,不过那个老师就喜欢扯东扯西的讲一大堆无关紧要的东西,好家伙重点全跳过,我就索性就没听过了。所以jsp学的不好的同学无所谓,不过建议Servlet学习透彻些,毕竟现在的Java WEB都还是围绕着Servlet的,这些框架也都是封装的Servlet。
Spring简介
Spring是一个轻量级的容器框架,它的出现就是为了简化企业级的应用开发。
Spring的特点:
- 一个轻量级的,非入侵式的框架
- 控制反转(IOC)
- 面向切面编程(AOP)
侵入式和非侵入式
我个人的理解,侵入和非侵入是框架相对于代码而言的概念。
- 侵入式:你的代码需要依赖框架,去除了框架你的代码就没法运行了,往往需要继承特定的类,或者实现特定的接口;
- 非侵入式:非入侵式就是框架的代码不会入侵到我的代码中去,只是通过注入依赖就可以自由组合和使用相应的功能。当我们去掉框架后,仍可以通过修改代码来使程序运行。
Spring是如何实现非侵入式的设计目标的:
- 应用反射机制,通过动态调用的方式来提供各方面的功能,建立核心组间BeanFactory;
- 配合使用Spring框架中的BeanWrapper和BeanFactory组件类最终达到对象的实例创建和属性注入
BeanWrapper:BeanWrapper接口是Spring底层常用的一个接口,是Spring IOC的核心接口之一,当Bean实例被创建出来后,就会被BeanWrapper包装起来,BeanWrapper可以设置和访问被包装对象的属性 值,可以简单理解为BeanWrapper是对Bean的包装。
BeanFactory:BeanFactory接口也是Spring底层常用的一个接口,是Spring IOC的核心接口之一,顾名思义BeanFactory就是一个生成和管理Bean的工厂。它的职责包括:实例化、定位、配置应用程序中的对象以及建立这些对象间的依赖关系。他有一个派生类ApplicationContext,它拥有BeanFactory的所有功能,并且更加面向框架,还有很多额外的功能。 它与BeanFactory最大的区别就是ApplicationContext在启动时就会实例化Bean,而BeanFactory只有在从容器中拿Bean时才会去实例化。
Spring的模块
上图是Spring5的各个模块,大致可以分为6大模块,接下来就让我们逐个分析一下每个模块的作用:
核心容器(Core Container)
我们可以看到它包含四个部件,分别是Beans、Core、Context和SpEL,让我们根据具体的jar来看看它们具体的功能吧:
- spring-core:控制反转(IOC)和依赖注入(DI)的基础 是Spring的核心工具类,包含很多工具包、基本注解,定义了资源的访问方式(底层Resource资源描述及基本资源加载器实现),很多模块都需要引入该模块。
- spring-beans:生产和管理Bean 是IOC/DI的核心,包含BeanFactory、BeanWrapper等。作用:Bean的定义、Bean的创建、Bean的解析。
- spring-context:speing上下文 是架构于spring-core之上,包含ApplicationContext。
- spring-expression:SpEL表达式 是统一表达式语言(EL)的扩展模块,专为Spring而生,更便利的于Spring Ioc进行交互。
AOP(面向切面编程),包括spring-aop、spring-aspects、spring-instrument
AOP意为面向切面编程,是继OOP后另一具有巨大深远影响意义的编程思想,包括ProxyFactory代理工厂等组件。
- spring-aop:提供AOP的实现,必须要导入的包
- spring-aspects:集成AspectJ框架
- spring-instrument:spring对服务器的代理接口。spring-instrument-tomcat:spring对tomcat连接池的集成。
Web应用模块
- spring-web:提供基础的Web应用功能,和整合Spring框架
- spring-websocket:提供对WebSocket协议的相关支持
- spring-webmvc:提供SpringMVC框架的相关类,与Spring框架无缝整合,并结合spring-web为基于Servlet容器的Web应用提供MVC支持
- spring-webflux:WebFlux是Spring5开始引入的基于Reactive响应式编程的Web框架,不同于spring-webmvc基于Servlet容器,WebFlux不需要Servlet API,完全异步且无阻塞,
- 一般基于Netty等异步网络框架,这也是Spring5最大的一个新特性
数据访问集成
- spring-jdbc:提供对JDCB相关数据库操作的支持
- spring-tx:提供Spring JDBC事务的相关支持
- spring-orm:提供对ORM(对象关系映射)的支持
- spring-oxm:提供对对象XML实体映射的支持,将java对象映射成XML数据,或者将XML数据映射成java对象
Messaging
- spring-messaging:提供对一些基础的报文传送应用的至此,即为Spring提供各种消息队列支持,如ActiveMQ、Kafka等。
Test
- 提供Spring测试框架组件的支持,如junit单元测试框架
IOC和AOP
Spring框架提供了IOC和AOP两大核心功能,即控制反转(Inversion of Control)和面向切面编程(Aspect Oriented Programming)。
接下来就让我们来好好认识一下这两个功能:
IOC:
控制反转(Inversion of Control,IOC),是面向对象编程中的一种设计原则,可以用来降低代码的耦合度,实现对象之间的“解耦”。
让我们来看看IOC的原理:借助“第三方”的IOC容器来实现对象之间的解耦
如上图所示,IOC容器就像一个工厂一样可以生产和分配对象,让我们拿个具体的例子来看一下:现在有A、B两个类,A的功能依赖于B。
在传统设计模式中:当A的功能依赖于B时,我们一般会将B的实例对象传递给A,简单些的程序还好说,要是很复杂的程序,那么我们就很容易出错。
在使用控制反转后:我们只需在A类中声明需要B类,IOC容器就会自动将B类实例注入到A类中,实现解耦。这里不得不讲一下注入依赖(Dependency,DI)了,注入依赖是控制反转的一种实现方式,Spring框架也正是利用注入依赖来实现控制反转的,所以在Spring框架中控制反转有时也被称为控制依赖,通过注入依赖 Bean的创建、引用、销毁等控制权都交给框架处理,当我们要使用某个类时,容器会自动查询该类的实例,若容器中没有这个类的实例,则自动创建并保存在IOC容器中,再交给使用者;如果已存在,则直接获取该类的实例交给使用者。对于使用者而言,我们只需声明需要依赖的Bean即可被自动注入。
西瓜籽:“你一会说IOC是个设计模式,一会又说IOC容器,这到底是个啥?”
大西瓜:“呀呀呀!没讲明白呀,那我就来总结一下到底什么是IOC容器,以及它在Spring中的具体实现。”
IOC容器
IOC容器是Spring用来实现IOC的载体。我们知道在Spring中经常使用到映射,比如Model的查找,具体到数据结构就是Map,而我们的Spring IOC容器,实际上也是一个存放着各种对象的Map。
在spring-beans包中有一个BeanFactory接口,上面提到过它可以创建和管理Bean,其实就是为IOC容器提供了最基本的功能,而它也仅仅只是一个接口,它的派生类DefaultListableBeanFactory,才是一个真正可使用的beanfactory实现,在其内部还定义了BeanDefinition的Map。
初始化bean的信息会存在beanDefinitionMap中,而DefaultSingletonBeanRegistry类里的singletonObjects哈希表则保存了单例对象。
AOP
AOP即面向切面编程,在Spring中,AOP是以动态代理技术为基础,设计出了一系列的AOP横切实现,比如前置通知、返回通知、异常通知等,同时,以Pointcut接口来匹配切入点,可以使用现有的切入点来设计横切面,也可以拓展相关的方法自定义横切面。使用AOP的思想,我们可以将非核心的业务功能定义为切面。分别独立开发核心功能和非核心功能,然后再将切面和核心业务功能组合在一起。
AOP的相关概念
- Target(目标对象):要被切面通知的对象,也就是业务逻辑类。
- Pointcut(切入点):这里的Pointcut通常指类和方法名。
- Joinpoint(连接点):用来定义程序中,哪里可以通过AOP添加额外的逻辑。也就是说,连接点就是被拦截到的程序执行点。说白了只要被拦截抛出,都是连接点。
- Advice(通知):在某一特定Joinpoint处运行的代码被称为advice,也就是拦截到连接带你后要执行的代码(功能)。包括"before"、"around"、"after"等不同类型的通知。
- Aspect(切面):切面=切入点 通知。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。
- Weaving(织入):把切面加入对象,并创建出代理对象的过程。
- 环绕通知:与前置通知和后置通知有所不同,前置通知和后置通知一旦设定必须执行,而环绕通知有着很高的灵活性,你可以自主决定是否调用该代码(功能)。
总结:面向切面编程就是指对某一层进行纵切,在这一层的切面上添加各种公用逻辑,最终的目标是去除冗余的代码,达到逻辑复用的目的。
continue