参考文档
关于Spring
什么是Spring框架?
Spring
是一款开源的轻量级java开发框架,旨在提高开发人员的开发效率以及系统的可维护性。Spring
框架一般指的是Spring Framework
,使用这些模块的集合可以方便协助我们进行开发。
Spring的组件代码是轻量级的,但它的配置却是重量级的。
题外话:Spring(春天)
,可见其目标和使命就是为java程序员带来春天!
- 左上角是负责持久层的部分,是Spring对数据持久化,事务管理,支持的功能框架。例如:SpringDataJpa。
- 右上角是负责表现层的部分, 是Spring对表现出层数据的处理部分的支持。例如:SpringMVC。
- 中间的两部分就是大家俗称的Spring框架。
- 最底层的部分负责测试,是Spring对于项目的测试,提供了完整的一个测试环境支持。
Spring
提供的核心功能主要是loC
和AOP
。
Ioc(Inverse of Control)
控制反转/反转控制
是一种设计思想,而不是一个具体的技术实现。
loC的思想就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
loC并非Spring特有,在其他语言中也有应用。
例如:现有类A依赖于类B
- 传统的开发方式:往往是在类A中动手通过new关键字来new一个B的对象出来
- 使用Ioc思想的开发方式:不通过new关键字来创建对象,而是通过Ioc容器(Spring框架)来帮助我们实例化对象。需要哪个对象,直接从Ioc容器里面过去接口。
坏处:丧失了一个权力(创建、管理对象的权力)
好处:不用再考虑对象的创建,管理等一系列的事情
为什么叫控制反转?
- 控制:指的是对象创建(实例化、管理)的权力
- 反转:控制权交给外部环境(Spring框架、loC容器)
将对象之间的相互依赖关系交给loC容器来管理,并由loC容器完成对象的注入。可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。loC容器就如同一个工厂,当需要创建对象时,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
Ioc解决了什么问题
Ioc的思想就是两方之间不互相依赖,由第三方容器来管理相关资源,好处是什么呢?
- 对象之间的耦合度或者说依赖程度降低
- 资源变得容易管理;比如说用Spring容器提供的话很容易就可以实现一个单例。
DI(Dependency Injection)
依赖注入
首先理解依赖,程序运行的需要可以称之为依赖。由于Spring框架
通过反射技术实例化了对象,并将对象的实例存入在容器进行管理。那么如果一个类中的属性为某个其余的类,属性无需手动赋值,通过Spring的配置文件,或者Spring提供的注解,通过Spring框架可以实现直接注入属性。
AOP(Aspect-Oriented Programming)
AOP是OOP的一种延续。面向切面编程
能够将那些与业务无关,却为业务模块共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
小结
Spring
是分层的Java SE/EE应用
轻量级开源框架,以IoC
和AOP
为内核,提供了展示层Spring MVC
和持久层Spring JDBC
以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,是使用最多的Java EE
企业应用开源框架。使用Spring
能对bean
对象的实例管理更加方便,代码编写更加优雅,降低代码的耦合性,提升代码的扩展性。
Spring的优势
- Spring简化项目开发:Spring灵活全面的扩展功能,使我们开发项目如鱼得水。通过Spring提供的Ioc容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再未单例模式类,属性文件解析等这些很多底层的需求编写代码,可以更专注于上层的应用
- Spring的面向切面编程:Spring框架的AOP面向切面编程,极大地提高了程序的扩展性,支持开发人员实现对程序的自定义增强。同时可以方便地使用Spring提供的事务管理
- 面向接口编程: 面向接口编程 降低代码的耦合性,同时也提高了代码的扩展性
- 测试方便: 对于测试的支持 有很多的组件实现
- 方便集成第三方框架Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Struts,Hibernate,Hessian,Quartz等)的直接支持。
关于Spring bean
什么是bean?
bean代指的就是那些被loC容器所管理的对象。
我们需要告诉loC容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是XML文件、注解或者java配置类。
1 | <!-- Constructor-arg with 'value' attribute --> |
org.springframework.beans
和org.springframework.context
是Ioc实现的基础,未来如有兴趣,可以自行研究。
bean的作用域
Spring
中bean
的作用域通常有下面几种:
singleton
:唯一bean
实例,Spring
中的bean
默认都是单例的,对单例设计模式的应用。prototype
:每次请求都会创建一个新的bean
实例request
: 每一次HTTP
请求都会产生一个新的bean
,该bean
仅在当前HTTP request
内有效。session
:每一次来自新session
的HTTP
请求都会产生一个新的bean
,该bean
仅在当前HTTP session
内有效。golobal-session
:全局session
作用域,仅仅在基于portlet
的wed应用中才有意义,Spring5
已经没有了。Portlet
是能够生成语义代码(例如:HTML)片段的小型Java Web
插件。它们基于portlet
容器,可以像servlet
一样处理 HTTP 请求。但是,与servlet
不同,每个portlet
都有不同的会话。
如何配置bean的作用域
xml方式:
1 | <bean id="..." class="..." scope="singleton"></bean> |
注解方式:
1 |
|
单例bean的线程安全问题
单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。
解决方法:
- 在bean中尽量避免定义可变的成员变量。
- 在类中定义一个
ThreadLocal
成员变量,将需要的可变的成员变量保存在ThreadLocal
中。
@Component 和 @Bean的区别
@Component
注解作用于类,而@Bean
注解用于方法@Component
通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中 (我们可以使用@Component
注解定义要扫描的路径从中找出标识了需要装配的类自动装配到Spring的bean容器中)。@Bean
注解通常是我们在标有该注解的方法中定义产生这个bean,@Bean
告诉了Spring这是某个类的实例,当我需要用它的时候还给我。@bean
注解比@Component
注解的自定义性更强,而且很多地方我们只能通过@Bean
注解来注册bean。比如当我们引用第三方库的类需要装配到Spring容器,则只能通过@Bean
来实现。
关于Spring MVC
MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。要想真正理解Spring MVC,得想从Model 1 和 Model 2这两个没有Spring MVC的时代讲起。
Model 1 时代
在Model1 模式下,整个Web应用几乎全部用JSP页面组成,只用少量的JavaBean来处理数据库连接、访问等操作。这个模式下JSP即是控制层(Controller)又是表现层(View), 这很明显会存在很多问题,比如控制逻辑和表现逻辑混杂在一起,导致代码重用率极低;再比如前端和后端相互依赖,难以进行测试维护并且开发效率极低。
Model 2 时代
Java Bean(Model) + JSP(View) + Servlet (Controller),这种开发模式就是早期的JavaWeb MVC 开发模式。
- Model: 系统涉及的数据,也就是dao和bean。
- View:展示模型中的数据,只是用来展示。
- Controller:处理用户请求都发送给Java Bean,返回数据给JSP并展示给用户。
Model2模式下还存在很多问题,Model2的抽象和封装程度还远远不够,使用Model2进行开发时不可避免地会重复造轮子,这就大大降低了程序的可维护性和复用性。
Spring MVC 时代
Spring MVC 是当前最优秀的MVC框架。可以帮助我们进行更简洁的Web层的开发,并且它天生与Spring框架集成。Spring MVC 下我们一般把后端项目分为Service层(处理业务)、Dao层(数据库操作)、Entity层(实体层)、 Controller层(控制层,返回数据给前台页面)。
Spring MVC 工作原理
流程说明:
- 客户端(浏览器)发送请求,直接请求到
DispatcherServlet
。 DispatcherServlet
根据请求信息调用HandlerMapping
, 解析请求对应的Handler
。- 解析到对应的
Handler
(Controller
)后,开始由HandlerAdapter
适配器处理。 HandlerAdapter
会根据Handler
来调用真正的处理器开处理请求, 并处理相应的业务逻辑。- 处理器处理完业务后,会返回一个
ModelAndView
对象,Model
是返回的数据对象,View
是个逻辑上的View
。 ViewResolver
会根据逻辑View
查找实际的view
。DispatcherServlet
把返回的Model
传给View
(视图渲染)。- 把
View
返回给请求者(浏览器)。