导图社区 java学习重点之 spring家族
java学习重点之spring家族,主要概括了Spring Framework,Spring Boot和Spring Cloud。从Spring Framework整体架构开始,层层深入扩展到Spring MVC,JSP,JSTL等。侧重Spring Boot注解,Spring Cloud基础。
编辑于2019-10-08 02:43:18Spring家族
Spring Framework
Core Container
bean是Spring框架在运行时管理的对象
是任何Spring应用程序的基本构建块
beans
BeanFactory
Beans
生命周期
配置
基于XML的配置
基于注解的配置
annotation自动注册bean
<!-- 使用Annotation自动注册Bean,解决事物失效问题:在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解。 --><context:component-scan base-package="com.qb.keco"><!-- base-package 如果多个,用“,”分隔 --><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan> <!-- 使用Annotation自动注册Bean,只扫描@Controller --><context:component-scan base-package="com.qb.keco" use-default-filters="false"><!-- base-package 如果多个,用“,”分隔 --><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan>
添加注解
@Component
可以用于注册所有bean
@Repository
主要用于注册dao层的bean
@Service
主要用于注册服务层的bean
@Controller
主要用于注册控制层的bean
自动装配Bean
no
默认方式,手动装配方式,需要通过ref设定bean的依赖关系
byName
根据bean的名字进行装配,当一个bean的名称和其他bean的属性一致,则自动装配
byType
根据bean的类型进行装配
当一个bean的属性类型与其他bean的属性的数据类型一致,则自动装配
constructor
根据构造器进行装配
如果bean的构造器有与其他bean类型相同的属性,则进行自动装配
autodetect
如果有默认构造器,则以constructor方式进行装配,否则以byType方式进行装配
调用/注入
@Autowired
在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config />。在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;如果查询的结果不止一个,那么@Autowired会根据名称来查找;如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。
按照类去匹配
@Qualifier
指定按照名称去装配 bean
基于Java类配置
@Configuration
@Bean
initMethod
destroyMethod
@Lazy
指定延迟初始化
@Scope
指定作用域
实例化
构造器实例化
静态工厂方式实例化
实例工厂方式实例化
作用域
singleton
单例模式、默认状态,只生成一个实例,每次从spring容器内获取的都是同一个bean,唯一性
适用无会话状态的Bean
Dao
Service
prototype
每次从spring容器内获取,都会产生一个新的bean,再注入
request
request 在web服务的一次请求中,此bean被注入都是同一个bean实例,如果是另一个request请求,被注入时会生成另一个bean实例
session
globalSession
application
websocket
core
IOC
注入方式
setter 方法注入
这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口)
构造器注入
注解注入
@Autowired
自动装配,用于替代基于XML配置的自动装配基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器、字段、方法注入
构造器注入
通过将@Autowired注解放在构造器上来完成构造器注入,默认构造器参数通过类型自动装配
字段注入
通过将@Autowired注解放在构造器上来完成字段注入
方法参数注入
通过将@Autowired注解放在方法上来完成方法参数注入
@Required
应用于bean属性的setter方法使用该注解的属性必须在配置文件中设置,否则容器会抛出一个BeanlnitializationException异常
@Qualifier
在按照类型注入的基础上,再按照bean的id注入。他在类成员注入数据时,不能独立使用,但是在给方法的形参注入数据时,可以独立使用。属性value用于指定bean的id
@Resource
使用属性name指定bean的id
@Configuration
@Configuration 表示这个类可以使用spring IOC容器作为bean定义的来源
@Bean
@Bean 返回一个对象,该对象被注册为spring应用程序上下文中的bean
静态工厂方法注入
实例工厂方法注入
DI
context
ApplicationContext
(1)BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:①继承MessageSource,因此支持国际化。②统一的资源文件访问方式。③提供在监听器中注册bean的事件。④同时加载多个配置文件。⑤载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。(2)①BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。②ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。 ③相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。(3)BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。(4)BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
SpEl
Spring表达式语言(简称SpEL)是一种与JSP2的EL功能类似的表达式语言,它可以在运行时查询和操作对象图。与JSP2的EL相比,SpEL功能更加强大,它甚至支持方法调用和基本字符串模板函数。SpEL可以独立于Spring容器使用——只是当成简单的表达式语言来使用;也可以在Annotation或XML配置中使用SpEL,这样可以充分利用SpEL简化Spring的Bean配置。
AOP
术语
通知(Advice)
就是你想要的功能,也就是上面说的 安全,事物,日志等。你给先定义好把,然后在想用的地方用一下。
前置通知
应用:权限控制(权限不足抛出异常)、记录方法调用信息日志<!-- 配置前置通知:告诉spring在目标方法执行之前增强 --><aop:before method="before" pointcut-ref="pointcut1"/>
后置通知
特点:在目标方法运行后返回值后再增强代码逻辑 应用:于业务相关的, 如银行在存取款结束后的发送短信消息 <!-- 配置后置通知 --> <!-- returning="result" 目标方法返回值为result--> <aop:after-returning method="afterReturning" pointcut-ref="pointcut2" returning="result"/>
环绕通知
特点 :目标方法执行前后,都进行增强(控制目标方法执行) 应用 :日志、缓存、权限、性能监控、事务管理增强代码的方法要求: - 接收的参数:ProceedingJoinPoint(可执行的连接点) - 返回值: Object返回值 - 抛出Throwable异常
异常抛出通知
作用:目标代码出现异常,通知执行。记录异常日志、通知管理员(短信、邮件) 应用场景:处理异常(一般不可预知),记录日志
引介通知
在目标类中添加新的方法和属性应用于修改老版本程序
最终通知
作用:不管目标方法是否发生异常,最终通知都会执行(类似于finally代码功能) 应用场景:释放资源 (关闭文件、 关闭数据库连接、 网络连接、 释放内存对象 )
连接点(JoinPoint)
这个更好解释了,就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。
切入点(Pointcut)
上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
切面(Aspect)
切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。
引入(introduction)
允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗
目标(target)
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。
代理(proxy)
代理模式,将通知应用到目标对象后,被动态创建的对象。
织入(weaving)
把切面应用到目标对象来创建新的代理对象的过程。
动态代理
1、JDK动态代理2、CGLIB动态代理3、何时使用JDK还是CGLIB?4、如何强制使用CGLIB实现AOP?5、JDK动态代理和CGLIB字节码生成的区别?6、CGlib比JDK快?7、Spring如何选择用JDK还是CGLIB?利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1)如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP。3)如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。1)添加CGLIB库(aspectjrt-xxx.jar、aspectjweaver-xxx.jar、cglib-nodep-xxx.jar)2)在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类。2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法, 并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final, 对于final类或方法,是无法继承的。1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。2)在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理,总之,每一次jdk版本升级,jdk代理效率都得到提升,而CGLIB代理消息确有点跟不上步伐。1)当Bean实现接口时,Spring就会用JDK的动态代理。2)当Bean没有实现接口时,Spring使用CGlib是实现。3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。
JDK动态代理
java.lang.reflect.Proxy
invoke
CGLIB动态代理
net.sf.cglib.proxy
intercept
实现方式
ProxyFactoryBean
AspectJ 框架
基于XML
<!-- 使用aop操作 start--><!-- 1、创建两个类的对象 --><bean id="mainTest" class="com.zwp.aop.MainTest"></bean><bean id="secondText" class="com.zwp.aop.SecondText"></bean><!-- 2、配置aop操作 --><aop:config><!-- 2.1配置切点 --><aop:pointcut expression="execution(* com.zwp.aop.MainTest.*(..))" id="pointcut1"/><!-- 2.2配置切面:即把增强用到方法上面的过程 --><aop:aspect ref="secondText"><aop:before method="before1" pointcut-ref="pointcut1"/><aop:after method="after1" pointcut-ref="pointcut1"/><aop:around method="round1" pointcut-ref="pointcut1"/></aop:aspect></aop:config><!-- 使用aop操作 end-->
基于注解
@Aspect
定义切面
@Pointcut
定义切入点表达式
@Before
@After
@AfterReturning
@AfterThrowing
@Around
@DeclareParents
Data Access/Integration
JDBC
ORM
JPA
通过JDK 5.0注解或XML描述对象-关系表的映射关系
并将运行期的实体对象持久化到数据库中
Mybatis
#{}和${}的区别
#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号
$将传入的数据直接显示生成在sql中
分页实现
逻辑分页
自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索
并非是一次性查询出所有数据
RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在你执行 next()的时候,去查询更多的数据。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。
物理分页
利用原生的sql关键字limit
利用interceptor来拼接sql
使用Interceptor拦截器
PageHelper工具
执行SQL语句之前动态的将SQL语句拼接了分页的语句,从而实现了从数据库中分页获取的过程
支持延迟加载
延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息
设置 lazyLoadingEnabled=true 即可
一级缓存
基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致
默认开启
可能会出现脏数据
二级缓存
基于 PerpetualCache 的 HashMap 本地缓存不同在于其存储作用域为 Mapper 级别
如果多个SQLSession之间需要共享缓存,则需要使用到二级缓存
Ehcache
Executor执行器
在Mybatis配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数
SimpleExecutor
每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement
ReuseExecutor
执行update或select,以sql作为key查找Statement对象
存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内
BatchExecutor
执行update,都添加到批处理中(addBatch()),等待统一执行(executeBatch())
与JDBC批处理相同
自定义插件
Executor 拦截执行器的方法(log记录)
StatementHandler 拦截Sql语法构建的处理
ParameterHandler 拦截参数的处理
ResultSetHandler 拦截结果集的处理
Hibernate
OXM
Spring 的 O/X 映射接口是 Spring 框架的强大特性。借助它,您不仅可以将 XML 文档转换为 Java 对象,还可以将 Java 对象转换为 XML 文档。它 利用 Spring 的一个关键优势:依赖项注入。通过结合使用依赖项注入和 Spring 的 O/X Mapper,您可以轻松开发一个解决方案,该方案可以使用任一 O/X 实现,比如 Castor、XBeans、JiBX、JAXB 和 XStream。由于各个特定实现是 Spring 强大的 Inversion of Control 容器的一部分,开发人员可以在多个特定 O/X 实现之间轻松切换而无需修改代码。Spring 的 O/X Mapper 还向开发人员提供一个统一的异常层次结构,这意味着不管您使用哪个第三方实现,抛出的运行时异常都是相同的。再强调一次,这将有利于在多个 O/X 供应商之间切换。
JMS
Java消息服务(Java Message Service ,JMS)是一个Java标准,定义了使用消息代理的通用API。在此之前每个消息代理都有私有的API,这导致不同的代理之间的消息代码很难通用,但是借用JMS所有遵从规范的实现都使用通用的接口,这就类似于JDBC为数据库操作提供了通用的接口一样。
SpringAMQP
RabbitMQ
Transaction
事务
实现方式
基于注解
@Transactional()
value/transactionManager
指定事务管理器,默认为""
propagation
事务的传播行为,默认值为 Propagation.REQUIRED
Propagation.REQUIRED/NESTED
如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。
Propagation.SUPPORTS
如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
Propagation.MANDATORY
如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
Propagation.REQUIRES_NEW
重新创建一个新的事务,如果当前存在事务,暂停当前的事务。
Propagation.NOT_SUPPORTED
以非事务的方式运行,如果当前存在事务,暂停当前的事务。
Propagation.NEVER
以非事务的方式运行,如果当前存在事务,则抛出异常。
isolation
事务的隔离级别,默认值为 Isolation.DEFAULT
Isolation.DEFAULT
使用底层数据库默认的隔离级别。
Isolation.READ_UNCOMMITTED
Isolation.READ_COMMITTED
Isolation.REPEATABLE_READ
Isolation.SERIALIZABLE
timeout
事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly
指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollbackFor
用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
noRollbackFor
抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。
基于XML
编程式事务管理
对基于 POJO 的应用来说是唯一选择
POJO(Plain Ordinary Java Object)意思是普通的java对象 ,没有继承任何类、实现任何接口、也没有包含特殊的注解,。 JavaBeans是一类POJO,具有无参构造函数、私有成员变量通过公共的访问器和设置器进行读写、可以序列化。 使用POJO的好处就是和使用的框架解耦,Spring框架就是采用基于POJO开发,Spring开发中不需要自己的业务类继承或实现任何框架的类或接口,通过依赖注入的方式来实现组件之间装配。 但是我们在实际编码中还是可以生成继承或者实现某些接口的实例(Bean),所以在Spring中Bean应该是具备以下特点: 1.无参构造函数便于注入 2.getter和setter函数便于属性的设置 3.可以是实现某个接口的类,但是这些类不得依赖Spring框架,否则Spring框架代码改变,业务代码也有可能需要跟着改变。
需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法
基于 TransactionProxyFactoryBean的声明式事务管理
此方式,可手动开启、提交、回滚事务
基于Aspectj AOP配置事务
Web
Web层由spring-web,spring-webmvc,spring-websocket,和spring-webmvc-portlet模块构成.Spring-web模块提供面向web整合特性,比如多部件的文件上传功能和使用Servlet监听器初始化的IoC容器,和一个面向web的应用上下文.她也包括一个Http客户端和spring远程操作支持的面向web的部分.Spring-webmvc模块(也被称作Web-Servlet模块)包括为web应用而实现的Spring’s model-view-controller(MVC) 和REST Web Services .springmvc框架在model代码域和web表单以及其他所有spring框架的特性提供了一个清晰的界限.Spring-webmvc-portlet模块(也被称作Web-Portlet模块)提供一个被用在Portlet环境和镜像的spring-webmvc模块功能的MVC实现.
WebSocket
SockJS
Servlet
JSP
HttpServlet
DispatcherServlet
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。 DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:1、文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;2、通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);3、通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);4、通过ViewResolver解析逻辑视图名到具体视图实现;5、本地化解析;6、渲染具体的视图等;7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
Web
Spring MVC
组件
前端控制器(DispatcherServlet)
处理器映射器(HandlerMapping)
处理器适配器(HandlerAdapter)
拦截器(HandlerInterceptor)
语言环境处理器(LocaleResolver)
主题解析器(ThemeResolver)
视图解析器(ViewResolver)
文件上传处理器(MultipartResolver)
异常处理器(HandlerExceptionResolver)
数据转换(DataBinder)
消息转换器(HttpMessageConverter)
请求转视图翻译器(RequestToViewNameTranslator)
页面跳转参数管理器(FlashMapManager)
处理程序执行链(HandlerExecutionChain)
运行流程
web.xml 文件配置 DispatcherServlet
http请求到DispatcherServlet前端控制器
HandlerMapping 处理器映射器
根据 HttpServletRequest 查找 HandlerExecutionChain
根据 HandlerExecutionChain 获取 HandlerAdapter、执行 handler
Handler处理器
业务处理
实现开发中又称为controller即后端控制器
执行完成返回 ModelAndView
ViewReslover视图解析
根据逻辑视图名创建一个View对象
DispatcherServlet
进行视图渲染
View视图(jsp)
将模型数据填充进来(将model数据填充到request域)显示给用户
@RequestMapping
用于建立请求URL和处理请求方法之间的对应关系
Portlet
Spring框架通过Web MVC模块提供了自己的MVC实现,Spring框架的Portlet MVC模块则是基于Web MVC模块的Portlet实现。Portlet与Servlet的最大区别是请求的处理分为action阶段和render阶段。在一个请求中,action阶段只执行一次,但是render阶段可能由于用户的浏览器操作而被执行多次。
Aspects
AspectJ框架
Instrumentation
这个类为JVM上运行时的程序提供测量手段。很多工具通过Instrumenation 修改方法字节码 实现收集数据目的。这些通过Instrumentaion搜集数据的工具不会改变程序的状态和行为。这些良好的工具包括 monitoring agents , ,profilers, coverage analyzers, 和 event loggers。
Message
Spring-messaging模块是spring framework 4 包含的一个从spring集成项目(如Meaasge,MessageChannel,MessageHandler,和其他基于消息应用的基础服务)而来的关键抽象.这个模块也包括一系列的用来映射消息到方法的注解,类似于基于编程模型的springMVC注解.
Test
Spring-test模块支持在JUnit和TestNG下的sping组件的单元测试和集成测试.她提供了Spring ApplicationContexts 加载和缓存这些上下文.你可以独立的测试你的代码通过她提供的模拟对象.
Spring Boot
优点
独立运行
Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,现在不再需要打成war包部署到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。
简化配置
Spring Boot 中有两种上下文,一种是 bootstrap,,另外一种是 application,,bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。
核心配置文件
bootstrap 配置文件
对比 application 配置文件,bootstrap 配置文件具有以下几个特性: boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载 boostrap 里面的属性不能被覆盖 bootstrap 配置文件有以下几个应用场景: 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息; 一些固定的不能被覆盖的属性 一些加密/解密的场景。
application 配置文件
格式
.properties
app.user.name = javastack
.yml
app: user: name: javastack .yml 格式不支持 @PropertySource 注解导入配置。
自动配置
@EnableAutoConfiguration
应用监控
版本控制
RESTful
可以通过一套统一的接口为 Web,iOS和Android提供服务。
@PathVariable
获取url数据 import com.mr.model.User;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; /** * */@RestControllerpublic class RESTFulController { /** * * RESULTFul风格Demo1 */ @RequestMapping("/boot/user/{id}") public Object user(@PathVariable("id") Integer id){ User user=new User(); user.setUserId(id); user.setUserName("ZS"); user.setUserPass("123"); return user; } /** * * RESULTFul风格Demo2 */ @RequestMapping("/boot/user/{id}/{name}") public Object user(@PathVariable("id") Integer id,@PathVariable("name") String name){ User user=new User(); user.setUserId(id); user.setUserName(name); user.setUserPass("456"); return user; } /** * * RESULTFul风格Demo3 */ @RequestMapping("boot/user/{id}/{name}/{pass}") public Object user(@PathVariable("id") Integer id,@PathVariable("name") String name,@PathVariable("pass") String pass){ User user=new User(); user.setUserId(id); user.setUserName(name); user.setUserPass(pass); return user; }}
核心注解
@SpringBootApplication
@SpringBootConfiguration
@Configuration
@EnableAutoConfiguration
@ComponentScan
单元测试
单元测试又称为模块测试,是针对程序模块(软件设计中的至小单元)来进行正确性检验的测试工作。单个分支单个结果判断
Junit
常用注解
@Test
@Ignore
@Before
@After
@BeforeClass
修饰的方法会在所有方法被调用前执行,且该方法时静态的,所以当测试类被加载后就接着运行它,而且在内存中他只会存在一份实例,他比较适合加载配置文件(针对所有测试,只执行一次 )
@AfterClass
所修饰的方法通常用来对资源管理,如关闭数据库连接(针对所有测试,只执行一次 )
常用断言
@Test(timeout = 5000 )
@Test(expected = XXXXException. class)
期望出现异常,如果出现该异常则成功,否则测试失败
Assert.assertEquals("提示语", 5, result);
"提示语" 为错误时你个人想要输出的错误信息; 5 是指你期望的值;result 是指你调用程序后程序输出给你的结果
assertTrue(String message, boolean condition)
assertFalse(String message, boolean condition)
assertEquals(String message, XXX expected,XXX actual)
assertArrayEquals(String message, XXX[] expecteds,XXX [] actuals)
assertNotNull(String message, Object object)
assertNull(String message, Object object)
assertSame(String message, Object expected, Object actual)
assertNotSame(String message, Object unexpected,Object actual)
assertThat(String reason, T actual, Matcher matcher)
SSM框架上使用
创建一个测试基类
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath:config/spring/spring-dao.xml", "classpath:config/spring/spring-service.xml", "classpath:config/spring/spring-web.xml"})@Transactional@Rollbackpublic class BaseTest{ }
@RunWith(SpringRunner.class)/@RunWith(SpringJUnit4ClassRunner.class)
让测试在Spring容器环境下执行
ContextConfiguration 加载所需的配置文件(可以以字符数组的形式加载)
@Transactional 开启事务:已经配置了注解式事务
@Rollback 设置测试后回滚,默认属性为true,即回滚
创建DaoTest测试类继承测试基类
创建ServiceTest测试类继承测试基类
创建ControllerTest测试类继承测试基类
热部署
Spring Loaded
在maven项目下,pox.xml文件中的build中添加spring-loaded依赖
spring-boot-devtools
在maven项目下,pox.xml文件中的dependencies中添加spring-boot-devtools依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional></dependency>
在配置文件application.yml中添加
debug: truespring: devtools: restart: enabled: true #设置开启热部署 freemarker: cache: false #页面不加载缓存,修改即时生效
JRebel插件
Spring Cloud
微服务之间的通信
HTTP通信
消息通信
事件驱动的通信
消息中间件
Java消息服务(Java Message Service,JMS)
一个Java平台中关于面向消息中间件(MOM)的API
用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信
常用协议
AMQP协议
MQTT协议
STOMP协议
XMPP协议
组成
Broker
消息服务器,作为server提供消息核心服务
Producer
消息生产者,业务的发起方,负责生产消息传输给broker
Consumer
消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
Topic
主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息
由MQ服务器分发到不同的订阅者,实现消息的广播
Queue
队列,PTP模式下,特定生产者向特定queue发送消息
消费者订阅特定的queue完成指定消息的接收
Message
消息体,根据不同通信协议定义的固定格式进行编码的数据包
模式分类
PTP点对点
使用queue作为通信载体
Pub/Sub发布订阅(广播)
使用topic作为通信载体
消息生产者(发布)将消息发布到topic,同时有多个消息消费者(订阅)消费该消息
从1到N个订阅者都能得到一个消息的拷贝
常见消息中间件
RabbitMQ
使用Erlang编写的一个开源的消息队列,支持很多协议
多用于进行企业级的ESB整合
ActiveMQ
Apache下使用Java完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现
支持常用的多种语言客户端
Kafka
Apache下使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统
RocketMQ
阿里系下开源的一款分布式、队列模型的消息中间件
多用于订单交易系统
Redis
使用C语言开发的一个Key-Value的NoSQL数据库
可以当做一个轻量级的队列服务来使用
ZeroMQ
号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发
在金融界的应用中经常使用,偏重于实时数据通信场景
优势
系统解耦
交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低
提高系统响应时间
为大数据处理架构提供服务
应用场景
异步通信
解耦
冗余
扩展性
过载保护
可恢复
顺序保证
缓冲
数据流处理
RPC
首先需要有处理网络连接通讯的模块,负责连接建立、管理和消息的传输。其次需要有编解码的模块,因为网络通讯都是传输的字节码,需要将我们使用的对象序列化和反序列化。剩下的就是客户端和服务器端的部分,服务器端暴露要开放的服务接口,客户调用服务接口的一个代理实现,这个代理实现负责收集数据、编码并传输给服务器然后等待结果返回。
Dubbo
dubbo 作为 rpc 框架,实现的效果就是调用远程的方法就像在本地调用一样。如何做到呢?就是本地有对远程方法的描述,包括方法名、参数、返回值,在 dubbo 中是远程和本地使用同样的接口;然后呢,要有对网络通信的封装,要对调用方来说通信细节是完全不可见的,网络通信要做的就是将调用方法的属性通过一定的协议(简单来说就是消息格式)传递到服务端;服务端按照协议解析出调用的信息;执行相应的方法;在将方法的返回值通过协议传递给客户端;客户端再解析;在调用方式上又可以分为同步调用和异步调用;
CAP原理
c强一直性,A可用性,P分区容错
任何分布式系统只能保证满足其二,而分区容错是必须保证的
断路器
服务熔断
熔断机制是应对雪崩效应的一种微服务链路保护机制
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务降级
进而熔断该节点微服务的调用,快速返回“错误”的响应信息
服务降级
当某个服务熔断之后,服务器将不再被调用
客户端可以自己准备一个本地的fallback回调,返回一个缺省值
@HystrixCommand
SpringCloud框架里熔断机制通过Hystrix实现
5秒内调用20次,如果失败,就会启动熔断机制
核心组件
Eureka
各个服务启动时,Eureka Client都会将服务注册到Eureka Server
Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
Ribbon
服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台
Feign
基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
Hystrix
通过Hystrix的线程池发起请求
不同的服务对应不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
Zuul
如果前端、移动端要调用后端系统,统一从Zuul网关进入,再转发请求给对应的服务
案例