文章目录
- 利用 Spring Integration 实现分布式锁
- SpringBoot 启动流程
- SA-TOKEN 权限认证框架
- MyBatis Plus 实体类id使用数据库自增
- mybatis 部分用到的设计模式
- mybatis 执行流程
- mybatis 层次结构
- mybatis 流式查询
- 配置 spring mvc 的几种方式的区别
- filter 和 interceptor 的关系
- BeanFactory
- FactoryBean 用于在配置属性复杂的情况下通过编码实现bean配置
- Spring AOP pointcut常用表达式
- Spring Bean 生命周期
- Spring事务
- Spring 的JDBC异常抽象,可以自定义特定异常码下抛出的异常类型
- @Transactional 失效的几种场景
- 解决类内调用 `@Transactional` 事务失效的方法
- JPA Java Persistence API 为 O/R Mapping 提供一种基于 POJO 的持久化模型
- Spring Data 中 xxxTemplate 和 Repository 的区别
- Spring 中使用 redis
- Spring 缓存抽象
- SpringMVC请求处理流程
- StopWatch 可以用来计算请求耗时
- SpringBoot 自动配置实现原理
- Spring 扩展点
- Spring Bean的定制
- SpringBoot 核心
- @PropertySource 可加载指定配置文件,配合@Value 或 @ConfigurationProperties
- Spring IOC学习笔记
- Spring Boot 推荐用Java 配置类,并推荐使用 启动类 作为配置类,如果要使用xml 配置,在配置类的地方使用注解 `@ImportResource(locations = {"xxx.xml"})`
- Spring Boot 可通过实现 ApplicationContextAware 接口获取 ApplicationContext 对象,但不推荐直接使用这个对象获取Bean,应使用自动装配注释
- Spring Boot 自动注入推荐做法
- 20. Spring Bean 作用域
- 27. Spring Bean 生命周期回调
- 28. Spring Bean 属性 depends-on 表示在实例化之前先实例化依赖的 Bean
- 29. Spring @Autowired 可以用在 List、Set、Map属性上。@qualifier名字不一定要不同,注入如List、Set时会将名字相同都注入进来
- 30. ResponseEntity 代表整个http response ,可以自定义头信息、状态码、body体。优先级高于@ResponseBody
- 31. Spring Boot 优雅注入配置文件
- 32. 过滤器和拦截器
- 33. Spring Boot 的几种参数校验方式
- 34. Spring Boot 自定义校验注解
- 35. Spring Boot 定时任务
- Spring Cloud 服务发现与注册抽象
- bootstrap.properties 和 application.properties 有何区别
利用 Spring Integration 实现分布式锁
@Configuration
public class RedisLockConfiguration {
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory){
return new RedisLockRegistry(redisConnectionFactory, "redis-lock");
}
}
SpringBoot 启动流程
如果我们使用的是SpringApplication的静态run方法,那么首先要创建一个SpringApplication对象实例,它会做几件事情:
- 根据classpath里面是否存在某个特征类org.springframework.web.context.ConfigurableWebApplicationContext来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
- 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
- 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
- 推断并设置main方法的定义类。
run方法首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。找出能接收ApplicationStartingEvent 的并调用它们的started()方法。
创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,发布 ApplicationEnvironmentPreparedEvent 事件。
如果SpringApplication的showBanner属性被设置为true,则打印banner。
根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
遍历调用所有SpringApplicationRunListener的contextPrepared()方法,发布ApplicationContextInitializedEvent 事件。
最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
遍历调用所有SpringApplicationRunListener的contextLoaded()方法,发布ApplicationPreparedEvent 事件。
调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
遍历调用所有SpringApplicationRunListener的started()方法,发布ApplicationStartedEvent 事件。
查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
遍历调用所有SpringApplicationRunListener的running()方法,发布ApplicationReadyEvent事件。
SA-TOKEN 权限认证框架
MyBatis Plus 实体类id使用数据库自增
属性上加@TableId(value = "id",type = IdType.AUTO)
mybatis 部分用到的设计模式
- Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
- 工厂模式,例如SqlSessionFactory、MapperProxyFactory;
- 单例模式,例如ErrorContext
- 代理模式,Mybatis实现的核心,比如MapperProxy 用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;
- 模板方法模式,例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;
- 适配器模式,例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;
mybatis 执行流程
session.getMapper(xxxMapper.class);
userMapper.listUserByUserName("xxx");
整个sql执行流程可以分为两大步骤:
一、寻找sql
二、执行sql语句
mybatis 层次结构
mybatis 流式查询
try(Cursor<String> strings = userMapper.testCursor()) {
strings.forEach(s -> log.info(s));
}
为防止 mapper 方法执行完断开数据库连接,在方法上加 @Transactional
配置 spring mvc 的几种方式的区别
Spring Boot 1.x 中,自定义 SpringMVC 配置可以通过继承 WebMvcConfigurerAdapter 来实现。
Spring Boot 2.x 中,自定义 SpringMVC 配置建议通过实现 WebMvcConfigurer 接口来完成。
如果在 Spring Boot 中使用继承 WebMvcConfigurationSupport 来实现自定义 SpringMVC 配置,或者在 Spring Boot 中使用了 @EnableWebMvc 注解,都会导致 Spring Boot 中默认的 SpringMVC 自动化配置失效。
filter 和 interceptor 的关系
Filter 由 Servlet 标准定义,要求 Filter 需要在 Servlet 被调用之前调用,作用顾名思义,就是用来过滤请求。在 Spring Web 应用中,DispatcherServlet 就是唯一的 Servlet 实现。
Interceptor 由 Spring 自己定义,由 DispatcherServlet 调用,可以定义在 Handler 调用前后的行为。这里的 Handler ,在多数情况下,就是我们的 Controller 中对应的方法。
BeanFactory
BeanFactory 默认采用延迟初始化策略,即当容器启动时,并未完成 Bean 的初始化,只有当调用到该 Bean 的实例时,才会完成其初始化操作,并进行依赖注入。
ApplicationContext 在 BeanFactory 的基础上提供了事件发布、国际化等功能。同时,ApplicationContext 在容器启动时,就会完成所有 Bean 的初始化。
BeanFactory 是 IOC容器的一级接口,主要提供了一些和 Bean 相关的查询方法。
直接继承 BeanFactory 的有三个二级接口
- HierarchicalBeanFactory,定义了工厂分层
- AutowireCapableBeanFactory ,它扩展了自动装配的功能。
- ListableBeanFactory ,该接口可以列出工厂可以生产的所有实例。
ConfigurableListableBeanFactory 同时继承这三个接口,DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 接口。
FactoryBean 用于在配置属性复杂的情况下通过编码实现bean配置
Spring AOP pointcut常用表达式
- execution是使用的最多的一种Pointcut表达式,表示某个方法的执行,其标准语法如下。
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern表示方法的访问类型,public 等;
ret-type-pattern表示方法的返回值类型,如String表示返回类型是String,* 表示所有的返回类型;
declaring-type-pattern表示方法的声明类,如 com.elim…*表示com.elim包及其子包下面的所有类型;
name-pattern表示方法的名称,如“add*”表示所有以add开头的方法名;
param-pattern表示方法参数的类型,name-pattern(param-pattern)其实是一起的表示的方法集对应的参数类型,如“add()”表示不带参数的add方法,“add(*)”表示带一个任意类型的参数的add方法,“add(*,String)”则表示带两个参数,且第二个参数是String类型的add方法;
throws-pattern表示异常类型; - within 是用来指定类型的,指定类型中的所有方法将被拦截。
Spring Bean 生命周期
Spring事务
事务抽象接口 PlatformTransactionManager
,通常使用实现类DataSourceTransactionManager
。
@Bean(name = "pcTransactionManager")
@Primary
public DataSourceTransactionManager pcTransactionManager() {
return new DataSourceTransactionManager(pcDataSource());
}
一般都使用声明式事务,利用 AOP 实现,使用的是 around 增强。在SpringBoot 2.X 中,默认全部使用 CGlib 代理。
- JDK 动态代理要求代理对象实现接口,代理类是代理对象的兄弟类,所以注入时用接口形式接收,不能用实现类。
- CGlib 不要求实现接口,代理类是代理对象的子类,所以无论以接口形式还是实现类接收都是可以的。缺点在于代理对象不能是final的,否则无法继承。
在多数据源的情况下要注意在 @Transactional
中选定 transactionManager
Spring 的JDBC异常抽象,可以自定义特定异常码下抛出的异常类型
@Transactional 失效的几种场景
- 同一类中方法调用
- 方法不是用public 修饰
- 错误的 Propagation :
TransactionDefinition.PROPAGATION_SUPPORTS
:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED
:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER
:以非事务方式运行,如果当前存在事务,则抛出异常。 - 错误的 rollbackFor
- 数据库不支持事务
- 在事务方法里另外捕获了异常
解决类内调用 @Transactional
事务失效的方法
- 通过注入实例,调用实例的方法
- 获取当前代理,避开直接调用实例
((FooService) (AopContext.currentProxy())).insertThenRollback();
JPA Java Persistence API 为 O/R Mapping 提供一种基于 POJO 的持久化模型
Spring Data 中 xxxTemplate 和 Repository 的区别
xxxTemplate 的好处是灵活,可以做任意操作,但是都要自己写。Repository 好处是做了大部分常见操作的封装,使用方便。Spring Data在保留底层存储特性的同时,提供了相对一致的编程模型,比如 JdbcTemplate,MongoTemplate,RedisTemplate 等。
Spring 中使用 redis
使用原生 jedis-client 时,注意jedis 实例不是线程安全的,使用 jedisPool 获取实例。SpringBoot 2.X中的 Spring Data Redis 使用的是 lettuce ,支持读写分离。
Spring 缓存抽象
Spring 的缓存类型可以是 JVM内部缓存、EhCache、Redis等。由 spring.cache.type
设置。有多个缓存配置可以使用 CompositeCacheManager
配置。
很少变、或者可以接受短时不一致的信息,可以缓存在JVM内部。集群中需要一致的缓存信息,可以放在外部缓存中。读写比很小的就不使用缓存。
基于注解的缓存:@EnableCaching 、@Cacheable、@CacheEvict、@Caching、@CacheConfig、@CachePut
SpringMVC请求处理流程
- 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
- DispatcherServlet 根据请求信息调用 HandlerMapping,解析得到请求对应的 mappedHandler,其中包含请求的Controller类和具体方法,以及拦截器执行链。
- 由 HandlerAdapter 适配器处理,执行相应的业务逻辑。
- 处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。对于json数据,mv为 null ,此时已经就返回了。
- 如果有返回视图,ViewResolver 会根据逻辑 View 查找实际的 View。
- DispaterServlet 把返回的 Model 传给 View(视图渲染)。
- 把 View 返回给请求者(浏览器)
StopWatch 可以用来计算请求耗时
SpringBoot 自动配置实现原理
@SpringBootApplication
——> @EnableAutoConfiguration
——> @Import(AutoConfigurationImportSelector.class)
——>
会从META-INF/spring.factories
中加载自动配置类,然后根据类上的条件注解
(@Conditional、@ConditionalOnClass、@ConditionalOnProperty、@ConditionalOnBean等)来决定是否初始化以及如何初始化对应的Bean。
Spring 扩展点
- BeanFactoryPostProcessor:针对Bean定义,在创建Bean之前获取元数据,可用作低版本Spring实现自动配置的手段。
- BeanPostProcessor:针对Bean实例,在创建Bean之后提供回调
Spring Bean的定制
生命周期回调:
- InitializingBean、@PostConstruct、init-method
- DisposableBean、@PreDestroy、destroy-method
xxxAware:
- ApplicationContextAware:可以获取容器上下文
- BeanFactoryAware
SpringBoot 核心
- 自动配置
- 起步依赖
- Actuator
@PropertySource 可加载指定配置文件,配合@Value 或 @ConfigurationProperties
@PropertySource 的功能还可以通过实现 EnvironmentPostProcessor 实现
Spring IOC学习笔记
IOC容器在创建bean时,通过构造函数、工厂方法参数或者在实例化完之后设置的参数来定义对象的依赖关系。
BeanFactory 是顶级接口,ApplicationContext 接口继承 BeanFactory,提供更多企业级功能。
元数据配置可以用 XML、注释 或者 Java代码
创建 Bean 时,推荐使用构造函数注入,确保必须项不为 null 。Setter 注入应用于可选项的属性。
单例的和预先实例化(默认值)的 Bean 会在 ApplicationContext 初始化时被创建,其他的Bean在请求时再创建。
我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
Spring Boot 推荐用Java 配置类,并推荐使用 启动类 作为配置类,如果要使用xml 配置,在配置类的地方使用注解 @ImportResource(locations = {"xxx.xml"})
Spring Boot 可通过实现 ApplicationContextAware 接口获取 ApplicationContext 对象,但不推荐直接使用这个对象获取Bean,应使用自动装配注释
Spring Boot 自动注入推荐做法
@Service
public class DatabaseAccountService implements AccountService {
//使用构造函数注入,可以用 final 修饰
private final RiskAssessor riskAssessor;
//只有一个构造函数,可以省略 @Autowired
@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
20. Spring Bean 作用域
默认单例。对于有状态的 Bean,应使用 Prototype ,每次都创建一个新的实例。在单例Bean 中引用原型的 Bean,可以用 @Lookup注解在返回类型为对应Bean的方法上。
27. Spring Bean 生命周期回调
- 初始化回调:可以但不推荐实现
InitializingBean
接口的afterPropertiesSet()
方法,因为和Spring耦合过强,xml 配置可以用init-method
,注解配置用@Bean(initMethod='xxx')
或者@PostConstruct
- 销毁回调:同上,实现
DisposableBean
接口 或者 xmldestroy-method
或者@PreDestroy
- xml 配置全局默认初始化回调:在顶级标签beans上增加
<beans default-init-method="init">
,默认销毁回调同理。
28. Spring Bean 属性 depends-on 表示在实例化之前先实例化依赖的 Bean
29. Spring @Autowired 可以用在 List、Set、Map属性上。@qualifier名字不一定要不同,注入如List、Set时会将名字相同都注入进来
30. ResponseEntity 代表整个http response ,可以自定义头信息、状态码、body体。优先级高于@ResponseBody
31. Spring Boot 优雅注入配置文件
- 不推荐的做法:
@Value
@ConfigurationProperties
绑定 bean,需要@Component
,@Autowired
配合。
32. 过滤器和拦截器
- 过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。
- 拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。
33. Spring Boot 的几种参数校验方式
JSR提供的校验注解:
@Null
被注释的元素必须为 null@NotNull
被注释的元素必须不为 null@AssertTrue
被注释的元素必须为 true@AssertFalse
被注释的元素必须为 false@Min(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值@DecimalMin(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值@DecimalMax(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max=, min=)
被注释的元素的大小必须在指定的范围内@Digits (integer, fraction)
被注释的元素必须是一个数字,其值必须在可接受的范围内@Past
被注释的元素必须是一个过去的日期@Future
被注释的元素必须是一个将来的日期@Pattern(regex=,flag=)
被注释的元素必须符合指定的正则表达式
Hibernate Validator提供的校验注解:
@NotBlank(message =)
验证字符串非null,且长度必须大于0@Email
被注释的元素必须是电子邮箱地址@Length(min=,max=)
被注释的字符串的大小必须在指定的范围内@NotEmpty
被注释的字符串的必须非空@Range(min=,max=,message=)
被注释的元素必须在合适的范围内
- Controller @RequestBody 校验:直接在参数前加
@Valid
,失败会抛出MethodArgumentNotValidException
- Controller @PathVariable和@RequestParam 校验非自定义实体类参数:在类上加
@Validated
,再在参数上加各种注解,以及@Valid
(可选),失败会抛出ConstraintViolationException
- Controller 校验自定义实体类参数:直接加
@Valid
,失败会抛出BindException
- Service 校验非自定义实体类参数:在类上加
@Validated
,在接口参数上加校验注解,不能只在实现类上加,除非不用接口。失败会抛出ConstraintViolationException
- Service 校验自定义实体类参数:同第 4 点,除了参数上只使用
@Valid
34. Spring Boot 自定义校验注解
注解类上加@Constraint(validatedBy = xxxxx.class)
,然后对应的 Validator 类实现 ConstraintValidator
接口
35. Spring Boot 定时任务
方法上加@Scheduled,类上加@EnableScheduling。
使用固定速率 fixedRate,如果任务执行时间大于间隔,则会扰乱执行间隔,不建议。
默认所有定时任务共用一个线程,可配置线程池 ,实现 SchedulingConfigurer
接口
@EnableAsync
和 @Async
使定时任务并行执行
Spring Cloud 服务发现与注册抽象
bootstrap.properties 和 application.properties 有何区别
Spring Boot 在结合 Spring Cloud 时,就会经常遇到 bootstrap,特别是在需要加载一些远程配置文件的时侯。
bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加载的,比 applicaton 优先加载,配置在应用程序上下文的引导阶段生效。一般来说我们在 Spring Cloud Config 或者 Nacos 中会用到它。且 boostrap 里面的属性不能被覆盖;
application (. yml 或者 . properties):由ApplicatonContext 加载,用于 spring boot 项目的自动化配置。