1. Spring 特点
Spring 次要有如下特点:
- 轻量级:Spring 是非侵入式,其中的对象不依赖 Spring 的特定类;
- 管制反转(IoC):通过 IoC,促成了低耦合,一个对象依赖的其余对象通过被动的形式传递进来,而不必该对象被动创立或查找;
- 面向切面(AOP):反对面向切面编程,将利用业务逻辑层和零碎服务层离开;
- 容器:蕴含并治理利用对象的配置以及生命周期,此时 Spring 就相当于一个容器;
- 框架汇合:能将简略的组件进行配置,组合成为更为简单的利用;在 Spring 中,利用对象被申明式地组合在一个 XML 文件中;此外,Spring 也提供了事务管理、长久化框架集成等根底性能,将应用逻辑的开发留给开发者;
2. Spring 外围组件
Spring 是一个分层架构,次要由如下 7 大模块所形成。Spring 模块位于外围容器,定义了创立、配置和治理 Bean 的形式。
- Spring Core:提供 Spring 框架基本功能,次要组件是 BeanFactory,是工厂模式的实现,通过 IOC 机制将应用程序的配置和依赖性标准与理论的利用程序代码离开。
- Spring Context:一个配置文件,给 Spring 框架提供上下文信息,上下文包含 JNDI、EJB、电子邮件、国际化、校验和调度等企业服务。
- Spring AOP:通过配置管理个性,Spring AOP 间接将 AOP(面向切面)性能集成到 Spring 框架。从而咱们可能非常不便的应用 Spring 框架来治理任何反对 AOP 的对象。模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过应用该组件,能够不依赖其余组件九江申明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 形象层提供了有意义的异样层次结构,能够用来治理异样解决和不同数据库供应商抛出的错误信息。异样层次结构简化了错误处理,而且极大升高了须要编写的异样代码数量。Spring DAO 面向 JDBC 的异样听从通用的 DAO 异样层次结构。
- Spring ORM:Spring 框架中插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包含 JDO、Hibernate 和 iBatis SQL Map,这些都听从 Spring 的通用事务和 DAO 异样层次结构;
- Spring Web:Web 上下文模块建设在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文,所以 Spring 框架反对与 Jakarta Structs 的集成。同时该模块还简化了解决多局部申请以及申请参数绑定到域对象的工作。
- Spring MVC:MVC 是一个全功能的构建 Web 利用的 MVC 实现,能够通过策略接口对 MVC 框架实现高度可配置。而且 MVC 还包容了 JSP、Velocity、Tiles 等视图技术。
3. Spring 罕用注解
注解 | 阐明 |
---|---|
@Controller |
1. 用于标注管制层组件 2. 用于标记一个类,示意它是一个 SpringMVC Controller 对象 3. 散发处理器将扫描应用了该注解的类的办法,同时检测办法是否应用 @RequestMapping 4. 可能将 Request 申请 header 局部的值绑定到办法的参数上 |
@RestController |
相当于 @Component 与 @ResponseBody 的组合 |
@Component |
泛指组件,当组件不好归类时进行注解 |
@Repository |
用于注解 DAO 层,在 DaoImpl 类中注解 |
@Service |
用于注解业务层组件 |
@ResponseBody |
1. 异步申请 2. 用于将 Controller 的办法返回的对象,通过适当的 HttpMessageConverter 转换为指定格局后,写入到 Response 对象的 body 数据区3. 返回的数据并非 html 的页面,而是其余某种格局的数据(json、xml)时应用 |
@RequestMapping |
用于解决申请地址映射的注解,用于类或办法,用于类时,示意类中所有响应申请的办法都以该地址作为父门路 |
@Autowired |
对类成员变量、办法以及构造函数进行标注,从而实现主动拆卸,通过 @Autowired 的应用来打消 get、set 办法 |
@PathVariable |
用于将申请 URL 中的模板变量映射到性能解决办法的参数上,即取出 URL 模板中的变量作为参数 |
@RequestParam |
用于在 Spring MVC 后盾管制层获取参数,相似 request.getParameter("name") |
@RequestHeader |
将 Request 申请 header 局部的值绑定到办法的参数上 |
@ModelAttribute |
在该 Controller 所有办法在调用前,先执行该注解,可用于注解和办法参数中 |
@SessionAttributes |
将值放到 session 作用域,写在 Class 下面 |
@Valid |
实体数据校验,联合 Hibernate Validator 一起应用 |
@CookieValue |
获取 cookie 中的值 |
4. IoC 原理
4.1 定义
Spring 通过一个配置文件来形容 Bean
之间的相互依赖关系,利用 Java 的反射性能来实例化 Bean
并建设 Bean
之间的依赖关系。Spring 的 IoC 容器在实现这些底层工作的根底上,还提供 Bean
实例缓存、生命周期治理、Bean
实例代理、事件公布、资源装载等高级服务;
总结而言:IOC 负责创建对象、治理对象(通过依赖注入)、整合对象、配置对象以及治理对象的生命周期;
4.2 Spring 容器高层视图
- Spring 启动时先读取
Bean
配置信息,并在 Spring 容器中生成一份对应的Bean
配置注册表; - 依据上一步中生成的
Bean
配置注册表来实例化Bean
,并拆卸好Bean
之间的依赖关系; - 将实例化后的
Bean
装载到 Spring 容器中的Bean
缓存池中,供下层的应用程序应用;
4.3 Spring Bean 的作用域及生命周期
4.3.1 作用域
Spring 中,用来组成应用程序的主体以及由 Spring IoC 容器所治理的对象叫做 Bean。简而言之,Bean 就是由 IoC 容器来进行初始化、拆卸和治理的对象。
Bean 的作用域次要有如下几种:
- Singleton(单例)
作用域为 Singleton
,该模式在多线程下不平安 ,表明 IoC 容器中只会存在一个共享 Bean 实例,而且所有对 Bean 的申请,次要 id
和该 Bean 定义相匹配,那么就会返回 Bean 的同一实例。Singleton
是单例模型,即在从创立容器的同时就会主动创立一个 Bean 的对象,无论是否应用,而且 每次获取到的对象都是同一对象。
- Prototype(原型):每次创立时应用
作用域为 Prototype
,表明一个 Bean 定义对应多个实例,该作用域中的 Bean 会导致在 每次对该 Bean 申请时均创立一个新的 Bean 实例。Prototype
是一个原型类型,在咱们创立容器时并未实例化,而是当咱们获取 Bean 时才去创立一个对象,而且每次获取到的对象都不一样。
- Request:一次 request 一个实例
作用域为 Request
,表明在一次 HTTP
申请中,容器返回该 Bean 的同一个实例,即每个 HTTP
申请均有各自的 Bean 实例,根据某个 Bean 定义创立而成,只在基于 Web 的 Spring ApplicationContext 情景下无效。当一次 HTTP
申请解决完结时,该作用域中的 Bean 实例均被销毁。
- Session
作用域为 Session
,表明 在一个 HTTP Session
中,容器返回该 Bean 的同一个实例,对不同的 Session
申请则创立新的实例,该 Bean
实例仅在以后 Session
内无效,只在基于 Web 的 Spring ApplicationContext 情景下无效。当一个 HTTP Session
被废除时,在该作用域内的 Bean 也将生效。
作用域类别 | 阐明 |
---|---|
Singleton |
Spring IoC 容器中仅存在一个 Bean 实例,以单例形式存在,是 Spring 中的默认值 |
Prototype |
每次从容器中调用 Bean 时,均返回一个新的实例,即每次调用 getBean() 办法,相当于 new 一个新的对象 |
Request |
每次 HTTP 申请均创立一个新的 Bean,仅实用于 WebApplicationContext 环境 |
Session |
每次 HTTP Session 共享一个 Bean,不同 Session 应用不同的 Bean,仅实用于 WebApplicationContext 环境 |
4.3.2 生命周期
- Spring 对 Bean 进行实例化;
- Spring 将值和 Bean 的援用注入到 Bean 对应属性中;
- 若 Bean 实现了 BeanNameAware 接口,则 Spring 将 Bean 的 ID 传递给 setBeanName() 办法;
- 若 Bean 实现了 BeanFactoryAware 接口,Spring 将调用
setBeanFactory()
办法,将 Bean 所在利用援用传入进来; - 若 Bean 实现了 ApplicationContextAware 接口,Spring 将调用
setApplicationContext()
办法,将 Bean 所在利用的援用传入进来; - 若 Bean 实现了 BeanPostProcessor 接口,Spring 将调用
post-ProcessBeforeInitalization()
办法; - 若 Bean 实现了
InitializingBean
接口,Spring 将调用他们的after-PropertiesSet()
办法,相似地,如果 Bean 应用init-method
申明了初始化办法,则该办法也会被调用; - 若 Bean 实现了 BeanPostProcessor 接口,Spring 将调用他们的
post-ProcessAfterInitialization()
办法; - 此时,Bean 曾经准备就绪,咱们就能够被应用程序应用,他们将始终驻留在利用上下文中,直到该利用被销毁;
- 若 Bean 实现了 DisposableBean 接口,Spring 将调用它的
destory()
接口办法;同样,若 Bean 应用destroy-method
申明了销毁办法,该办法也将被调用;
4.4 Spring 依赖注入的四种形式
- 结构器注入
// 带参,不便用结构器进行注入
public CatDaoImpl(String name){this.name = name;}
<bean id="CatDaoImpl" class="com.cunyu.CatDaoImpl">
<constructor-arg value="name"></constructor-arg>
</bean>
- setter 办法注入
public class Id {
private int id;
public int getId() {return id;}
public void setId(int id) {this.id = id;}
}
<bean id="id" class="com.cunyu.Id">
<property name="id" value="1801333"></property>
</bean>
- 动态工厂注入
所谓动态工厂就是通过调用动态工厂的办法来获取本人所需对象,而且为了不便 Spring 治理,咱们不能通过“类. 静态方法()”来获取对象,而应该通过 Spring 注入的模式;
// 动态工厂
public class DaoFactory {public static final FactoryDao getStaticFactoryDaoImpl(){return new StaticFacotryDaoImpl();
}
}
public class SpringAction {
// 须要注入的对象
private FactoryDao staticFactoryDao;
// 注入对象的 set 办法
public void setStaticFactoryDao(FactoryDao staticFactoryDao) {this.staticFactoryDao = staticFactoryDao;}
}
<bean name="springAction" class="com.cunyu.SpringAction" >
<!-- 利用动态工厂的办法注入对象 -->
<property name="staticFactoryDao" ref="staticFactoryDao"></property>
</bean>
<!-- 从工厂类获取静态方法 -->
<bean name="staticFactoryDao" class="com.cunyu.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
- 实例工厂
实例工厂示意获取对象实例的办法不是动态的,所以须要先 new
工厂类,而后再调用一般的实例办法;
// 实例工厂
public class DaoFactory {public FactoryDao getFactoryDaoImpl(){return new FactoryDaoImpl();
}
}
public class SpringAction {
// 注入对象
private FactoryDao factoryDao;
public void setFactoryDao(FactoryDao factoryDao) {this.factoryDao = factoryDao;}
}
<bean name="springAction" class="com.cunyu.SpringAction">
<!-- 应用实例工厂的办法注入对象, 对应上面的配置文件 -->
<property name="factoryDao" ref="factoryDao"></property>
</bean>
<!-- 此处获取对象的形式是从工厂类中获取实例办法 -->
<bean name="daoFactory" class="com.cunyu.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
4.5 Spring 主动拆卸形式
要实现主动拆卸,次要从如下两个角度来进行实现:
- 组件扫描(Component Scanning):Spring 会主动发现利用上下文中所创立的 Bean;
- 主动拆卸(Autowiring):Spring 主动满足 Bean 之间的依赖;
Spring 拆卸包含 手动转配和主动拆卸 , 手动拆卸是通过 XML
拆卸、构造方法、setter
办法等形式;
而主动拆卸有如下几种,使得 Spring 容器通过主动拆卸形式来进行依赖注入;
拆卸形式 | 阐明 |
---|---|
no |
默认不进行主动拆卸,通过显式设置 ref 属性来进行拆卸 |
byName |
通过参数名主动拆卸,Spring 容器在配置文件中发现 Bean 的 autowire 属性被设置为 byName 后试图匹配、装载和该 Bean 的属性具备雷同名字的 Bean |
byType |
通过参数类型主动拆卸,Spring 容器在配置文件中发现 Bean 的 autowire 属性被设置为 byType 后试图匹配、装载和该 Bean 的属性具备雷同了类型的 Bean ,若发现多个 Bean 符合条件,则抛出谬误 |
constructor |
相似于 byType ,但须要提供给结构器参数,若无固定的带参的结构器参数类型,则抛出异样 |
autodetect |
首先尝试应用 constructor 来主动拆卸,若无奈工作,则应用 byType 形式 |
4.6 IoC 的优缺点
- 长处:组件之间的解耦,进步程序可维护性、灵活性;
- 毛病:创建对象步骤简单,有肯定学习老本;利用反射创建对象,效率会升高;
5. AOP 原理
5.1 定义
即剖开封装的对象外部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为 Aspect
,即切面 。所谓切面即 与业务无关,但被业务模块所专用的逻辑,便于缩小零碎的反复代码,升高模块间的耦合度,利于后续的可操作性和可维护性。
通过应用横切,AOP 将软件切分为:外围关注点和横切关注点 。业务解决的次要流程是外围关注点,与横切关注点关系不大。 横切关注点的特点是常常产生在外围关注点的多处,且各处根本类似 。AOP 的作用就在于 拆散零碎中的各种关注点,将外围关注点和横切关注点分来到。
5.2 外围概念
5.3 AOP 的两种代理形式
Spring 提供了两种形式来生成代理对象:JDK Proxy 和 CGlib,默认的策略是如果指标类是接口,则应用 JDK 动静代理技术,否则应用 CGlib 来生成代理;
- JDK 动静接口代理
次要波及 Proxy
和 InvocationHandler
,InvocationHandler
是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用指标类的代码,动静地将横切逻辑与业务逻辑编制在一起。而 Proxy
则利用 InvocationHandler
动态创建一个合乎某一接口的实例,生成指标类的代理对象;
- CGlib 动静代理
全称 Code Generation Library
,是一个高性能高质量的代码生成类库,能在运行期间扩大 Java 类与实现 Java 接口。 CGlib 封装了 ASM,能在运行期间动静生成新的类。
- JDK 动静代理和 CGlib 动静代理的区别
JDK 动静代理只能为接口创立代理实例,而对于没有通过接口定义业务办法的类,则须要通过 CGlib 创立动静代理;
5.4 切面的告诉类型
- 前置告诉(Before):指标办法在被调用前调用告诉;
- 后置告诉(After):指标办法实现后调用告诉;
- 返回告诉(After-returning):指标办法胜利执行之后调用告诉;
- 异样告诉(After-throwing):指标办法抛出异样后调用告诉;
- 盘绕告诉(Around):在被告诉的办法调用之前和调用之后执行自定义的行为;
6. Spring MVC
6.1 什么是 MVC 框架?
MVC,全称 Model View Controller,是模型(model)- 视图(view)- 控制器(controller)的缩写,是一种软件设计榜样。用一种业务逻辑、数据、界面显示拆散的办法组织代码,将业务逻辑汇集到一个部件中,而后在改良和个性化定制界面及用户交互的同时,不必重写业务逻辑;
采纳 MVC 设计模式次要有如下益处:
- 通过分层设计,实现了业务零碎各组件之间的构造,有利于业务零碎的可扩展性和可维护性;
- 有利于零碎的并行开发,晋升开发效率;
6.2 SpringMVC
6.2.1 定义
Spring MVC 是 Spring 框架的一个模块,一个基于 MVC 的框架;
6.2.2 组件
DispatcherServlet
:外围组件,前端控制器,也叫地方控制器,由它来调度相干组件,用于接管申请、响应后果,相当于转发器,有了DispatcherServlet
就缩小了其余组件之间的耦合度;HandlerMapping
:处理器映射器,依据 URL 门路映射到不同的Handler
;HandlerAdapter
:处理器适配器,依照HandlerAdapter
的规定来执行Handler
;Handler
:处理器,由咱们本人依据业务进行开发;ViewResolver
:视图解析器,将逻辑视图解析成具体的视图;View
:一个接口,反对不同的视图类型;
6.2.3 MVC 工作流程
- 浏览器发送申请,前端控制区
DispatcherServlet
拦挡该申请; DispatcherServlet
拦挡到申请后,对申请 URL 进行解析,失去申请资源标识符 URI,依据 URI 调用HandlerMapping
后获取对应Handler
;DispatcherServlet
拿到Handler
之后,找到HandlerAdapter
,通过它来拜访Handler
,并执行处理器;- 执行
Handler
的逻辑,返回一个ModelAndView
对象给DispatcherServlet
; - 而后
DispatcherServlet
申请ViewResolver
解析视图,依据逻辑视图名解析真正的View
; - 而后
ViewResolver
将解析后的View
返回给DispatcherServlet
,而后对View
进行渲染; - 而后由
DispatcherServlet
响应视图给浏览器;
6.2.4 SpringMVC 的长处
- 具备 Spring 的个性;
- 反对多种视图;
- 配置不便,非侵入;
- 分层更加清晰,利于团队开发的代码保护,以及可读性好;
6.3 注解
6.3.1 注解原理
注解实质上是一个集成了 Annotation
的非凡接口,其具体实现类是 Java 运行时生成的动静代理类。通过反射获取注解时,返回的是 Java 运行时生成的动静代理对象。通过代理对象调用自定义注解的办法,将最终调用 AnnotationInvocationHandler
的 invoke
办法,而后该办法从 memberValues
的 Map
中索引出对应的值;
6.3.2 罕用注解
注解 | 阐明 |
---|---|
@RequestMapping |
用于解决申请 url 映射的注解,能用在类或办法上,用于类时示意所有响应申请的办法均以该地址作为父门路 |
@RequestBody |
实现接管 HTTP 申请的 json 数据,将 json 转换为 Java 对象 |
@ResponseBody |
实现将 controller 办法返回对象转化为 Json 对象响应给客户 |