@SpringBootApplication
2021-08-25 19:13:11 0 举报
AI智能生成
@SpringBootApplication
作者其他创作
大纲/内容
@SpringBootApplication
@SpringBootConfiguration
@Configuration
@Component
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)
Import
Registrar.class
@Import(AutoConfigurationImportSelector.class)
getCandidateConfigurations
SpringFactoriesLoader
loadFactoryNames
loadSpringFactories
spring.factories
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
Spring
容器和对象的创建流程
告诉Spring我们需要的Bean(通过配置文件)
告诉Spring我们需要的Bean(通过配置文件)
1. 先创建容器
2. 加载配置文件, 封装成BeanDefinition
加载配置文件(定义bean)
读取配置文件
BeanDefinitionReader接口定义读取配置文件, 不同的配置文件实现接口去读取
解析配置文件
BeanDefinition接口 解析Bean的定义信息, 不会进行值的替换
3. 调用执行BeanFactoraryPostProcessor
后置操作(替换占位符)
BeanFactoryPostProcessor(可能有多个)
在这一步进行占位符的替换(jdbc.name->root)
准备工作
准备beanPostProcessor
准备监听器, 事件, 广播器
4. 实例化Bean
堆空间中开辟空间, 属性都是默认值
通过反射获取Bean对象
获取Class对象(Clazz)
Class.forname(类全限定名)
类名.class
对象.getClass()
获取类对象
Constructor ctor = Clazz.getDeclaredConstructor()
Object obj = ctor.newInstance()
Object obj = ctor.newInstance()
5. 初始化Bean
Bean的生命周期
Bean的生命周期
填充属性
set方法
调用Aware接口的方法
invokeAwareMethods
BeanNameAware, BeanClassLoaderAware, BeanFactoryAware
目的是调用容器对象属性的set方法, 完成属性的注入
before
beanPostProcessor(扩展功能)
AOP
动态代理(AopProxy)
cglib
CglibAopProxy
jdk
JdkDynamicAopProxy
需要接口
调用ApplicationContextAware 的set方法
虽然实现了BeanFactory, 但是是两套流程所有分开调用set方法
调用init方法
after
beanPostProcessor(扩展功能)
完整对象可以使用
销毁过程
Spring容器按照使用者可以分为
自定义对象
如果想要在自定义对象中获取到容器对象怎么办?
(Person对象想要获取 Beanfactory, ApplicationContext对象)
(Person对象想要获取 Beanfactory, ApplicationContext对象)
1. 把这些对象定义到类中, 创建对应set方法
谁来调用这些set方法呢? Spring容器, 这些容器类都有对于的Aware方法, 用来注入这些容器对象
2. Person类实现BeanFactoryAware, ApplicationContextAware接口
容器类aware接口中定义了对应容器类对象的set方法
3. 容器调用这些容器类的set方法
invokeAwareMethods
容器对象
BeanFactory, ApplicationContext...
定义Bean的方法
<bean/>
@Bean
@Component
BeanDefinition
FactoryBean
创建类A, 实现FactoryBean接口, 并在这个类上加@component
getObject()
返回一个对象
getObjectType()
返回一个对象的Class类型
会创建两个Bean对象,
一个是这个实现了FactoryBean接口的实现类Bean对象,
&bean对象名称, 可以获得这个factoryBean
另一个是getObject返回的Bean对象
bean对象名称, 获得factoryBean创建的bean对象
supplier
注解
针对Bean管理中创建对象提供的注解
@Component
这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
@Service
这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
@Controller
此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。
@Repository
这个注解是具有类似用途和功能的 @Component 注解的特化。
基于注解方式实现属性的注入
@AutoWired
根据属性类型进行自动装配
@Qualifier
根据属性名称进行注入
@Resource
可以根据类型注入 可以根据名称注入
过注解里name属性并赋值为不同实现注解里的别名可以即根据类型又根据名称注入
@Value
注入普通类型属性
MVC
@RequestMapping
用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。
此注释可应用于两个级别:
此注释可应用于两个级别:
类级别:映射请求的 URL
方法级别:映射 URL 以及 HTTP 请求方法
方法级别:映射 URL 以及 HTTP 请求方法
关键方法
refresh()
创建容器
prepareRefresh();
做容器刷新前的准备工作
obtainFreshBeanFactory()
创建容器对象, 加载xml配置文件的属性值到当前工厂中, 最重要的是BeanDefinition
1.销毁已有的BeanFactory
2. 创建BeanFactory
3. 设置相关属性
4. 配置文件的加载(loadBeanDefinition)
prepareBeanFactory()
beanFactory的准备工作, 对各种属性进行填充
postProcessorBeanFactory()
模板方法的体现, 子类覆盖方法做额外处理, 这里是一个空方法
invokeBeanFactoryPostProcessors()
调用各种beanFactory处理器
registerBeanPostProcessor()
注册bean处理器, 只是注册功能
finishBeanFactoryInitialization()
初始化剩下的单实例
创建对象的几个重要方法
getBean()
尝试在容器中获取Bean对象
doGetBean()
实际获取bean的方法
createBean()
创建Bean对象
doCreateBean()
实际创建Bean对象的方法
createBeanInstance()
实例化Bean对象
关键类
BeanFactory
访问Spring容器Bean的入口: The root interface for accessing a Spring bean container.
等同于容器
子接口ApplicationContext
PostProcessor
后置处理器, 增强器
BeanFactoryPostProcessor
针对BeanFactoryPostProcessor进行占位符的替换等后置操作, 因为读取了配置文件得到Bean的定义信息, 但是不会替换占位符
实现类: PlaceholderConfigurerSupport
* Abstract base class for property resource configurers that resolve placeholders
* in bean definition property values.
* in bean definition property values.
可以解析Bean Definition 中的占位符
BeanPostProcessor
针对Bean
postProcessBeforeInitialization()
postProcessAfterInitialization()
aware
容器对象的set方法
Implementing this interface makes sense for example when an object requires access to a set of collaborating beans
IOC
IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理
通过配置文件, 注解的方式将Bean注册到Spring的IoC容器里, 在需要的时候直接从IoC中获取就可以了, 无需去管理依赖的对象
核心是BeanFactory
存在着一个Map保存了对象名-对象的pair, 这样调用BeanFactory.getBean(对象名字)就可以获取到这个Bean
不存在就创建对象放入map返回
因为Bean默认是单例的所以, 需要在放入Map的过程加锁保证只会放入一个单例Bean对象
AOP
动态代理
cglib
如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。
CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
jdk
需要接口, 创建接口实现类的代理对象, 通过代理对象增强需要增加的功能
编写JDK动态代理方法
创建接口, 定义方法
创建接口实现类, 实现方法
使用Proxy类创建接口代理对象
定义一个JDK动态代理类 JDK_proxy
其中利用Proxy.newProxyInstance()方法创建接口实现类的动态代理对象
newProxyInstance()需要传入三个参数
1. 当前类的类加载器
2. 该代理对象所代理的实现类所实现的接口
3. InvocationHandler接口的实现类的对象
2. 该代理对象所代理的实现类所实现的接口
3. InvocationHandler接口的实现类的对象
创建UserDaoProxy类实现InvocationHandler接口
将被代理类的对象传递进来
set
构造器
重写接口中invoke(Object proxy, Method method, Object[] args)方法
1. proxy 被代理对象
2. method需要被增强的方法
3. args method方法的参数
2. method需要被增强的方法
3. args method方法的参数
通过参数中method.invoke(被代理对象(通过有参构造传递进来),args ) 执行被增强的原始方法
1. 该方法的返回值也是当前invoke方法的返回值
1. 该方法的返回值也是当前invoke方法的返回值
在method之前或之后, 实现方法的增强
在动态代理类中把InvocationHandler接口的实现类UserDaoProxy的对象传递进来
1. 需要先new 一个被代理类的对象 userDao
2. 传递到UserDaoProxy对象参数中, 将被代理类传递进去
3. 该方法实例化的是被代理类的代理对象, 需要强制转化成被代理类实现的接口, 因为实际上是增强了接口里的方法
4. 通过该代理类调用对应的方法, 获得增强方法后的结果
2. 传递到UserDaoProxy对象参数中, 将被代理类传递进去
3. 该方法实例化的是被代理类的代理对象, 需要强制转化成被代理类实现的接口, 因为实际上是增强了接口里的方法
4. 通过该代理类调用对应的方法, 获得增强方法后的结果
UserDao dao = (UserDao)Proxy.newProxyInstance(JDK_proxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
DefaultAopProxyFactory类
AopProxy createAopProxy()
这个方法返回一个AopProxy对象, 可以是
CglibAopProxy
JdkDynamicAopProxy
AOP思想梳理
匹配方法
按照某个类别匹配, 类似于正则表达式的东西来匹配
expression表达式
方法名字, 方法参数, 方法返回值, 完全限定名
方法的哪些位置可以插入代码?
环绕通知 @Around
add()方法之前之后都执行
前置通知 @Before
add()方法之前执行
后置通知 @After
add()方法之后执行
最终通知 @AfterReturning
相当于try catch finally 中的finally, 无论add()方法是否异常都最后执行
异常通知 @AfterThrowing
add()方法发生异常才执行
AOP 具体的执行过程
创建IOC容器存放对象
进行对象的实例化和初始化, 放入容器
容器运行过程中需要的对象
BeanFactoryPostProcessor
BeanPostProcessor
AbstractAutoProxyCreator
用户需要的对象
用户自定义
advice
MethodInterceptor
从容器获取对象
调用具体的方法
AOP核心名词
连接点
类中可以被增强的方法, 称为连接点
切点 advice
实际被增强的方法, 称为切入点
切面
把通知应用到切入点的过程称为切面
通知
实际增强的逻辑部分, 称为通知
循环依赖问题
什么是循环依赖?
A类中含有B类的属性b; B类中含有A类的属性a
因为在Spring中对象Bean默认是单例的, 整个容器一个类只有一个对象, 创建AB单例对象的时候就会产生循环依赖
因为A类中的b属性应该已经是一个完整的对象
因为A类中的b属性应该已经是一个完整的对象
根本问题是属性赋值
构造器
无法解决循环依赖
set方法
通过三级缓存+提前暴露解决
循环依赖的过程
创建A对象
实例化A对象(b=null)
填充A对象的b属性
从容器中查找B对象, 找到了直接赋值
没找到B对象, 需要创建B对象
实例化B对象(a=null)
填充B对象中的a属性
从容器中查找A对象, 找到了直接赋值
没找到A对象, 需要创建A对象, 至此形成了一个闭环导致循环依赖
解决方法:
三级缓存+提前暴露
三级缓存+提前暴露
实例化过程中, 将处于半成品的对象全部放到缓存中, 方便后续进行调用
只要有了对象的引用地址, 因为对象默认单例, 后续进行复制也可以
半成品对象放到了map缓存结构中, 成品对象也需要放到某一个map中, 但是成品和半成品不能放到一起
如果放到一起, 就会导致获取对象的时候, 获取到半成品值为null
为了将成品和半成品对象完全的区分开, 可以创建多级缓存来区分
三级缓存
三种缓存
(DefaultSingletonBeanRegistry)
(DefaultSingletonBeanRegistry)
一级缓存
Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
b完成初始化操作后, 将创建完成的成品b对象放入一级缓存, 并且从二级三级缓存中删除b的半成品对象
a对象在b对象完成初始化放入一级缓存后, 可以从一级缓存中取到b对象, a对象自己完成创建后, 将自己放入一级缓存并且删除二三级缓存中的半成品对象
二级缓存
Map<String, Object> earlySingletonObjects = new HashMap<>(16);
b从三级缓存中获取到a的半成品对象时, 将a对象放入二级缓存, 将三级缓存的a对象删除,
三级缓存
Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
函数式接口
可以传递一个lambda表达式进来, 在进行调用的时候使用getObject来调用lambda表达式中的方法
实例化但未初始化的半成品对象提前放入三级缓存
key:a, value:lambda
lambda: ()->getEarlyBeanReference(beanName, bean)
a,b实例化后都会放入三级缓存
三级缓存分别存储什么对象?
1. 成品对象
2. 半成品对象
3. lambda表达式
从三级缓存getValue()就会调用这个lambda表达式获得半成品对象
如果只有一级缓存行不行?
不行, 因为成品和半成品对象会放到一起, 在进行对象获取的时候有可能获取到半成品对象
如果只有二级缓存行不行?
三级缓存使用的地方
getSingleton
doCreateBean
将这里从三级缓存获取对象和将实例化的对象放入三级缓存的逻辑改成二级缓存, 结果可以成生成两个Bean对象
但是开启AOP之后失败, 报错: 没有使用最终版本的bean对象
但是开启AOP之后失败, 报错: 没有使用最终版本的bean对象
三级缓存做了什么?
如果一个对象需要被代理, 生成代理对象, 这个对象需要预先生成非代理对象
三级缓存放的value是 lambda: ()->getEarlyBeanReference(beanName, bean)
这个方法可能会用代理对象替换非代理对象
如果没有三级缓存, 就无法得到代理对象, 那么在整个容器中, 包含了同名对象的代理对象和非代理对象
因为对象都是单例的, 根据名称只能获取一个对象的值,但是现在存在两个, 无法判断, 所以必须保证容器中任何时候都只有一个对象供外部调用
所以在三级缓存中, 完成了代理对象替换非代理对象的工作, 确定返回的是唯一的对象
三级缓存是为了解决AOP代理过程中产生的循环依赖问题, 如果没有AOP的话, 二级缓存也可以解决循环依赖问题
起始相当于是一个回调机制, 当需要使用当前对象的时候, 会判断次对象是否需要被代理实现, 如果直接替换掉, 不需要直接返回非代理对象即可
完整对象 vs 完成实例化但未完成初始化
Spring的设计模式
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
Spring事务
编程式事务管理
对应事务开启, 操作,提交等 都用代码的方式写出来
声明式事务管理(使用)
通过配置方式
基于注解方式(使用)
创建配置类, 使用配置类替代xml配置文件
@Configuration //配置类
@ComponentScan(basePackages = "com.AtGuiGu.Spring10_Transaction") //组件扫描
@EnableTransactionManagement //开启事务
@ComponentScan(basePackages = "com.AtGuiGu.Spring10_Transaction") //组件扫描
@EnableTransactionManagement //开启事务
//创建数组库连接池
@Bean
public DruidDataSource getDruidDataSource(){
@Bean
public DruidDataSource getDruidDataSource(){
//创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
基于xml配置文件方式
Spring的事务传播行为
当多个事务同时存在的时候,spring如何处理这些事务的行为。
- ① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
- ② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
- ③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
- ④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
- ⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- ⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- ⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
- ② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
- ③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
- ④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
- ⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- ⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- ⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
BeanFactory vs FactoryBean
BeanFactory
Spring 容器最核心也是最基础的接口,本质是个工厂类,用于管理 bean 的工厂,最核心的功能是加载 bean,也就是 getBean 方法,通常我们不会直接使用该接口,而是使用其子接口。
FactoryBean
该接口以 bean 样式定义,但是它不是一种普通的 bean,它是个工厂 bean,实现该接口的类可以自己定义要创建的 bean 实例,只需要实现它的 getObject 方法即可
生成Bean的工厂Bean, 同样也是Bean对象, 但是需要通过&才能获取这个factoryBean对象
SpringMVC
执行流程
- (1)用户发送请求至前端控制器DispatcherServlet;
- (2)DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
- (3)处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返回给DispatcherServlet;
- (4)DispatcherServlet 调用 HandlerAdapter处理器适配器,请求执行Handler;
- (5)HandlerAdapter 经过适配调用 具体处理器进行处理业务逻辑;
- (6)Handler执行完成返回ModelAndView;
- (7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- (8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- (9)ViewResolver解析后返回具体View;
- (10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- (11)DispatcherServlet响应用户。
- (2)DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
- (3)处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返回给DispatcherServlet;
- (4)DispatcherServlet 调用 HandlerAdapter处理器适配器,请求执行Handler;
- (5)HandlerAdapter 经过适配调用 具体处理器进行处理业务逻辑;
- (6)Handler执行完成返回ModelAndView;
- (7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- (8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- (9)ViewResolver解析后返回具体View;
- (10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- (11)DispatcherServlet响应用户。
代码流程
配置web.xml , 注册DispatcherServlet
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
编写SpringMVC 的 配置文件
添加 处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
添加 处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
添加 视图解析器
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
编写我们要操作业务Controller
1. @Controller是为了让Spring IOC容器初始化时自动扫描到;
2. @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
2. @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
装数据
addObject("key", "value")
封视图;
setViewName("viewname")
返回一个ModelAndView,
各个组件的作用
- 前端控制器 DispatcherServlet:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
- 处理器映射器 HandlerMapping:根据请求的URL来查找Handler
- 处理器适配器 HandlerAdapter:负责执行Handler
- 处理器 Handler:处理器,需要程序员开发
- 视图解析器 ViewResolver:进行视图的解析,根据视图逻辑名将ModelAndView解析成真正的视图(view)
- 视图View:View是一个接口, 它的实现类支持不同的视图类型,如jsp,freemarker,pdf等等
- 处理器映射器 HandlerMapping:根据请求的URL来查找Handler
- 处理器适配器 HandlerAdapter:负责执行Handler
- 处理器 Handler:处理器,需要程序员开发
- 视图解析器 ViewResolver:进行视图的解析,根据视图逻辑名将ModelAndView解析成真正的视图(view)
- 视图View:View是一个接口, 它的实现类支持不同的视图类型,如jsp,freemarker,pdf等等
SpringMVC怎么样设定重定向和转发的?
(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
SpringMVC常用注解
@Controller
- 负责注册一个bean 到spring 上下文中
- 也可以使用@RestController,相当于@ResponseBody + @Controller,表示是表现层
- 也可以使用@RestController,相当于@ResponseBody + @Controller,表示是表现层
@RequestMapping
注解为控制器指定可以处理哪些 URL 请求
@RequestBody
该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,
然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上
然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上
@RequestParam
在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法
@PathVariable
绑定 URL 占位符到入参
@ResponseBody
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区
@ModelAttribute
- 在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法
- 在方法的入参前使用 @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 –绑定到对象中,再传入入参将方法入参对象添加到模型中
- 在方法的入参前使用 @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 –绑定到对象中,再传入入参将方法入参对象添加到模型中
@ExceptionHandler
注解到方法上,出现异常时会执行该方法
@ControllerAdvice
使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常
Mybatis
执行流程
- 1)读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
- 2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
- 3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
- 4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
- 5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
- 6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
- 7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
- 8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
- 2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
- 3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
- 4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
- 5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
- 6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
- 7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
- 8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
编码流程
编写Mybatis核心配置文件 mybatis-config.xml
编写Mybatis工具类
获取sqlSessionFactory对象
获取SqlSession对象
实体类
编写接口 Mapper
接口实现类由原来的UserDaoImpl转变为一个Mapper配置文件 UserMapper.xml
编写Mapper中的SQL语句(Select, Update, Add, Delete)
- id: 就是对应的namespace中的方法名
- resultType: sql 语句执行的返回值
- parameterType: 参数类型
- resultType: sql 语句执行的返回值
- parameterType: 参数类型
核心配置文件mybatis-config.xml中注册mappers.xml
#{}和${}的区别
#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
缓存
一级缓存
- 与数据库同一次会话期间查询到的数据会放在本地缓存中。
- 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
- 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
二级缓存
- 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
- 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
- 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
缓存查找流程
1. 先查看二级缓存 找到直接返回
2. 二级缓存没找到 继续找一级缓存
3. 一级缓存没有 数据库查询
2. 二级缓存没找到 继续找一级缓存
3. 一级缓存没有 数据库查询
SpringBoot
@EnableAutoConfiguration
主要作用就是根据具体的判断条件去找到spring.factories文件中加载可以加载的组件类的全限定名
利用全限定名+反射就可以获取类的对象注入到Spring IoC容器, 这样达到了自动装配的效果
run
读取spring.factories中的监听器, 开始监听
准备环境对象, 读取需要的环境变量
0 条评论
下一页