Spring In Action 4 学习笔记(一)Spring概览
Spring的核心概念就是DI和AOP,是Spring实现所有复杂华丽框架的基石。
相对于EJB等重型框架,Spring更加轻量化,可以强化普通的POJO对象。
1、简化JAVA开发
为了尽可能简化Java的开发,Spring遵循如下4个策略:
- Lightweight and minimally invasive development with POJOs
使用POJO类进行轻量化低侵入式的开发
- Loose coupling through DI and interface orientation
通过依赖注入和接口降低耦合
- Declarative programming through aspects and common conventions
通过切面和约定进行声明式编程
- Eliminating boilerplate code with aspects and templates
通过切面和模板消除冗余代码
关键字:POJO类、低侵入、DI、AOP、Template
1.1、强化POJO类
使用Spring你完全不用在你的代码中掺杂Spring的API,也几乎不需要继承Spring的接口或父类。当然,可能是需要加如一些注解。像如下这段代码:
package com.habuma.spring;public class HelloWorldBean {public StringsayHello() {return "HelloWorld";}}
就是一个普通的JAVA类,没有侵入Spring特性的代码,完全可应用在非Spring应用中。但Spring可以把它添加到自己的上下文中,即可作为Spring的Bean来使用,从而使其获取强大的力量。
1.2、依赖注入
DI可以使你的代码更简洁、易读、便于测试。
任何应用中的类之间都有依赖关系,它们必需相互协作以完成业务逻辑,导致程序耦合性强、难以测试。如下例子:
package com.springinaction.knights;public classDamselRescuingKnight implements Knight {private RescueDamselQuest quest;public DamselRescuingKnight() {//该依赖产生强耦合this.quest = new RescueDamselQuest();}public void embarkOnQuest() {quest.embark();}}
DamselRescuingKnight对RescueDamselQuest的引用直接写在构造方法中,两者之间耦合性太强,DamselRescuingKnight想要更换一个Quest的实现的话都要写一个新的类来实现。
而且如果想要对DamselRescuingKnight 进行单元测试也不容易。
DI在对象创建时通过第三方绑定其依赖的对象,从而降低耦合。改造后的代码如下:
package com.springinaction.knights;public class BraveKnight implements Knight {//引用接口private Quest quest;//依赖作为参数传入public BraveKnight(Quest quest) {this.quest = quest;}public void embarkOnQuest() {quest.embark();}}
对依赖对象的引用改为接口,依赖对象通过参数传入,称为构造方法注入。
对BraveKnight类的测试:
package com.springinaction.knights;import static org.mockito.Mockito.*;import org.junit.Test;public class BraveKnightTest {@Testpublic void knightShouldEmbarkOnQuest() {Quest mockQuest = mock(Quest.class);BraveKnight knight = new BraveKnight(mockQuest);knight.embarkOnQuest();verify(mockQuest,times(1)).embark();}}
Knight对Quest的依赖可以使用参数来绑定,Spring中通过XML、Java Config、Autowired来实现绑定。
1.3、引入切面
应用中通常会承担一些本不属于自己职责的工作,如日志记录、事务处理、安全管理等,而这些功能往往需要贯穿整个应用的任何角落。这从两个方面提高了应用复杂度:
- 这些代码遍布与应用中,当需要修改其实现方式时,对所有代码都有影响,即便做成共通方法,方法的调用方式也可能有变化,也不得不全面测试。
- 各模块的职责不再单一,比如一个通讯录模块不应去关心安全性和事务问题。
看一个例子便于理解:
package com.springinaction.knights;import java.io.PrintStream;public class Minstrel {private PrintStream stream;public Minstrel(PrintStream stream) {this.stream= stream;}public void singBeforeQuest() {stream.println("Fala la, the knight is so brave!");}public void singAfterQuest() {stream.println("Teehee hee, the brave knight did embark on a quest!");}}package com.springinaction.knights;public class BraveKnight implements Knight {private Quest quest;private Minstrel minstrel;public BraveKnight(Quest quest, Minstrel minstrel) {this.quest= quest;this.minstrel= minstrel;}public void embarkOnQuest() throws QuestException {
<span style="background-color: rgb(255, 255, 51);"> if(minstrel != null) {minstrel.singBeforeQuest();}</span>quest.embark();
<span style="background-color: rgb(255, 255, 51);"> if(minstrel != null) {minstrel.singAfterQuest();}</span>}}
BraveKnight的职责就是embarkOnQuest,不应该由BraveKnight来执行Minstrel的方法,而且BraveKnight也不应对Minstrel产生依赖。在业务类及此类功能模块增多时复杂度也会指数上升:
AOP的思想可以完美的解决这些问题,业务功能不必再考虑自己职责以外的工作,日志、事务、安全等被独立为单独的模块,通过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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.2.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="knight" class="com.springinaction.knights.BraveKnight"><constructor-arg ref="quest" /></bean><bean id="quest" class="com.springinaction.knights.SlayDragonQuest"><constructor-arg value="#{T(System).out}" /></bean><bean id="minstrel" class="com.springinaction.knights.Minstrel"><constructor-arg value="#{T(System).out}" /></bean><aop:config>
<span style="background-color: rgb(255, 255, 51);"> <aop:aspect ref="minstrel"><!--Define pointcut with AspectJ's pointcut EL --><aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))"/><aop:before pointcut-ref="embark" method="singBeforeQuest"/><aop:after pointcut-ref="embark" method="singAfterQuest"/></aop:aspect></span></aop:config></beans>
通过该配置文件,定义切点,声明切面切入位置,切入代码由上下文来控制和调用,从而降低了模块间的耦合及应用复杂度,BraveKnight和Minstrel类中没有任何迹象体现AOP,它们仍然是POJO的,而BraveKnight中也没有对Minstrel的引用:
1.4、使用模板
虽然Java作为高级语言已经帮我们处理了很多底层操作:垃圾回收、内存申请等,但有时我们还是不得不写很多冗余代码,比如访问DB:
public Employee getEmployeeById(long id) {Connection conn = null;PreparedStatement stmt = null;ResultSet rs = null;try {conn = dataSource.getConnection();stmt = conn.prepareStatement("select id, firstname, lastname, salary from employee where id=?");stmt.setLong(1, id);rs = stmt.executeQuery();Employee employee = null;if (rs.next()) {employee = new Employee();employee.setId(rs.getLong("id"));employee.setFirstName(rs.getString("firstname"));employee.setLastName(rs.getString("lastname"));employee.setSalary(rs.getBigDecimal("salary"));}return employee;} catch (SQLException e) {…...} finally {if(rs != null) {try {rs.close();} catch(SQLException e) {}}if(stmt != null) {try {stmt.close();} catch(SQLException e) {}}if(conn != null) {try {conn.close();} catch(SQLException e) {}}}return null;}
一个简单的员工信息查询,主要代码被淹没在跟业务无关的代码中,而且这些冗余代码对不同的db访问操作都是相同的,catch到的异常在这里也不能做不了什么特殊处理。
Spring提供了模板来解决此类问题,如处理DB访问的JdbcTemplate,可以将DB访问相关的冗余代码移到模板中,使程序员和代码可以专注于业务逻辑的实现。
2、Bean容器
Spring中的Bean对象由container来创建、绑定,并管理它们的生命周期。Container属于Spring框架的核心模块,
Container有两种类型的实现:org.springframework.beans.factory.BeanFactory和org.springframework.context.ApplicationContext。Bean factories提供最基本的容器支持;Application contexts在bean factories的基础之上为应用提供了其它一些服务。一般都是用application contexts。
2.1、应用ApplicationContext
Spring实现了几种ApplicationContext接口,常见实现的如下:
- AnnotationConfigApplicationContext—用于加载基于Java及注解的配置
- AnnotationConfigWebApplicationContext—用于Spring Web应用,加载基于Java及注解的配置
- ClassPathXmlApplicationContext—用于从classpath资源文件加载基于XML的配置
- FileSystemXmlApplicationContext—用于从文件系统加载基于XML的配置文件
- XmlWebApplicationContext—用于从web应用中加载基于XML的配置文件
应用示例:
ApplicationContext context = new FileSystemXmlApplicationContext("c:/knight.xml");//knight.xml在$classpath目录下ApplicationContext context = new ClassPathXmlApplicationContext("knight.xml");ApplicationContext context = new AnnotationConfigApplicationContext(com.springinaction.knights.config.KnightConfig.class);
得到applicationcontext实例之后,就可以通过其getBean()方法获取定义的bean对象。
2.2、Spring Bean生命周期
系统开发中Spring Bean的生命周期很少用到,如果需要搭建自己的框架,在创建bean的过程中进行一些定制化的操作的话,会很有帮助。
- 实例化bean对象;
- 给bean的属性注入值或对其它bean的依赖;
- 如果bean实现了BeanNameAware接口,调用setBeanName()方法传入bean的ID;
- 如果bean实现了BeanFactoryAware接口,调用setBeanFactory()方法传入bean factory;
- 如果bean实现了ApplicationContextAware接口,调用setApplicationContext()方法传入 application context;
- 如果bean实现了BeanPostProcessor接口,调用postProcessBeforeInitialization()方法;
- 如果bean实现了InitializingBean接口,调用afterPropertiesSet()方法;
- 如果bean自定义了init方法,调用该方法;
- 如果bean实现了BeanPostProcessor接口,调用postProcessAfterInitialization()方法;
- Bean实例投入使用,直到application context被销毁;
容器关闭时:
- 如果bean实现了DisposableBean接口,调用postProcessAfterInitialization()方法;
- 如果bean自定义了detroy方法,调用该方法。
3、Spring领域纵览
在Spring核心框架之上,Spring还扩展到web services、REST、mobile、NoSQL等领域。
3.1、Spring核心模块
Spring4.0包含20个模块,每个模块三个jar文件:二进制包、源码、JavaDoc。项目中可以根据实际需要导入相应的包。这些模块按其功能可分为6类:
3.2、Spring portfolio
Spring提供了丰富的产品包,将Spring编程模型引入到了Java开发的几乎每个层面。
- SPRING WEB FLOW
基于Spring MVC,为创建交互式、流程式Web应用提供支持,如向导、购物车等功能。 http://projects.spring.io/spring-webflow/。
- SPRING WEB SERVICES
Spring核心的web service是基于协议后置模型,服务协议取决于bean的接口。SpringWeb Services提供了协议前置模型,根据服务协议来实现具体的服务。 http://docs.spring.io/spring-ws/site/。
- SPRING SECURITY
基于AOP,为Spring应用提供安全机制。http://projects.spring.io/spring-security/。
- SPRING INTEGRATION
提供了几种常见集成模型的实现。http://projects.spring.io/spring-integration/。
- SPRING BATCH
提供对数据批处理的支持。http://projects.spring.io/spring-batch/。
- SPRING DATA
Spring Data简化了跟各种数据库(关系型、对象型、Graph DB)的协作。
- SPRING SOCIAL
对于网络社交类的应用提供了支持,不过相对于社交,Spring Social更侧重于连接,可以通过REST APIs等方式跟其它应用建立关联。https://spring.io/guides/gs/accessing-facebook/,https://spring.io/guides/gs/accessing-twitter/。
- SPRING MOBILE
手机、平板正成为更主流的客户端,SpringMobile是对Spring MVC在移动WEB应用领域的扩展。
- SPRING FOR ANDROID
引入Spring框架来简化Android设备的本地应用开发,该项目初期提供了RestTemplate,可以通过REST APIs与Spring Social协作。http://projects.spring.io/spring-android/。
- SPRING BOOT
提供了快速创建Spring应用的途径,Spring Boot应用了自动配置技术,并提供了一些starter项目来减少Spring工程的build文件,不论是用Maven还是Gradle。
Spring In Action 4 学习笔记(一)Spring概览相关推荐
- Spring in Action 4th 学习笔记 之 AOP
前提:本文中的AOP仅限于Spring AOP. 先说说为什么需要AOP 最简单的一个例子就是日志记录,如果想记录一些方法的执行情况,最笨的办法就是修改每一个需要记录的方法.但这,真的很笨... 好的 ...
- Spring In Action 5 学习笔记 chapter1
环境 win7x64 idea 2018.3 maven 3.3.9 spring 4.0.4 很久没摸spring boot了,idea还是2018的,生疏了,抓起来再看看.[我亦无他,惟手熟尔] ...
- 《Spring技术内幕》学习笔记17——Spring HTTP调用器实现远程调用
1.Spring中,HTTPInvoker(HTTP调用器)是通过基于HTTP协议的分布式远程调用解决方案,和java RMI一样,HTTP调用器也需要使用java的对象序列化机制完成客户端和服务器端 ...
- 《Spring技术内幕》学习笔记19——Spring RMI实现远程调用
1.Spring除了使用基于HTTP协议的远程调用方案,还为开发者提供了基于RMI机制的远程调用方法,RMI远程调用网络通信实现是基于TCP/IP协议完成的,而不是通过HTTP协议. 在Spring ...
- Spring Security技术栈学习笔记(八)Spring Security的基本运行原理与个性化登录实现
正如你可能知道的两个应用程序的两个主要区域是"认证"和"授权"(或者访问控制).这两个主要区域是Spring Security的两个目标."认证&qu ...
- [Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP
上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(三):Spring实现JDBC 下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(五):SpringA ...
- Spring Security技术栈学习笔记(十三)Spring Social集成第三方登录验证开发流程介绍
开发第三方登录,我们必须首先要了解OAuth协议(本文所讲述的OAuth协议指的是OAuth2协议),本文首先简单介绍OAuth协议,然后基于Spring Social来阐述开发第三方登录需要做哪些准 ...
- Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习
Spring Cloud学习笔记-网关Spring Cloud Gateway官网教程实操练习 1.Spring Cloud Gateway介绍 2.在Spring Tool Suite4或者IDEA ...
- Spring Security技术栈学习笔记(十四)使用Spring Social集成QQ登录验证方式
上一篇文章<Spring Security技术栈开发企业级认证与授权(十三)Spring Social集成第三方登录验证开发流程介绍>主要是介绍了OAuth2协议的基本内容以及Spring ...
- Java学习笔记-Day64 Spring 框架(二)
Java学习笔记-Day64 Spring 框架(二) 一.控制反转IOC和依赖注入DI 1.控制反转IOC 2.依赖注入DI 3.Spring IOC容器 3.1.简介 3.2.实现容器 3.2.获 ...
最新文章
- Antd-Design List渲染列中Button 点击事件 传递参数
- 信息系统项目管理师-信息系统安全管理核心知识思维脑图
- 查看表扫描次数,并对比索引对表查询的作用
- 线性代数(矩阵、高斯、线性基……)
- C# 篇基础知识10——多线程
- SpringBoot2.x Nacos RocketMQ 事务消息
- html清除require报错,javascript - requirejs加载报错问题?
- Android基础View回顾
- mysql开启binlog日志影响性能吗_mysql binlog日志优化及思路
- L1-012 计算指数
- c++ 2条中线焦点_三角形的中线为何交于一点
- JavaScript的Forms验证-Parsley.js
- 汉字转换成拼音的类(转)
- html倒计时星期日,功能齐全的jQuery倒计时插件
- 抓取中央气象台-台风报文数据
- Python自动化办公【PDF文件自动化】
- 隐藏微信右上角的分享按钮
- 《大江大河2》里这段精彩的博弈:没有对错,只有权衡
- 基因组层次聚类实战小案例
- 存储芯片涨价:助芯片制造商美光科技业绩连超预期