spring boot笔记

spring基础

对spring的理解

spring如何管理Bean(核心思想:依赖注入)

注册Bean

  1. 注册Bean: 相当于new一个java类—–独立抽出依赖
  2. 常用注释: @Bean@Component@Controller@Service@Repository

装配Bean

  1. 装配Bean: 相当于调用new得到的java类,来使用它;按类型装配由于Java多态性实现IOC—–注入依赖
  2. 常用注解: @Autowired

理解

注册过的Bean会存放在spring容器中,当装配Bean时,会从spring容器中(按类型、按名字)去取出适合的Bean new成实例,提供使用。

而按类型装配Bean,则会灵活的利用java多态性,实现IOC

MVC思想

Controller控制器

SpringMVC之请求参数的获取方式

  1. 返回体定制:ResponseEntity

常用注释

spring内置常用注释列表

项目主入口注解

@SpringBootApplication

相当于以下三个注解:

  1. @EnableAutoConfiguration: 启用 Spring Boot 的自动配置机制;所以在Spring Boot中以下@EnableXXX可写可不写:

    a. 包括了: @EnableAspectJAutoProxy;容器中注册的Bean可以使用AOP
    这样被注册的Bean,就可以使用@Aspect@Pointcut@Around等实现AOP了。
    [为什么spring boot直接可以使用AOP](java – Spring AOP works without @EnableAspectJAutoProxy? – Stack Overflow)

    b. 包括了:@EnableWebMvc:容器中注册的Bean可以使用成为拦截器
    这样被注册的Bean,就可以使用implements WebMvcConfigurer注入拦截器了

    c. 包括了:@EnableAsync:容器中注册的Bean可以使用异步多线程

    这样被注册的Bean,就可以使用@Async执行异步函数了

    Spring Boot中如何优雅的使用多线程

    d. 包括了:@EnableScheduling:容器中注册的Bean可以使用定时任务

    这样被注册的Bean,就可以使用@Scheduled执行定时任务函数了

    Spring Boot中如何优雅的使用定时任务

    e. 包括了:@EnableTransactionManagement:容器中注册的Bean可以使用事务

    这样被注册的Bean,就可以使用@Transactional执行事务了

    Spring Boot中如何优雅的使用事务管理器以及创建多个数据源的事务管理器

  2. @ComponentScan: 扫描被@Component注解的 bean,注解默认会扫描该类所在的包下所有的类

    包括了:@MapperScan@Mapper@Repository都可以不用写,因为在application.yml中配置了mapper的接口路径

  3. @Configuration: 允许在 Spring 上下文中注册额外的 bean 或导入其他配置类

注册Bean、装配Bean

  1. 注册Bean两种方式:

    @Component:修饰类;里面的每个@Bean每次调用都是新实例
    @Configuration:修饰类是特殊的@Component;里面的每个@Bean都是单例模式
    @Bean:修饰被@Component、@Configuration标注的类中的成员方法
    三层架构的类的注释(默认单例模式): @Controller(表现层)、@Service(业务层)、 @Repository(持久层)

    @RestController 相当于 @Controller + @ResponseBody

    Spring @Configuration@Component 区别)

    @Scope(···)
    singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
    prototype : 每次请求都会创建一个新的 bean 实例。
    request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
    session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。

    @Profile(···): 指定环境变量下注册Bean

    @Mapper: Mybatis的注解,向Spring容器中注册Bean;等价于在启动类上扫描文件路径@MapperScan;

    配置文件注意:需要把写Mapper层的XML文件路径写在配置文件中application.ymlmybatis mapper-locations、配置Entity类路径mybatis typeAliasesPackage

    持久层注册装配过程:Spring会根据配置文件中的mybatis mapper-locations扫描所有的Mapper层的XML并根据在Mapper层的XML中使用namespace的全限定包名找到对应的DAO接口,并实现该DAO接口里面的每个成员方法生成一个新的DAO类Bean;且这个新的DAO类Bean的类型为DAO接口名,命名为首字母小写的DAO接口名;最后把这个新的DAO类Bean注册到Spring容器中;当Service层通过@Resource即可找到那个新的DAO类Bean并注入进来,至此整个持久层就串起来了。

    ​ 扫描接口路径:每个DAO接口类上都加上@Mapper <====等价于====>在启动类或自定义Mybatis配置类上使用@MapperScan。二者选一个即可、也可以都不加;因为只要Spring容器扫描XML文件XML文件又能通过namespace找到DAO层接口。

    ​ 配置每个DAO类的成员方法实现类XML路径:在配置文件中application.ymlmybatis mapper-locations

    ​ 配置XML文件中简写返回类型的包路径:在配置文件中application.ymlmybatis typeAliasesPackage;推荐使用全限定名不要用alias

    @Mapper为什么可以不用写

  2. 装配Bean: ——- 按名字装配性能最优
    源自spring库: @Autowired 默认按类型装配、@Autowired + @Qualifier(···) 按名字装配;
    源自java标准: @Resource(name="···")默认按名字装配、@Resource(type="···")

    注意:通常注解式装配Bean直接是注入到成员变量中,相当于setter注入

Spring boot将含有多个构造器的类注入到bean容器,并实现区分对同一个类不同bean名称的 bean的区分的四种方法

Spring Boot注解装配只能使用无参构造器,如果需要注入有参构造器的Bean则可以通过new getApplicationContext().getBean(clazz)(··参数··)

spring用注解无法灵活注入带参构造函数解决办法

请求相关

  1. 请求方法注解:

@GetMapping(···)@PostMapping(···)@PutMapping(···)@DeleteMapping(···)@PatchMapping(···);
@RequestMapping(value="···",method=RequestMethod.POST)
2. 请求参数传值注解:
@PathVariable@RequestParam@RequestBody(替换@ModelAttribute)

请求参数校验

读取配置文件

@EnableConfigurationProperties

@PropertySource: 指定使用的配置文件

@ConfigurationProperties: @ConfigurationProperties(prefix = "···")

全局异常处理

@ControllerAdvice

@RestControllerAdvice(定义全局处理异常类): 相当于 @ControllerAdvice + @ResponseBody
@ExceptionHandler(写你想要拦截的异常类型)

解释: 被 @RestControllerAdvice 注解的类会自动注入到 控制器请求方法注解(@RequestMapping)中

spring异常处理

事务处理

ServiceImpl的方法中使用: @Transactional(rollbackFor = Exception.class)

json相关注解

其他Spring相关注解

  1. @EnableXXX
    配合@Configuration使用,包括 @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy, @EnableWebMvc
    通常Spring boot不需要配置,框架已经配置好了

  2. @Lazy
    spring启动时不先实例化bean,等到使用时才开始实例化

Lombok库的注解

疑问

@Bean用于第三方组件的注册

Spring MVC相关

Spring的生命周期

实例化Bean启动时 BeanPostProcess

  1. Spring对Bean进行实例化(相当于程序中的new Xx())
  2. Spring将值和Bean的引用注入进Bean对应的属性中
  3. 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
  4. 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
  5. 如果Bean实现了ApplicationContextAwaer接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把y应用上下文作为参数传入.(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )
  6. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)
  7. 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。
  8. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法(作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )
  9. 经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁10.如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。

监听器

  • 实现 javax.servlet.ServletRequestListener, javax.servlet.http.HttpSessionListener, javax.servlet.ServletContextListener 等等接口
  • 主要用来监听对象的创建与销毁的发生, 比如 session 的创建销毁, request 的创建销毁, ServletContext 创建销毁
@Slf4j
@Component
@Conditional(JeecgCloudCondition.class)
public class SystemInitListener implements ApplicationListener<ApplicationReadyEvent>, Ordered {
    @Autowired
    private ISysGatewayRouteService sysGatewayRouteService;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        log.info(" 服务已启动,初始化路由配置 ###################");
        if (applicationReadyEvent.getApplicationContext().getDisplayName().indexOf("AnnotationConfigServletWebServerApplicationContext") > -1) {
            sysGatewayRouteService.addRoute2Redis(CacheConstant.GATEWAY_ROUTES);
        }
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
复制代码

Spring监听器—ApplicationListener与主动触发监听器

过滤器Filter

基于回调实现、属于web层,依赖于Servlet

适用于: 静态资源请求

// 首先 不需要任何@EnableXXX,只需要框架里有Servlet即可


// 第一步:自定义过滤器 ··· implements Filter
//重写方法 init、doFilter、destroy


//第二步:注入过滤器到spring容器中的2种方式
//1. 在自定义过滤器上直接使用注解
@Order
@WebFilter // 功能类似于FilterRegistrationBean注册过滤器
@WebInitParam
    
//2. 在注册了的Bean中代码形式注入过滤器
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean registFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean(); //属于Servlet中的一个方法,用于注册过滤器
        registration.setFilter(new CostTimeFilter());
        registration.addUrlPatterns("/*");
        registration.setName("CostTimeFilter");
        registration.setOrder(1);
        return registration;
    }
}
复制代码

SpringBoot 中过滤器的简介及使用方式

拦截器

基于反射AOP思想,拦截控制器,依赖于Spring框架
适用于: 统一权限控制、动态请求

// 首先开启 @EnableWebMvc,Spring Boot默认已经开启

// 第一步:自定义拦截器 ··· extends HandlerInterceptor/HandlerInterceptorAdapter
// 重写方法 preHandle、postHandle、afterCompletion

// 第二步:注入拦截器 ··· implements WebMvcConfigurer
复制代码

AspetAOP

拦截Service
实际开发中,AOP常和事务结合

AOP的实现原理—-本质是反射

服务器定位模式(Service Locator) < == == > 委托模式(delegate)< == == > 反射、动态代理 < == ==> 类的方法不是由自己的实例调用,而是委托给用户自主调用

Spring默认使用cglib库的反射实现,没有用jdk自带的反射

控制器 servlet、controller

解析器 ··· implements HandlerMethodArgumentResolver

方法参数解析器:适用于使用注解使控制器方法参数的运行时修改
视图解析器(ViewResolver)
语言解析器

// 首先开启 @EnableWebMvc,Spring Boot默认已经开启

// 第一步:自定义解析器 ··· implements HandlerMethodArgumentResolver/···  extends AbstractNamedValueMethodArgumentResolver
// 重写方法 createNamedValueInfo、resolveName、supportsParameter、handleMissingValue

// 第二步:注入解析器 ··· implements WebMvcConfigurer
复制代码

Spring自定义参数解析器参考代码

spring发起一个请求的过程

容器启动、销毁等事件的监听器(ApplicationListener或自定义事件监听) ->
前端控制器(DispatcherServlet) -> 请求到处理器映射(HandlerMapping) -> 过滤器(Filter) -> Servlet容器(Tomcat) -> 拦截器(Interceptor) -> 解析器(Resolver) -> AOP -> 控制器(Controller) -> 验证器(Validator) -> 命令对象(Command 请求参数绑定到的对象就叫命令对象)-> 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象;就是需要返回给前端的值)

Spring过滤器与拦截器-代码实现
过滤器、拦截器区别
拦截器、过滤器区别—知乎
spring生命周期

Spring架构

Spring工程模板推荐

Spring MVC详细讲解

spring boot常用组件

监控模块

Spring Boot ActuatorMicrometer

Spring MVC

模型(Model)中注入数据

  1. Spring MVC 传递模型数据到视图中方法总结

请求参数校验

使用方式

  1. 在controller中的参数中使用@Validated
  2. entity文件中使用@valid注解标注 以校验 集合中的元素自定义数据类型
  3. 自定义校验器,统一错误信息返回格式

校验详细介绍

Springboot之分组验证以及自定义参数验证

Spring中的零散知识点

路径匹配

**: 表示任意多级目录
*: 表示任意名称的目录
classpath*:classpath::打包速度前者慢些
classpath*:org/jeecg/modules/**/xml/*Mapper.xml: 此种方式能匹配到与输出目录classes同级的jar包内部的文件
classpath*:/mapper/**/*.xml:输出目录中的静态资源

Spring中的Bean默认是单例模式,为什么可以并发请求

单例模式的成员变量必须保证线程安全,如用ThreadLocal,单例的方法及其局部变量每次调用都会创建在自己的方法栈上下文中,因此可以保证并发而互不影响。

所以Spring中的所有注册的类的成员变量有两种情况:

  1. 成员变量是使用@Autowired等注解,且这个成员变量的类定义中成员方法也满足条件1、条件2
  2. 成员变量是其他普通类型,如int、List、Set、Map等,则必须手动保证线程安全ThreadLocal,

spring boot web层基于servletservlet的每个request是一个线程;而且数据库连接也要保证线程隔离,因为临时表绑定变量等都只在当前会话有效,且不同会话互相隔离,才有意义;当有要求单次请求中需要多次操作数据库,必须把多次操作封装在一个事务中。

在同一个方法中,Mybatis多次请求数据库,是否要创建多个SqlSession会话? – 简书 (jianshu.com)

spring中的mybatis的sqlSession是如何做到线程隔离的? – 等你归去来 – 博客园 (cnblogs.com)

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享