Spring/MyBatis

Spring

BeanFactory是Spring工厂,IOC工厂
ApplicationContext是Spring容器,IOC容器
SpringMVC是基于Spring来实现的
SpringBoot是方便启动的,让整个项目快速运行
在这里插入图片描述

SpringBoot演示

新建Spring项目,一般在网页start.spring.io建立,不用在idea中建:
在这里插入图片描述

在这里插入图片描述

然后genrate,会生成一个压缩包,下载到本地
在这里插入图片描述
在这里插入图片描述

然后导入IDEA中,看一下maven设置,这里有两个特别的设置,可以改变目录的展现形式
关键是pom.xml
在这里插入图片描述

新建一个子包,controller
新建一个类AlphaController,用来处理前端请求

在这里插入图片描述

做以下注释:
在这里插入图片描述
然后运行main方法:
在这里插入图片描述
在网页上显示:
在这里插入图片描述

为什么可以启动这么快?
可见项目依赖了很多包,但是并没有一个个去依赖
怎么实现的?因为刚才在start里填写了web,最终会映射到pom.xml里,然后spring帮我们把包根据应用场景整合在一起

在这里插入图片描述
在这里插入图片描述

独立运行

自动配置后面说
里面内嵌了tomcat,tomcat是以包的形式存在这里面的

Spring优点(IOC)

IOC的好处:如果没有IOC,对象得自己创建,对象依赖得自己设置,对象得自己管理,自己管理很不靠谱。
IOC可以使对象做到可插拔

dao是数据访问层的代码

IOC叫控制反转,是将bean的管理权力交给Spring来做,Spring做这个事有什么好处,通俗来说就是降低bean之间的耦合度,使bean做到可插拔,撤换掉某个bean很方便

单例的用IOC来管理,实体的数据变化多,可复用,每个用户都不一样,一般不用IOC管理

Controller、Service、Repository功能是一样的, 只是语义有区别,controller用在控制层,service是服务,repository是数据层

要调谁就叫Autowired,而且调的是接口,具体要注入谁是Spirng决定的
Controller一般没有接口,因为Controller是页面调的,要换的话就重写一个Controller

PathVariable的意思是从路径里,把id解析出来,然后传给这个方法的参数id
ResponseBody表示要把最后的结果做成字符串返回给页面
返回的是json格式,就是map的形式,{id:1,username:’’,password:’’}
在这里插入图片描述

IOC不止能把bean注入给别人,还能管理bean的生命周期和作用域
可以看到这里,创建了个init方法,然后加了一个注解 PostConstruct,表示在初始化后(构造方法之后)执行这个方法
创建了一个destroy方法,加了注解PreDestroy,表示在销毁前执行这个方法
在这里插入图片描述

怎么体现是单例的:
默认创建的是单例的
在两个controller中都依赖UserService,但是运行只会生成一个对象
如果加了Scope(“prototype”)注解,表示作用域,就会创建两个对象,因为两个Controller都装配了Service。
prototype表示多个实例
Scope作用域默认是singleton单例,一般情况都是单例
在这里插入图片描述

在这里插入图片描述

IOC管理bean就是通过BeanFactory管理的
BeanFactory是比较底层的API,是开发框架的时候用的
ApplicationContext是子接口,应用相关,功能比较全,开发者一般用这个

ApplicationContext核心的功能就是获取bean
在这里插入图片描述

创建spring项目会自带一个“项目名词” + Application的类,整个项目从这里启动
main方法中传入这个类的对象class,表示配置文件,让spring自动配置

底层做的事:
1.加载配置文件,加载resources下的application.properties配置文件
2.启动Tomcat
3.创建Spring容器
4.自动扫描bean并将其装配到容器里

在这里插入图片描述

AOP

面向切面编程,面向方面编程
解决公用的需求,比如很多组件要做同样的事情,以一个低耦合、可插拔的方式解决,比如五个bean都要记录日志,都要事务管理,可以以AOP统一去做

因为要加一个注解Aspect
虽然现在已经有了aop的包了,可以用spring原生的方式去调用,也可以用方面的注解,但是aspect的注解不是自带的,默认是没有的,所以需要pom.xml里添加一个包:
在这里插入图片描述

AOP:
首先是目标组件,影响哪些bean,要对哪些bean做处理
第二个是连接点,JoinPoint,Spring里就是方法,目标是对象,连接点就是对象的方法。例如哪些个方法需要记录日志
这两个东西需要在写程序前分析好
目标组件和连接点表示程序中定位的问题

Aspect方面组件,表示写的这个类有特殊的含义
Aspect是一个切面,是AOP的组件,能影响很多个bean
哪些bean的哪些方法是我们的目标,用PointCut切点表示,service..*(…)表示service包下的所有类的所有方法
PointCut表示用来影响谁,表示行为发生的地点

pointcut拦截完以后,需要处理的逻辑是什么时候执行?
Advice表示通知,比如记日志这个事情,是在执行逻辑之前记还是之后,还是抛出异常时记录,表示行为发生的时机
但是怎么影响到目标组件呢,需要将Aspect的这些代码织入到连接点,让代码生效

织入有三种方式,如下

但是在方面里写的代码为什么就在连接点调用了呢,关键就是织入运行的时候,Spring中的AOP给目标Service生成一个代理对象,然后在代理对象里怎么操作都可以,在任何位置上添加代码都可以。所以底层执行的时候不是我们写的service,而是一个代理类
面试问,但是用的比较少,因为都被事务的组件实现了

在这里插入图片描述

切点位置:
在这里插入图片描述

在这里插入图片描述

也可以把这些日志写在一个方法里,但是一般不建议这样写,容易犯错:
在这里插入图片描述

SpringMVC

Servlet是java针对web开发制定的一个标准,服务器Tomcat是支持这个标准的
我们开发一个Servlet是要注册给Tomcat,Tomcat去调这个东西

前端发请求访问后台代码,所有的请求在SpringMVC框架下都是交给DispatcherServlet去统一处理。它接收到一个请求,请求中包含一个路径,比如要访问user/detail/…访问item什么什么。需要解析这个路径背后是由哪个组件,哪个Controller去处理
那么怎么去找呢,它依赖于HandlerMapping,这个组件是用来扫描代码中哪些Bean上是带有Controller注解的,然后把它们先存储起来;因为扫描那个注解就知道了requestmap路径是什么,对应的方法是什么,这里面存储的是路径和方法的对应关系

DispatcherServlet询问HandlerMapping路径应该用什么方法去处理,HandlerMapping给出一个结果
HandlerMapping在启动的时候就去扫描,将路径方法对应存储起来,用的时候返回一个处理这个请求的链,能处理这个请求的往往不是一个组件,而是多个组件。这个链中包含了Controller和拦截器

DispatherServlet现在知道请求是由谁来处理,但是还要得到Controller的实例,这时需要HandlerAdapter适配器,能够处理这个问题一个适配的组件,它里面持有了对Controller的引用,可以理解为Controller被它调用,或者被它持有
所以DispatcherServlet通过HandlerAdapter去调Controller,正常情况下Controller返回html,Spring里面默认是通过ModelAndView返回的html
现在有了Model 和View,那么它去找谁把模板和视图组织在一起呢,找另外一个核心组件ViewResolver,视图的解析器,它是依赖于ModelAndView的
ViewResolver通过ModelAndView知道了视图在哪里,数据是什么,合成一个前端需要的html,html用一个View组件做封装,由View组件给前端做一个相应,即response

DispatcherServlet起到一个协调的作用
第一步,通过HandlerMapping获取路径对应的组件Controller
第二步,通过HandlerAdapter去调用Controller,得到ModelAndView
第三步,得到的结果由ViewResolver处理,由View封装,向前台响应具体内容

有的时候用了拦截器能够对Controller形成拦截的话,这个拦截器会在三个地方,产生作用
1.在调HandlerAdapter之前拦截,
2.在调HandlerAdapter之后拦截,
3.视图响应数据以后,整个流程执行回DispatcherServlet过程中,做最后一层拦截(finally中)

拦截器可有可无,如果有的话,和AOP类似,能力比较强

但是在前后端分离的项目中,不用返回html,返回的是json,不用ViewResolver去处理,数据由HandlerAdapter直接处理返回,因为字符串简单;所以如果返回的json,那么HandlerAdapter直接向前台做响应就可以

那么什么时候直接做响应呢,是在Controller方法上加上了@ResponseBody注解的时候,由HandlerAdapter直接做响应
在这里插入图片描述

DispatherServlet是自动注册给容器的,已经被注册给Tomcat了,看doDispatch方法,派发请求,可以把它当做一个路由器
tomcat会把请求和响应都给这个方法

调用getHandler方法返回HandlerExecutionChain,封装了路径和bean的关系

接下来通过getHandlerAdapter获取了HandlerAdapter
在这里插入图片描述

每个HandlerMapping都能返回一个HandlerExcutionChain
在这里插入图片描述

然后调用handle方法,返回ModelAndView
在这里插入图片描述

ModelAndView在这里被处理
在这里插入图片描述

在这个方法中,如果mv不为空,会去渲染
在这里插入图片描述

在这里插入图片描述

MyBatis

引入依赖,数据库连接池是用的阿里的druid,因为是做电商

在这里插入图片描述
连接池怎么连接数据库,需要把连接参数给它
第一行是mybatis的配置,声明sql文件在哪里
classpath是target目录,是编译后的代码
源代码在编译后在target下是以一定形式组织的,classpath访问的是编译后的文件
xml不会编译,是搬运过来的

连接池需要配的是驱动类,mysql连接的url,用户名,密码,连接池的核心类(type)
在这里插入图片描述

在pom.xml中配置划线的插件
在这里插入图片描述

配置文件
在这里插入图片描述

这里是对数据库增删改查的操作(生成增删改查的代码)
table标签,指定表名是什么
domainObjextName 希望生成的实体类是什么
后面一行很多false,是说许多生成的东西不需要,就不要生成
generatedKey 主键是什么,自增的
字段有特殊的处理,columnOverride,这里price是double类型,计算精度会有损失,所以这里映射成BigDecimal
在这里插入图片描述

如何让这个代码生效,可以在命令行或者终端,用maven去构建:
(用这句话去生成代码)
在这里插入图片描述

然后生成这样一个实体
在这里插入图片描述

在DAO下生成了一个ItemMapper,这里生成了一些增删改查的方法(根据主键)
如果需要别的方法,根据这些方法添加别的方法就行了
这个接口不需要实现,也是用动态代理实现的,在运行的时候会帮你生成一个实现类
在这里插入图片描述

但是生成实现类的时候,需要知道底层的sql怎么写,查询增加怎么写?
是在一个配置文件中写的,在这个配置文件中指出相关联的接口
这个文件也是生成的,里面的sql语句也是生成的,可以在这个基础上修改
在这里插入图片描述

可以看到这个配置文件中有delete,insert标签
id就是刚刚接口中的方法,然后在标签中,增加了对应的sql语句

这里用 # 可以预编译,会变成?,编译以后再执行,底层是用的PreparedStatement
如果使用$就不会编译,就会直接拼接,就会有SQL注入的风险
在这里插入图片描述

这里需要在接口上加一个@Mapper,方便Spring去管理这个bean,这是MaBatis的要求
和之前的Repository是同义的
在这里插入图片描述
在这里插入图片描述

MaBatis的原理

第一个核心组件:SqlSessionFactory,通俗点就是session工厂
在mabatis体系中,session相当于数据库的连接
我们执行增删改查等数据库的操作,就是通过sqlSession来执行的
sqlSession是通过SqlSessionFactory来创建的,sqlSession依赖于SqlSessionFactory去构建

sqlSession封装的是底层的数据库连接connection,所以创建连接的时候,它需要访问到DataSource,获取连接,封装于其中
那么DataSource在哪里,从哪里读DataSource呢,是从配置类中Configuration读取,配置类的信息是从配置文件中加载的

那么我们需要写的Mapper接口(其实是应该我们写,只不过是借用了工具自动生成了)
Mapper接口和一个Mapper.xml配置文件有对应关系,一个mapper对应一个xml

mapper是一个接口,它的实现类是程序运行的时候,由MaBatis动态创建的,是一个动态代理的机制,
那么谁去做这个代理,谁来实例化这个接口,是MapperProxy,是一个代理类,它去调配置文件,明确要执行什么样的sql语句
实现接口的时候,需要获取 sqlSession,利用这个sqlSession执行增删改查的方法,所以它依赖于SqlSession

那么SqlSessionFactory是什么时候去创建SqlSession呢,这里是自动配置的,启动服务器,就自动创建好了
自动配置的类叫做MyBatisAutoConfiguration,在程序启动的时候,自动的去初始化,创建SqlSessionFactory

1.所以整个过程的第一个环节是自动配置,一启动,自动配置类生效,创建SqlSessionFactory
2.SqlSessionFactory要想创建sqlSession,必须读取数据源,需要依赖于配置类Configuration,这个配置类其实读取的是application.properties这个文件
3.Configuration也会去看mapper.xml都有哪些,加载Mapper.xml的配置信息,如下图
sqlSessionFactory去加载和matabis配置有关的内容

那么Mapper接口什么时候去实现,还是通过自动配置类去驱动的,底层还有一个组件,是扫描这个接口的组件,Mapper.xml是被Configuration配置类扫描的,Mapper接口是被MapperScannerConfigurer扫描的,它会去扫描Mapper,看哪些类有Mapper注解,生成对应的动态代理MapperProxy
4.配置类去调用MapperScannerConfigurer扫描带有Mapper注解的接口,然后去实现它

所以程序中,哪个地方Autowired注入了这个接口,它给我们传的是MapperProxy这个东西

在这里插入图片描述
在这里插入图片描述

底层代码

先看DateSourceAutoConfiguration,Spring会去扫描注解,看这些注解条件去加载Bean

//第一个注解,表示这是一个配置类,那么Spring在启动的时候就会实例化它,和component、controller类似,但是这是一个配置类,不是在什么层
@Configuration(
    proxyBeanMethods = false
)
//这个注解的意思是,在程序中有DataSource类的时候,这个配置才被加载
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
//没有这个东西的时候会加载
@ConditionalOnMissingBean(
    type = {"io.r2dbc.spi.ConnectionFactory"}
)
//启用这个配置文件,这个类就是刚才说的Configuration,配置文件的类,全局的配置类
//这个自动配置的bean会用到这个全局的配置类
@EnableConfigurationProperties({DataSourceProperties.class})
//当前bean在调用的时候,会先把这两个bean实例化好,再导入
@Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {
    public DataSourceAutoConfiguration() {
    }

    static class EmbeddedDatabaseCondition extends SpringBootCondition {
        private static final String DATASOURCE_URL_PROPERTY = "spring.datasource.url";
        private final SpringBootCondition pooledCondition = new DataSourceAutoConfiguration.PooledDataSourceCondition();

        EmbeddedDatabaseCondition() {
        }
        .....

这个前缀叫spring.datasource,所以在配置文件里,以这个前缀开头的东西会被加载到这个bean里(如下图连接池的东西,会被这个DataSourceProperties读取到)
在这里插入图片描述
在这里插入图片描述

刚刚那个自动配置类是抽象的东西,druid是具体的东西
这个配置类会在DataSourceAutoConfiguration之前加载
并且启用了配置类druid的配置类和DataSource的配置类

在里面方法上有个注解Bean,Spirng扫描注解会调用这个方法,获得DataSource对象,把这个对象放到容器里,并且这Bean的名字和方法同名,就叫做dataSource
另一个注解ConditionalOnMissBean表示如果没有这个实例,就会去创建
在这里插入图片描述
druid的配置类
在这里插入图片描述

如果想要配置连接数,连接池的一些相关东西
需要在下面写spring.datasource.druid.(…)
在这里插入图片描述

MyBatisAutoConfiguration
第一个注解表示是一个配置类,Spring容器要加载它
第二个注解,如果程序中有SqlSessionFactory的时候,这个类就要被加载
第三个,如果只有一个DataSource的时候,加载它;如果有多个的时候,就需要自己搞定
第四个,读取mabatis的配置文件
第五个:在自动配置之后配置它,
在这里插入图片描述

myBatis的配置类,加载前缀是mybatis的参数,也就是下图的划线处
在这里插入图片描述
在这里插入图片描述

这里两个注释表示如果没有这个bean的时候,会调用这个方法,返回bean放在容器里
在这里可以看到是通过自动配置创建了SqlSessionFactory
先new,然后把配置文件给它
在这里插入图片描述
这里会读到那个文件中前缀为mabatis的参数
在这里插入图片描述

这里体现了MapperScannerConfiguration,但是这里没有注解,是怎么调用的呢
在这里插入图片描述

是在这里
在这里插入图片描述

这里注册这个bean,让他起作用
然后也能看出,这里Mapper就是注解的Mapper,所以在mybatis中注解就是这个
在这里插入图片描述

那么MapperProxy是由谁创建的?由MapperProxyFactory
MapperScanner扫描到的接口给了它,它会调newInstance,创建一个代理实现类
在这里插入图片描述

而这个类中,没有真正实现接口,最终执行的invoke方法,只有这个方法
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值