当前使用spring版本为spring5.3, springboot2.3.6
1. spring
spring是一个轻量级的控制反转和面向切面的容器
1.1. BenFactory
/**
* 18-ApplicationContext的三个实现类(掌握)
* ①ClassPathXmlApplicationContext
* 根据类路径下的xml配置文件来加载Spring容器
* ②FileSystemXmlApplicationContext
* 根据系统盘符路径下的xml配置文件来加载Spring容器
* ③AnnotationConfigureApplicationContext
* 根据注解配置类来加载Spring容器
* ②FileSystemXmlApplicationContext
*/
@Test
public void test2() {
ApplicationContext beanFactory = new FileSystemXmlApplicationContext("C:\\Users\\qiuzhiwei\\Desktop\\spring4.xml");
Object user = beanFactory.getBean("user");
System.out.println("user = " + user);
}
web
2. ioc和di
2.1.spring-context(spring容器)
spring容器启动流程:
①Servlet容器启动, 会创建一个ServletContext全局上下文环境对象, 由于在web.xml 中配置了ContextLoaderListener, 会加载该监听器
②ContextLoaderListener类实现了ServletContextListener, 所以在ServletContext容器启动时,会执行 contextInitialized ()方法, contextInitialized ()会调用父类的initWebApplicationContext()方法
③initWebApplicationContext()调用了determineContextClass()方法, determineContextClass方法获取了ServletContext中"contextClass"的属性值作为全类名, 后面会用类名通过反射创建该类的实例,
④如果这个在web.xml中配置了"contextClass"参数则会加载配置的全类名作为spring容器
⑤如果没有在spring容器中配置"contextClass", 后面会给该全类名赋值 XmlWebApplicationContext
⑥后面会加载配置的"contextClass"或者XmlWebApplicationContext 作为spring的上下文
spring容器初始化过程:(以AnnotationconfigApplicationContext举例)
①AnnotationconfigApplicationContext调用自身构造器, 创建自身实例
②先执行父类初始化方法, 父类实例化了一个DefaultListableBeanFactory对象
③实例化一个BeanDefinitionReader实例和ClassPathBeanDefinitionScanner扫包器
④向容器中添加了两个BeanFactory后置处理器
⑤向容器中添加了两个Bean后置处理器
⑥将配置类的信息注册到容器中(即将BeanDefinition注册到容器中, 并非类的实例化)
⑦调用ApplicationContext的refresh()方法启动或者刷新容器
2.2. ioc
ioc: 控制反转, 将设计好的对象的控制权交给程序(spring容器)控制, IOC是一种设计思想
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.XmlWebApplicationContext</param-value>
</context-param>
2.3. di
对象控制权由程序员本身反转给程序(spring容器)控制, IOC是一种设计思想
di: 依赖注入, 通过spring容器将程序A对B的依赖注入到A, 可以降低两个程序之间的耦合
3. aop
aop底层使用动态代理技术,
动态代理分为两种:
①jdk动态代理: 适用于被代理类实现了接口, 生成的代理类同样会实现该接口,
②cglib动态代理: 适用于所有类, 生成的代理类会直接继承被代理类,
aop实现的两种方式:
使用标签配置切面
<aop:config>
<aop:pointcut id="p1" expression="execution(public void com.atguigu.service.impl.UserServiceImpl.addUser(..))"/>
<!--通知和切入点关系-->
<aop:aspect ref="myAdvice1">
<aop:before method="checkPermissions" pointcut-ref="p1"></aop:before>
<aop:after method="recordLog" pointcut-ref="p1"></aop:after>
</aop:aspect>
<aop:aspect ref="myAdvice1">
<aop:after method="recordLog" pointcut-ref="p1"></aop:after>
</aop:aspect>
</aop:config>
②使用注解配置切面
@Before("execution(* *..*Service.*(..))")
4. spring-web
spring-web组件
- DispatcherServlet:前置控制器,负责调度其他组件的执行,可以降低不同组件之间的耦合性,是整个Spring MVC的核心模块
- Handler:处理器,完成具体的业务逻辑,相当于Servlet
- HandlerMapping:DispatcherServlet是通过 HandlerMapping把请求映射到不同的Handler
- HandlerInterceptor:处理器拦截器,是一个接口,如果我们需要进行一些拦截处理,可以通过实现该接口完成
- HandlerExecutionChain:处理器执行链,包括两部分内容:Handler和HandlerInterceptor(系统会有一个默认的HandlerInterceptor,如果有额外拦截处理,可以添加拦截器进行设置)
- HandlerAdapter:处理器适配器,Handler执行业务方法之前,需要进行一系列的操作包括表单的数据验证、数据类型转换、把表单数据封装到POJO等,这些一系列的操作都是由HandlerAdapter完成,
- DispatcherServlet通过HandlerAdapter执行不同的Handler
- ModelAndView:封装了模型数据和视图信息,作为Handler的处理结果,返回给DispatcherServlet
- ViewResolver:视图解析器,DispatcherServlet通过它把逻辑视图解析为物理视图,最终把渲染的结果响应给客户端
4.1. 工作流程
- 客户端请求被DispatcherServlet接收
- 根据HandlerMapping映射到Handler
- 生成Handler和HandlerInterceptor
- Handler和HandlerInterceptor以HandlerExecutionChain的形式一并返回给DispatcherServlet
- DispatcherServlet通过HandlerAdapter调用Handler的方法完成业务逻辑处理
- 返回一个ModelAndView对象给DispatcherServlet
- DispatcherServlet把获取的ModelAndView对象传给ViewResolver视图解析器,把逻辑视图解析成物理视图
- ViewResolver返回一个View进行视图渲染(把模型填充到视图中)
- DispatcherServlet把渲染后的视图响应给客户端
原文链接:https://blog.csdn.net/qq_52797170/article/details/125591705
DispatcherServlet会在第一次访问时加载, 加载DispatcherServlet时,会调用initStrategies()方法,这个方法会初始化处理器映射器, 处理器适配器, 视图解析器及其他spring-web功能.
DispatcherServlet继承于FrameworkServlet, FrameWorkServlet继承于HttpServletBean, HttpServletBean继承于HttpServlet;
前端控制器DispatcherServlet的url-pattern=“/”,意味着所有资源都交给了DispatcherServlet处理
DispatcherServlet没有能力去处理静态资源,所以报错404,应该将静态资源放行给tomcat内置的缺省Servlet处理。
<mvc:resources mapping="/img/**" location="/img/"></mvc:resources>
<mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
<mvc:resources mapping="/html/**" location="/html/"></mvc:resources>
4.2. 拦截器-HandlerInterceptor
①preHandle():在请求被处理之前进行操作;预处理。
②postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果;*后处理**。*
③afterCompletion:所有的请求响应结束后执行善后工作,清理对象、关闭资源 ;*最终处理**。*
**使用方法: **
①自定义Interceptor类实现HandlerInterceptor接口
/**
* ①自定义Interceptor类实现HandlerInterceptor接口
*/
public class MyInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//②
//在处理器Handler之前执行,如果返回值为true就放行,如果返回值为false就拦截。
System.out.println("MyInterceptor1 preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//④
//在处理器Handler之后,在页面渲染之前执行
System.out.println("MyInterceptor1 postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//⑤
//在处理器Handler之后,在页面渲染之后执行
System.out.println("MyInterceptor1 afterCompletion");
}
}
②注册自定义Interceptor类
<!--②注册自定义Interceptor类-->
<mvc:interceptors>
<bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
</mvc:interceptors>
拦截路径配置:
<mvc:interceptors>
<mvc:interceptor>
<!--①精确匹配 -->
<!--<mvc:mapping path="/interceptor/testInterceptor"/>-->
<!--②匹配单层路径-->
<!--<mvc:mapping path="/interceptor/*"/>-->
<!--③匹配多层路径-->
<mvc:mapping path="/interceptor/**"/>
<!--④配置不拦截路径-->
<mvc:exclude-mapping path="/interceptor/testInterceptor"/>
<bean class="com.atguigu.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器原理:
①所有请求都会调用doDispatcher()方法,
②doDispatcher()方法会调用HandlerExecutionChain(处理器执行链)的applyPreHandle()方法, applyPreHandler()方法会执行所有的拦截器的preHandle()方法,
③然后DispatcherServlet会执行handle()方法, 该方法会调用处理器适配器,并最终调用处理器来执行Controller的所有方法,
④然后执行applyPostHandle()方法, 这个方法同上, 在controller层处理数据完成后会调用所有拦截器的postHandle()方法
⑤响应完成
⑥最后执行拦截器的
5. spring-context
spring上下文, 维护了spring运行环境, 其中包括有 ApplicationContext等容器核心类
6. spring-dao
6.1. 数据库连接
①原始的数据库连接是使用java适配数据库接口进行(加载驱动, 获取连接, 获取SQL执行对象, 执行SQL)
②连接池的出现使得可以将创建的连接(每次创建的连接对应一个库的连接)得以保存(连接是复用性很高且珍惜的资源, 不应该随意销毁)
③spring原生:
1. 通过读取SqlMapConfig.xml配置文件中的驱动和连接创建SqlSessionFactory对象,
2.通过SqlSessionFactory对象创建SqlSession对象
3.SqlSession通过读取入参找到对应的mapper.xml文件的<namespace/>标签,(<namespace/>标签是mybatis对该mapper编译名),并找到对应的SQL语句id,根据该id来执行SQL
④使用Mybatis-spring,
需要在spring应用上下文中放入SqlSessionFactory和一个数据映射器类
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
//dataSource可以是任何DataSource
Mybatis-Spring使用SQLSession的子类SQLSessionTemplate
<!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--利用构造器注入, 引用sqlSessionFactory创建实例-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!--配置SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--关联Mybatis-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/kuang/dao/*.xml"/>
</bean>
<!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
<bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
7. spring-mvc
spring-mvc 由三部分组成: 模型层Model, 视图层View, 控制层Control,
MVC是一种软件架构思想,把软件按照模型,视图,控制器来划分
spring MVC全名为spring web mvc, 提供前端控制器, 处理器映射器, 处理去适配器, 处理器, 视图解析器等组件
执行流程:
①当第一个请求访问服务器时, Servlet开始初始化, 初始化途中创建ServletContext
②ServletContest初始化后, 监听器ContextLoaderListener触发, 开始初始化WebApplicationContext(Spring容器)
③WebApplicationContext初始化过程中, 会读取spring.xml等spring配置文件, 实例化并装配容器中的类(取决于容器是否懒加载, 作用域是否是singleton)
8. spring-boot
spring的快速配置脚手架
8.1. 自动配置原理
①spring-boot采用了自动配置原理
②自动配置原理即是提供一套已经配置完善的快速配置脚手架,
③spring-boot的自动配置原理的核心理念是约定大于配置, 以达到搭建快速,方便集成的微服务的目的, 同时还能起到规范约束的作用
8.2. 零配置原理
@SpringBoot注解中有一个
9. spring-cloud
微服务治理技术
10.bean
10.1. bean的作用域(scope)
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"/>
①singleton: (默认)单例, 在spring容器中只存在一个该类型的单例, 容器创建对象就创建, 容器销毁对象销毁
②prototype: 每次获取都会生成一个新的对象, 对象交给gc管理
③request: 在一次请求中使用同一个对象, 仅可用于WebApplicationContext环境
④session: 在一个会话中生效, 仅可用于WebApplicationContext环境
10.2. bean的初始化
11.spring项目读取配置文件
12.mybatis
12.1. mybatis工作原理
mybatis工作原理: (配置文件为mybatis的配置文件, 不是spring的配置文件)
mybatis底层是jdbc, 依旧是加载驱动, 获取连接来连接数据库
①mybatis读取xml配置文件, 并且存入到一个Configuration类中
Configuration会存在整个mybatis的生命周期
②SqlSessionFactoryBuilder会根据Configuration类(mybatis的配置文件)创建SqlSessionFactory
③SqlSessionFactory会根据配置的DataSource创建一个连接池, 同时会解析配置文件中的类型解析器和映射器信息
类型解析器:用来处理java对象和数据库之间的数据转换
映射器:包括xml映射器, 注解映射器, 接口映射器, 可以扫描配置文件, 注解, mapper映射文件
④SqlSessionFactory会创建SqlSession对象
SqlSession对象是mybatis中的核心会话对象, 他提供了执行SQL和管理事务的方法
⑤SqlSession主要用法有两种:
通过直接使用SqlSession来执行Sql
根据mapper映射文件执行SQL:
根据mapper映射文件执行SQL:
①通过映射器获取到映射文件的namespace, 根据namespace中的全类名获取到class对象,并在Configuration(映射器容器)中添加该mapper
②MapperProxyFactory工厂提供Mapper接口的代理类代理mapper执行方法.
mybatis-spring使用SqlSessionTemplate对象本质上也是使用代理类
代理类代理SqlSessionTemplate执行selectone()方法
mybatis配置文件:
MyBatis的配置文件包含了全局配置信息和SQL映射信息,MyBatis通过解析配置文件来获取这些信息,并根据配置信息初始化SqlSessionFactory。
12.2. mybatis缓存
一级缓存:
①默认自动开启, 无法手动关闭, 只能手动清楚缓存数据
②SqlSession级别, 在同一个SqlSession中生效
二级缓存:
①默认关闭可, 手动开启
②在同一个namespace中生效
- dml操作会刷新缓存
- 开启了二级缓存会先查询二级缓存再查询一级缓存
- 缓存是将查到的数据临时序列化
13.注册中心
注册中心保存所注册服务的信息, 服务提供者和消费者注册到Eureka中, 将服务信息(ip, 端口等)携带到了Eureka, 并维持心跳连接
当服务消费者要调用提供者时, 会通过rpc协议或者http协议向注册中心传输信息(请求信息), 注册中心会找到消息提供者, 将请求转发给提供者, 然后提供者响应给注册中心, 注册中心响应给平台
13.1. Eureka(注册中心)+Ribbon(注册中心层面的客户端负载均衡+远程调用)
. mybatis缓存
一级缓存:
①默认自动开启, 无法手动关闭, 只能手动清楚缓存数据
②SqlSession级别, 在同一个SqlSession中生效
二级缓存:
①默认关闭可, 手动开启
②在同一个namespace中生效
- dml操作会刷新缓存
- 开启了二级缓存会先查询二级缓存再查询一级缓存
- 缓存是将查到的数据临时序列化
13.注册中心
注册中心保存所注册服务的信息, 服务提供者和消费者注册到Eureka中, 将服务信息(ip, 端口等)携带到了Eureka, 并维持心跳连接
当服务消费者要调用提供者时, 会通过rpc协议或者http协议向注册中心传输信息(请求信息), 注册中心会找到消息提供者, 将请求转发给提供者, 然后提供者响应给注册中心, 注册中心响应给平台
13.1. Eureka(注册中心)+Ribbon(注册中心层面的客户端负载均衡+远程调用)
13.2. nacos(注册中心+配置中心)+openfeign