赞
踩
Mybatis是一个开源的Java持久层框架,它可以帮助开发者简化与数据库交互的过程,他允许你使用简单的xml或者注解配置来映射Java对象与数据库之间的关系。MyBatis在持久层中充当数据访问层,它位于业务逻辑和数据库之间,负责将Java对象与数据库记录进行映射。
简化数据库操作: MyBatis可以通过XML或注解配置来映射Java对象与数据库表之间的关系,从而避免了手动编写大量的JDBC代码。这使得数据库操作变得简单、直观,并且易于维护。
灵活的SQL控制: MyBatis允许开发者直接编写SQL语句,而不是像一些ORM框架那样自动生成SQL语句。这使得开发者可以更灵活地优化和调整SQL语句,以满足特定的性能需求。
高度可定制化: MyBatis的插件机制和丰富的配置选项,使得它非常灵活且高度可定制化。开发者可以根据项目需求来选择和配置功能,从而实现个性化的数据访问层。
轻量级: MyBatis是一个轻量级的框架,它不依赖于其他复杂的框架,只需引入MyBatis的相关依赖即可。这使得项目部署和运行时的资源消耗较小。
优秀的性能: MyBatis的直接SQL控制和缓存支持,使得它在处理大量数据时表现出色,具有很好的性能。
一级和二级缓存: MyBatis支持一级缓存(默认开启)和二级缓存(可配置),这些缓存可以减少数据库的访问次数,提高查询性能。
支持原生SQL: MyBatis允许开发者在XML文件中直接编写原生的SQL语句,这样对于一些复杂的查询或特殊需求,可以更容易地实现。
与现有项目集成: MyBatis不会强制你按照特定的开发模式或架构来进行开发,它可以与现有的Java项目很好地集成,适用于各种场景。
繁琐的配置: MyBatis需要通过XML或注解来配置SQL映射和数据库连接等信息,这可能导致配置文件变得庞大而复杂,特别是对于大型项目而言。
SQL维护: 直接编写SQL语句可以提供更大的灵活性,但也可能导致SQL的维护问题。当数据库模式发生变化时,可能需要手动修改大量的SQL语句,这可能会增加开发和维护的工作量。
缺乏全面的ORM支持: MyBatis在对象关系映射(ORM)方面相对较弱。与一些全面的ORM框架相比,MyBatis在处理复杂关系和对象图时可能需要更多的手动操作。
依赖于SQL: MyBatis的灵活性使得开发者可以直接编写SQL语句,但也可能导致开发者过度依赖于SQL,而忽略了一些ORM框架所提供的便利功能。
缓存管理: 尽管MyBatis支持缓存,但对于复杂的分布式环境或大规模系统,缓存管理可能变得复杂,需要开发者注意缓存的清理和更新机制。
对SQL有较高要求: 如果你对SQL有较高的要求,并希望能够直接控制和优化数据库查询语句,MyBatis是一个不错的选择。它允许你直接编写SQL语句,灵活性较高,可以更好地满足复杂查询和性能优化的需求。
现有数据库结构较复杂: 当你的项目需要与一个已经存在的复杂数据库结构进行交互时,MyBatis能够更好地适应,因为它不会对数据库结构有过多的假设和限制。
需要灵活性和定制性: MyBatis提供了丰富的配置选项和插件机制,可以根据项目的特定需求进行定制,而不必遵循严格的框架规范。
复杂的数据映射: 如果你的项目需要处理复杂的数据映射关系,或者有大量复杂的查询需求,MyBatis可以提供更细粒度的控制,以便更好地映射数据库和Java对象之间的关系。
对性能有要求: MyBatis的直接SQL控制和缓存支持使得它在处理大量数据时表现出色,具有很好的性能。
#{param} - 预编译参数:
#{}
被称为预编译参数,它在SQL语句中表示一个占位符,用于接收参数值。
当使用#{}
时,MyBatis会自动将传入的参数值进行预编译处理,包括合理地转义特殊字符,从而防止SQL注入攻击。
#{}
适用于大多数情况,特别是当参数值用于构建SQL查询条件时,推荐使用#{}
来保证安全性。
2.${param} - 字符串替换:
${}
被称为字符串替换,它在SQL语句中表示一个占位符,用于直接替换参数值。
当使用${}
时,MyBatis不会对参数值进行预编译处理,而是直接将参数值替换到SQL语句中,类似于字符串的简单替换。
${}
适用于一些特殊情况,比如动态生成表名、列名等场景,但使用${}
时需要注意潜在的SQL注入风险。
使用as 别名的方式让字段的别名与属性名一致。
使用<resultMap>来映射字段名和实体类属性名的一一对应的关系
1、使用RowBounds对象进行分页
可以在查询方法中传入RowBounds对象来实现分页,它包含offset和limit属性。offset表示从第几条记录开始,limit表示返回的记录条数。
2、使用MyBatis的分页插件
MyBatis提供了一个基于拦截器实现的分页插件。该插件会拦截执行的SQL,然后重写SQL,添加分页限制条件。
它的原理是:
(1)需要在SQL映射文件中配置分页插件
(2)在查询方法中只需要传入pageNum和pageSize参数
(3)插件根据页面参数生成对应的分页SQL语句,默认是基于MySQL的limit分页语句
(4)插件会拦截执行SQL的方法,重写SQL,添加分页条件
(5)将重写后的SQL交给数据库执行
(6)插件会从返回结果中取出分页数据
这样可以自动实现分页功能,不需要手动编写包含limit的SQL语句。
3、自己编写SQL实现分页
可以在SQL语句中直接编写带有limit子句的分页语句,进行分页操作。这需要在不同数据库编写对应的分页语句。
分页插件的工作流程如下:
拦截:分页插件会在MyBatis的执行流程中拦截SQL查询语句。
获取分页参数:插件会从传入的方法参数或上下文中获取分页参数,如当前页码和每页显示的记录数。
计算LIMIT和OFFSET:根据分页参数计算出LIMIT和OFFSET的值,即限制返回的记录数和偏移量。
修改SQL语句:将计算得到的LIMIT和OFFSET的值添加到原始的SQL语句中,生成新的分页SQL语句。
执行查询:使用修改后的分页SQL语句执行数据库查询,获取分页结果。
使用#{0},#{1}来获取参数,0表示DAO层的第一个参数,1表示DAO层的第二个参数。
使用@Param注解来传参数,然后使用#{参数名}来获取参数。
使用Map将多个参数封装成对象,然后传参。
执行原理: MyBatis在执行动态SQL时,会先解析XML或注解中定义的SQL语句,然后根据动态SQL中的条件进行判断和处理,生成最终的SQL语句。在解析过程中,MyBatis会根据动态SQL的元素类型,如<if>
、<choose>
、<foreach>
等,对SQL进行逻辑组合和替换。最终生成的SQL语句将包含满足条件的SQL片段,而排除不满足条件的SQL片段。这样就可以根据不同的条件生成不同的SQL,实现了动态SQL的功能。动态SQL的使用可以帮助开发者实现更灵活和可复用的数据库操作,尤其在处理复杂的查询条件和动态拼接SQL语句时非常有用。
Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
SqlSessionFactoryBuilder: SqlSessionFactoryBuilder是用于构建SqlSessionFactory的构建器。它可以读取MyBatis的配置文件,并根据配置文件中的信息创建SqlSessionFactory对象。通常,SqlSessionFactoryBuilder是在应用程序启动时创建的,用于构建SqlSessionFactory,然后用于创建SqlSession对象。
SqlSessionFactory: SqlSessionFactory是SqlSession的工厂,用于创建SqlSession对象。SqlSessionFactory是一个线程安全的对象,一般情况下,应该在应用程序的生命周期内只创建一个SqlSessionFactory实例,以避免不必要的开销。
SqlSession: SqlSession是MyBatis的核心接口,它提供了操作数据库的方法,包括查询、插入、更新和删除等。SqlSession的实例是非线程安全的,因此每个线程都应该拥有自己的SqlSession实例。SqlSession可以通过SqlSessionFactory来获取。
Mapper: Mapper是Mapper接口的实例,用于定义数据库操作的方法。Mapper接口是基于Java的一种声明式方式来定义SQL操作,其中的方法名和方法参数与SQL语句相关联。Mapper接口是一种将Java方法与SQL语句绑定的方式,通过这种方式,可以将SQL语句与Java代码解耦,并使得数据库操作更加简洁和可维护。
Mapper XML: Mapper XML是存放SQL语句和结果映射配置的XML文件。在Mapper XML中,可以使用SQL语句、参数映射、结果映射和动态SQL等特性。Mapper XML文件通常与Mapper接口相对应,通过XML文件中的namespace属性与Mapper接口进行关联。
Configuration: Configuration是MyBatis的核心配置类,用于保存MyBatis的全局配置信息。Configuration包含了所有的Mapper映射信息、类型别名、全局属性、数据库连接池和事务管理等配置项。SqlSessionFactory通过Configuration来创建SqlSession。
Executor: Executor是MyBatis执行SQL语句的核心组件。Executor负责将用户发起的数据库操作请求转换成JDBC的操作,并负责执行JDBC的操作以及处理结果。Executor有两种实现:SimpleExecutor和ReuseExecutor,分别对应普通的SQL执行和重用已编译的SQL执行。Executor的选择会影响MyBatis的性能和内存使用。
StatementHandler: StatementHandler是Executor的辅助组件,用于创建和执行JDBC的PreparedStatement对象,将SQL语句和参数传递给数据库执行,并处理数据库返回的结果。StatementHandler使用了MyBatis的ParameterHandler和ResultSetHandler来完成参数处理和结果集处理。
在只有一个参数并且在<if>
标签中使用的情况下,通常是需要使用@Param
注解的。
当MyBatis解析<if>
标签内的表达式时,如果没有使用@Param
注解指定参数名称,MyBatis会尝试从上下文中查找与参数类型相符的参数,这可能导致一些问题。
1.Mybatis 中有一级缓存和二级缓存,采用装饰设计模式;
2.默认情况下一级缓存是开启的,而且是不能关闭的 ,一级缓存是指 SqlSession 级别的缓存,当在同一个 SqlSession 中进行相同的 SQL 语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存 1024 条 SQL。
3.二级缓存是指可以跨 SqlSession 的缓存。 是 mapper 级别的缓存,对于 mapper 级别的缓存不同的sqlsession 是可以共享的,需要额外整合到第三方缓存 例如Redis、MongoDB、oscache、ehcache等。
一级、二级缓存 采用装饰模式设计封装。
Mybatis的一级缓存存放在SqlSession的生命周期,在同一个SqlSession中查询时,Mybatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中。
如果同一个SqlSession中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当Map缓存对象中已经存在改键值时,则会返回缓存中的对象。(一个SqlSession连续两次查询 得到的是同一个java对象)
任何的insert update delete操作都会清空一级缓存(增删改任何记录都会清空当前SqlSession的缓存)。
2.如果服务器集群的时候,每个sqlSession有自己独立的缓存相互之间不存在共享,所以在服务器集群的时候容易产生查询数据冲突问题。
方案1 在sql语句上 随机生成 不同的参数 存在缺点:map集合可能爆 内存溢出的问题
方案2 开启二级缓存(共享 依赖Redis实现)
方案3 使用sqlSession强制清除缓存
方案4 创建新的sqlSession连接。
MyBatis中的Executor是负责SQL语句执行的核心接口。主要作用是根据StatementHandler配置的语句处理器,调用数据库接口JDBC来执行SQL,并将结果映射成Java对象。
Executor在MyBatis执行过程中的地位核心。
Mybatis 中支持以下五种事务隔离级别:
READ_UNCOMMITTED(读未提交):允许读取其他事务未提交的数据,可能出现脏读、不可重复读、幻读等问题。很少使用。
READ_COMMITTED(读已提交):只能读取其他事务已经提交的数据,可以避免脏读,但是不可重复读和幻读问题仍可能存在。
REPEATABLE_READ(可重复读):在同一个事务中多次读取同一记录的结果是相同的,可以避免脏读和不可重复读问题,但仍可能出现幻读问题。
SERIALIZABLE(串行化):强制事务串行执行,避免脏读、不可重复读和幻读等问题,但会降低系统并发性能。
数据库默认的事务隔离级别,通常是可重复读。
Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。
Spring 是一个以 IoC 和 AOP 为基础的Java EE轻量级开源框架,其目的是用于简化 Java 企业级应用的开发难度和开发周期。
Spring框架的所有模块可以满足一切企业级应用开发的需求,在开发过程中可以根据需求有选择性地使用所需要的模块。
1、Spring Core(核心容器):spring core提供了IOC,DI,Bean配置装载创建的核心实现。
spring-core :IOC和DI的基本实现
spring-beans:BeanFactory和Bean的装配管理(BeanFactory)
spring-context:Spring context上下文,即IOC容器(AppliactionContext)
spring-expression:spring表达式语言
②Spring AOP:对⾯向切⾯编程提供了丰富的⽀持。这个模块是Spring应 ⽤系统中开发切⾯的基础,与DI⼀样,AOP可以帮助应⽤对象解耦。
spring-aop:面向切面编程的应用模块,整合ASM,CGLib,JDK Proxy
spring-aspects:集成AspectJ(AOP应用框架)
spring-instrument:动态Class Loading模块
③Spring Data Access
spring-jdbc:spring对JDBC的封装,用于简化jdbc操作
spring-orm:java对象与数据库数据的映射框架
spring-oxm:对象与xml文件的映射框架
spring-jms: Spring对Java Message Service(java消息服务)的封装,用于服务之间相互通信
spring-tx:spring jdbc事务管理
④Spring Web
spring-web:最基础的web支持,建立于spring-context之上,通过servlet或listener来初始化IOC容器
spring-webmvc:实现web mvc
spring-websocket:与前端的全双工通信协议
spring-webflux:Spring 5.0提供的,用于取代传统java servlet,非阻塞式Reactive Web框架,异步,非阻塞,事件驱动的服务
⑤Spring Message
Spring-messaging:spring 4.0提供的,为Spring集成一些基础的报文传送服务
⑥Spring test
spring-test:集成测试支持,主要是对junit的封装
轻量级:Spring框架是轻量级的,它不依赖于大型的应用服务器或容器,可以嵌入到各种Java应用程序中。它只需要少量的资源,并且在启动和执行时的开销非常低。
依赖注入(Dependency Injection):Spring框架通过依赖注入来管理组件之间的依赖关系。这使得代码更加松耦合、可测试,并且使得组件之间的交互更加灵活和易于维护。
面向切面编程(AOP):Spring支持面向切面编程,允许开发人员将横切关注点(如日志记录、安全性、事务管理等)从核心业务逻辑中分离出来。这种分离提高了代码的模块化和可重用性。
声明式事务管理:Spring提供了声明式事务管理,允许开发人员在不编写显式事务代码的情况下实现事务控制。这简化了事务管理的代码,同时提供了更高的可读性和维护性。
集成数据访问:Spring提供了对各种数据访问技术(如JDBC、JPA、Hibernate等)的集成支持,使数据访问层的开发更加简单和灵活。
模块化:Spring框架是模块化的,允许开发人员选择和使用所需的模块,而不必导入整个框架。这种灵活性使得应用程序只使用所需的功能,减少了资源消耗。
丰富的生态系统:Spring拥有一个强大的生态系统,与许多其他流行的框架和技术(如Spring Boot、Spring Security、Spring Data等)相集成,提供了丰富的功能和工具。
测试友好:Spring的依赖注入和松耦合的特性使得对代码进行单元测试和集成测试变得更加容易和可靠。
广泛的支持和社区:Spring框架拥有庞大的用户社区和强大的支持,这意味着您可以轻松地找到解决方案、文档和社区支持。
复杂性:随着应用程序的规模增长,Spring框架的复杂性也会增加。一些复杂的配置和注解可能会使代码难以理解和维护。
依赖注入的滥用:虽然依赖注入可以提高代码的灵活性和可测试性,但滥用依赖注入可能导致过度解耦,使得代码结构变得复杂,难以理解和维护。
过度抽象:Spring框架鼓励使用接口和抽象类进行编程,以便实现松耦合。然而,过度的抽象可能会导致代码冗余和额外的开销。
过多的XML配置:早期的Spring应用程序通常使用XML配置来定义依赖和bean的关系。虽然现代的Spring应用程序可以使用更多的注解配置来代替XML,但仍然存在一些老旧的项目和遗留代码使用XML配置。
IOC,Inversion of Control,控制反转,指将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁)和对象间的依赖关系。
IoC 的一个重点就是在程序运行时,动态的向某个对象提供它所需要的其他对象,这一点是通过DI(Dependency Injection,依赖注入)来实现的,即应用程序在运行时依赖 IoC 容器来动态注入对象所需要的外部依赖。而 Spring 的 DI 具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性
将对象的创建、组装和管理的责任从应用程序代码中转移到框架或容器中。
AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架的一个重要特性,用于解决应用程序中横切关注点的处理,例如日志记录、安全性、事务管理等。AOP通过将这些横切关注点从主要业务逻辑中分离出来,使得代码更具模块化和可维护性。
AOP采用了一种不同的编程思想,它将横切关注点视为一个独立的模块,称为"切面"(Aspect)。切面是与业务逻辑无关的功能模块,它可以跨越多个对象和方法,并在特定的切入点(Join Point)上执行。切入点可以是方法调用、方法执行、异常处理等。
切面(Aspect):切面是一个模块化的横切关注点的定义,它包含了通知和切入点。切面描述了在何处以及何时应该执行哪些横切关注点。例如,一个日志记录切面可以在方法调用之前或之后打印日志。
连接点(Join Point):连接点是在应用程序执行过程中可以插入切面的点。它通常是方法的调用或方法的执行,但也可以是异常抛出等。在Spring中,连接点表示可以被切面影响的一组点,例如所有的方法调用。
通知(Advice):通知是切面在连接点上执行的具体操作。通知可以分为以下几种类型:
前置通知(Before Advice):在连接点之前执行。
后置通知(After Advice):在连接点之后执行(无论是否发生异常)。
返回通知(After Returning Advice):在连接点成功执行后执行。
异常通知(After Throwing Advice):在连接点抛出异常后执行。
环绕通知(Around Advice):在连接点之前和之后执行,可以控制连接点的执行。
切入点(Pointcut):切入点是用于匹配连接点的表达式。它定义了哪些连接点应该被切面处理。切入点表达式可以是方法名、包名、注解等。
引入(Introduction):引入是一种向现有的类添加新方法或属性的机制,它允许切面在不修改原始类的情况下,向类添加新功能。
目标对象(Target Object):目标对象是被切面所通知的对象,它是连接点的拥有者。通常,目标对象是应用程序中的一个普通Java对象。
织入(Weaving):织入是将切面应用到目标对象并创建代理对象的过程。织入可以在编译时、类加载时或运行时进行,Spring AOP采用运行时动态代理来实现织入。
日志的采集、权限控制 aop 拦截器、Mybatis mapper、Spring的事务、全局捕获异常、Rpc远程调用接口 (传递就是接口)、代理数据源、自定义注解
Spring AOP的底层原理主要是通过动态代理实现的,常用的动态代理技术有两种:
Spring AOP中的Advisor决定该对哪些类的哪些方法进行AOP代理。在应用代理时,如果目标类实现了接口,默认会采用JDK动态代理;如果目标类没有实现接口,则使用CGLib。
工作流程是:
(1)前置通知(Before Advice):在连接点(Join point)之前执行的通知。
(2)后置通知(After Advice):当连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
(3)环绕通知(Around Advice):包围一个连接点的通知,这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
(4)返回后通知(AfterReturning Advice):在连接点正常完成后执行的通知(如果连接点抛出异常,则不执行)
(5)抛出异常后通知(AfterThrowing advice):在方法抛出异常退出时执行的通知
加载配置文件: Spring容器在启动时首先需要加载配置文件,这些配置文件可以是XML格式的,也可以是基于Java配置的类。
解析配置文件: 加载配置文件后,Spring容器会对配置文件进行解析,识别和读取其中的Bean定义、依赖关系、AOP配置等信息。
创建Bean实例: 在解析配置文件的过程中,Spring容器会根据配置信息实例化每个Bean,并将它们注册到容器中。
处理Bean依赖: Spring容器会根据Bean定义中的依赖关系,自动处理Bean之间的依赖关系,确保Bean的依赖在其他Bean实例化之前已经被满足。
应用后置处理器: 在Bean实例化和依赖处理之后,Spring容器会应用注册的后置处理器,可以通过后置处理器来自定义Bean的初始化逻辑或修改Bean的属性。
完成Bean初始化: 容器对每个Bean进行初始化,执行初始化方法(如果有定义的话),并设置属性值。
完成容器启动: 所有的Bean都初始化完成后,Spring容器启动完成,此时所有的Bean都已经可用,可以通过容器获取并使用它们。
Spring Bean的生命周期涉及以下阶段:
初始化 - 当容器实例化Bean时,会调用Bean的构造方法或静态工厂方法来创建Bean。
属性注入 - 然后容器会根据配置为Bean注入依赖的其他Bean。这通常是通过setter方法或构造方法参数来实现的。
初始化后处理 - Bean实现了InitializingBean接口,会调用afterPropertiesSet()方法;或者Bean配置了init-method,会调用指定的方法。这允许Bean执行自定义的初始化任务。
使用 - 当Bean准备就绪后,可以从容器中获取并使用Bean。Bean就处于可用及准备服务状态。
销毁前处理 - 如果Bean实现了DisposableBean接口,会调用destroy()方法;或者配置了destroy-method,会调用指定的方法。这允许Bean执行关闭任务。
销毁 - 当容器关闭时,会销毁容器中的所有单例Bean。或当Bean的引用计数为0时,容器也可以选择销毁Bean。容器会调用上一步的销毁前处理方法。
垃圾回收 - 当Bean最终被从内存中删除时,Bean的生命就结束了。容器不再控制Bean的生命周期。
(1)singleton:默认作用域,单例bean,每个容器中只有一个bean的实例。
(2)prototype:为每一个bean请求创建一个实例。
(3)request:为每一个request请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,同一个session会话共享一个实例,不同会话使用不同的实例。
(5)global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会话共享的存储变量的话,那么这全局变量需要存储在global-session中。
Spring框架中的Bean默认情况下是单例的,即每个Bean在容器中只有一个实例。因此,如果Bean的作用域是单例,那么它是线程不安全的,因为多个线程可以并发地访问和修改同一个Bean实例。
如果线程安全是一个重要的考虑因素,可以考虑以下几种方式来处理:
避免在Bean中存储状态: 尽量避免在Bean中存储状态,使其成为无状态的组件。将状态保存在其他地方,如数据库、缓存等。
使用原型作用域: Spring提供了原型(prototype)作用域,它会为每次Bean的请求创建一个新的实例。如果需要线程安全的Bean,可以考虑使用原型作用域,确保每个线程都拥有一个独立的Bean实例。
使用ThreadLocal: 如果某些Bean需要在多线程环境下保持线程安全,但又希望它们是单例的,可以考虑使用ThreadLocal来保持线程间的隔离。
使用锁: 如果必须在Bean中存储状态,并且不希望使用原型作用域或ThreadLocal,可以在Bean中使用锁来保护共享状态,确保线程安全。
构造器注入(Constructor-based Dependency Injection)
在bean的构造函数中注入依赖。它会在容器创建bean时传入所需的依赖。
setter注入(Setter-based Dependency Injection)
在bean的setter方法中注入依赖。它会在调用setter方法后将依赖设置到bean中。
接口注入(Interface-based Dependency Injection)
让bean实现一个接口,该接口包含设置依赖的方法。容器会通过接口调用这些方法注入依赖。
属性注入(Attribute-based Dependency Injection)
可以通过bean定义中的@Autowired等注解让容器直接在属性上注入依赖。
方法注入(Method Injection)
在bean的某个方法中注入依赖,和setter类似,只是注入的方法可以是任意名称。
注解(@Autowired、@Resource等)
可以在属性、 setter方法、构造函数等上使用注解明确指定由容器注入依赖。
XML配置文件
可以在XML中明确指定bean的属性和构造函数参数进行注入。
Spring事务的实现方式和实现原理涉及到编程式事务管理和声明式事务管理,这里将详细说明这两种方式以及它们的实现原理:
1. 编程式事务管理:
编程式事务管理是通过编写代码来管理事务的开始、提交或回滚。在这种方式下,开发者需要在业务代码中显式调用事务管理的API来控制事务的行为。典型的API包括PlatformTransactionManager
接口和TransactionDefinition
接口。
2. 声明式事务管理:
声明式事务管理是将事务管理的逻辑从业务代码中分离出来,通过配置来实现。开发者可以通过XML配置或注解来定义事务的传播行为、隔离级别等属性。这样,业务代码无需关心事务管理,使得代码更加简洁和易于维护。
注解配置方式: 在配置类上添加@EnableTransactionManagement
注解开启事务管理功能,然后在需要事务管理的方法上添加@Transactional
注解来指定事务的属性。
事务的实现原理:
Spring事务管理的实现原理是通过AOP来实现的。在声明式事务管理中,Spring利用AOP在方法执行的前后织入事务逻辑。当调用带有事务注解的方法时,Spring的事务拦截器会对该方法进行拦截。在方法执行前,会开启一个事务;在方法执行后,根据方法的执行情况决定是提交事务还是回滚事务。这样,业务代码只需要关注业务逻辑,而不需要关心事务的管理。
Spring使用代理模式来实现AOP,具体来说,Spring使用了动态代理来织入事务逻辑。在实现阶段,Spring会生成一个代理对象,当调用被代理的方法时,代理对象会拦截方法的调用,并根据事务配置来执行相应的事务管理逻辑。
(1)工厂模式:Spring使用工厂模式,通过BeanFactory和ApplicationContext来创建对象
(2)单例模式:Bean默认为单例模式
(3)策略模式:例如Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略
(4)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术
(5)模板方法:可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中,用来解决代码重复的问题。比如RestTemplate, JmsTemplate, JpaTemplate
(6)适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,Spring MVC中也是用到了适配器模式适配Controller
(7)观察者模式:Spring事件驱动模型就是观察者模式的一个经典应用。
(8)桥接模式:可以根据客户的需求能够动态切换不同的数据源。比如我们的项目需要连接多个数据库,客户在每次访问中根据需要会去访问不同的数据库
@Aspect,@Before,@After,@Around,@Pointcut - 用于切面编程(AOP)。
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
1.TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
2.TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前线程存在事务,则把当前事务挂起。
3.TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
4.TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
5.TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
6.TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
7.TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
分离关注点: AOP允许将不同关注点的代码分离出来,从而提高了代码的可维护性和可读性。核心业务逻辑与横切关注点分离,使代码更具组织性。
代码重用: AOP允许将通用的横切关注点应用于多个模块和组件中,避免了代码重复。例如,事务管理是一个通用关注点,可以在多个业务方法中重用。
集中管理: AOP使得可以集中管理横切关注点的逻辑,而不必将它们分散到各个业务方法中。这样可以在需要时进行集中的修改和管理,提高了可维护性。
模块化: AOP可以将关注点切割成独立的模块,使得关注点的逻辑更加模块化和可测试。
降低耦合度: AOP可以减少应用程序中的硬编码,从而降低了模块之间的耦合度。核心业务逻辑与横切关注点的解耦有助于保持代码的灵活性和可扩展性。
提高可扩展性: AOP使得可以在不修改核心业务逻辑的情况下,添加或修改横切关注点。这样在应对新的需求或变化时更加灵活。
逻辑集中: AOP使得关注点的逻辑可以在一个地方集中处理,而不必在多个地方重复编写类似的代码。
代码简化: AOP可以使核心业务逻辑更加干净简洁,因为不需要携带大量与横切关注点相关的代码。
可插拔的增强: AOP可以通过简单地配置来添加或删除横切关注点的增强,而不需要修改核心代码。这使得增强变得更加可插拔和灵活。
Spring MVC是Spring框架的一个重要模块,它是一个基于Java的Web框架,用于构建Web应用程序。它提供了一个MVC(Model-View-Controller)的架构模式,用于将应用程序的不同方面分离,使得开发者可以更好地组织和管理Web应用的逻辑。
简单来说,Spring MVC提供了以下几个核心组件:
控制器(Controller): 控制器是Spring MVC的核心组件之一,它接收来自客户端的请求,并根据请求的内容来处理和调度请求。在Spring MVC中,控制器可以通过注解或实现Controller接口来定义,并处理来自用户的HTTP请求。
模型(Model): 模型代表应用程序的数据和业务逻辑。在Spring MVC中,模型可以是POJO(Plain Old Java Object)、实体类、数据传输对象(DTO)等。控制器可以将模型数据传递给视图进行展示。
视图(View): 视图是用户界面的呈现,用于展示数据给用户。Spring MVC支持多种视图技术,包括JSP、Thymeleaf、FreeMarker等。视图负责展示模型数据给用户,并将用户的输入传递给控制器进行处理。
Spring MVC的工作流程如下:
客户端发送HTTP请求到DispatcherServlet。
DispatcherServlet根据请求的URL调用相应的控制器。
控制器处理请求,并根据需要查询数据库、调用服务或执行其他业务逻辑。
控制器将模型数据传递给视图,并返回视图名称。
DispatcherServlet选择适当的视图,并将模型数据传递给视图。
视图将模型数据渲染为HTML,并通过HTTP响应返回给客户端。
Spring MVC具有以下优点:
低耦合:MVC模式使得数据、视图和控制器的逻辑分离,增强了代码的可维护性和可测试性。
灵活性:支持多种视图技术,可以根据项目需求灵活选择视图。
高扩展性:Spring MVC与Spring框架无缝集成,可以轻松扩展和集成其他Spring功能,如Spring Security、Spring Data等。
易于使用:使用注解和默认配置,减少了大量的XML配置,简化了开发流程。
Spring MVC的缺点:
1、用户向服务器发送请求,请求会先达到 SpringMVC 前端控制器 DispatcherServlet ;
2、DispatcherServlet 根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象对应的拦截器),最后以 HandlerExecutionChain 执行链对象的形式返回
3、DispatcherServlet 根据获得的 Handler,获取对应的 HandlerAdapter;
5、获取到 HandlerAdapter,将开始执行拦截器的 preHandler(…)方法;
6、提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)方法,处理请求,在填充 Handler 的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:
HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的类型信息
数据转换:对请求消息进行数据转换。如 String 转换成 Integer、Double 等
数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等
数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 Error 中
7、Handler 方法执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。
8、开始执行拦截器的 postHandle(...)方
9、根据返回的 ModelAndView(此时会判断是否存在异常:如果存在异常,则执行 HandlerExceptionResolver 进行异常处理)选择一个适合的 ViewResolver 进行视图解析,根据 Model 和 View,来渲染视图
10、渲染视图完毕执行拦截器的 afterCompletion(…)方法
11、将渲染结果返回给客户端
(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
直接在方法的形参中声明request,SpringMvc就自动把request对象传入。
可以在@RequestMapping注解里面加上method=RequestMethod.GET。
1、作用范围不同
2、关注点不同
3、使用范围不同
4、对象不同
Spring Boot是由Pivotal团队提供的一套开源框架,可以简化spring应用的创建及部署。它提供了丰富的Spring模块化支持,可以帮助开发者更轻松快捷地构建出企业级应用。Spring Boot通过自动配置功能,降低了复杂性,同时支持基于JVM的多种开源框架,可以缩短开发时间,使开发更加简单和高效。
简化配置:Spring Boot采用约定优于配置的原则,提供了默认配置和自动化配置,减少了开发人员需要手动配置的工作量。它可以根据应用程序的依赖和环境自动配置Spring框架和第三方库,使得开发者可以更专注于业务逻辑的开发。
快速启动和开发:Spring Boot提供了一个快速启动的起点,可以快速创建一个可执行的Spring应用程序。它提供了内嵌的Servlet容器,不需要独立安装和配置额外的服务器。同时,Spring Boot提供了一组开发工具和命令行界面,可以加快开发过程,提高开发效率。
微服务支持:Spring Boot与Spring Cloud框架的集成使得构建和管理微服务变得更加容易。它提供了服务发现、负载均衡、断路器模式和配置中心等功能,简化了微服务架构的开发和部署。
自动化依赖管理:Spring Boot引入了Starter依赖,通过简单地引入一个或多个Starter依赖,可以快速集成常用的功能模块,如数据库访问、安全性、日志记录等。这些Starter依赖会自动处理依赖关系和版本兼容性,简化了依赖管理的过程。
易于测试:Spring Boot提供了良好的测试支持。它支持单元测试、集成测试和端到端测试,并提供了一组用于测试Spring应用程序的工具和注解。开发者可以使用这些工具来编写可靠的自动化测试,确保应用程序的质量和稳定性。
社区支持和生态系统:Spring Boot拥有一个庞大的开发者社区和活跃的维护团队。这意味着你可以很容易地获取到相关的文档、教程和解决方案。此外,Spring Boot与其他Spring项目(如Spring MVC、Spring Data等)和第三方库(如Hibernate、Redis等)紧密集成,形成了一个强大的生态系统。
Spring Boot的starters是一组方便依赖关系描述的预定义模块。主要作用是进行自动依赖管理,简化Maven配置。
常用的Spring Boot starter包括:
Spring Boot预定义了以spring-boot-starter-xxx命名的许多starter POM,这些starter包含了指定场景所需的依赖,省去了手动配置的工作,从而简化了Maven配置,代表了Spring Boot的自动配置思想。
Spring Boot的核心注解是@SpringBootApplication。该注解是一个组合注解,包含了多个其他注解,主要包括:
@SpringBootConfiguration:标识该类为Spring Boot的配置类,相当于传统Spring框架中的@Configuration注解。
@EnableAutoConfiguration:开启自动配置功能,根据类路径上的依赖和配置,自动配置Spring应用程序所需的各种组件。
@ComponentScan:启用组件扫描,自动扫描并注册标注了@Component及其衍生注解的组件(如@Controller、@Service、@Repository等)。
JavaConfig是一种用于配置Java应用程序的替代方式,它基于Java代码而不是XML文件。在传统的Java开发中,通常使用XML配置文件来定义应用程序的配置信息,如依赖注入、AOP切面、Bean定义等。JavaConfig的出现是为了简化和集中配置的过程,并提供更直观、类型安全的配置方式。
JavaConfig通过使用Java语言本身的特性,将配置信息直接写入Java类中,以注解或方法的形式来表示。通过编写配置类,开发者可以将一些特定的配置细节集中在一起,而不需要散落在多个XML文件中。这种方式使得配置更易于维护、理解和版本控制。
使用JavaConfig的主要好处包括:
类型安全:JavaConfig使用Java代码来表示配置信息,由编译器进行类型检查,减少了配置错误的可能性。
集中化配置:JavaConfig将配置信息集中在一个或多个Java类中,使得配置更加可控和易于维护。
可读性和可维护性:JavaConfig使用Java语言,具有良好的可读性和可维护性,开发者可以直接阅读和修改配置代码。
便于重构和IDE支持:使用JavaConfig可以方便地进行重构操作,IDE(集成开发环境)可以提供智能的代码补全、语法检查和重构支持。
Spring Boot通过@EnableAutoConfiguration注解开启自动配置,对jar包下的spring.factories文件进行扫描,这个文件中包含了可以进行自动配置的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化,注册到Spring容器中。
Spring Boot自动配置的核心原理主要包含以下四点:
1、Spring Boot启动时会加载大量自动配置类
Spring Boot会根据classpath中的jar包依赖为项目进行自动配置,这些自动配置类以AutoConfigure结尾,在spring-boot-autoconfigure jar包中。
2、@Conditional注解控制自动配置的生效
这些自动配置类中使用了@Conditional注解来控制配置是否生效,只有在条件匹配的情况下才会应用自动配置。
3、@EnableAutoConfiguration注解启动自动配置
在SpringBootApplication注解中包含了@EnableAutoConfiguration注解,该注解会根据classpath和定义的excludes来选择哪些配置可以生效。
4、外部化配置可覆盖自动配置
Spring Boot提供了application.properties和application.yml文件来对框架自动配置进行自定义。
通过定义外部配置,可以很容易地覆盖自动配置的默认值,实现快速修改。
默认配置:Spring Boot提供了一组默认配置,这些配置包含在框架本身中,并在没有任何其他配置的情况下自动生效。这些默认配置是预先定义好的,可以根据Spring Boot的自动配置机制自动加载。例如,Spring Boot会自动配置内嵌的Servlet容器、数据库连接池等。
外部配置:Spring Boot支持从多个外部配置源加载配置属性。常见的外部配置源包括application.properties或application.yml文件、环境变量、命令行参数等。这些配置源可以覆盖默认配置或添加新的配置属性。外部配置具有较高的优先级,因此它们可以用于根据环境或部署需求来自定义应用程序的配置。
项目配置:在Spring Boot应用程序中,开发者可以通过编写自己的配置类或使用注解来定义项目特定的配置。这些配置类通常使用@Configuration注解进行标注,并可以通过@PropertySource注解或@Value注解来引用外部配置属性。项目配置可以在应用程序启动时被加载和应用,它们可以覆盖外部配置源中的属性值,或者添加额外的配置。
Spring Boot的配置加载顺序是:默认配置 -> 外部配置 -> 项目配置。
使用开发工具运行:在开发过程中,可以使用集成开发环境(IDE)中的运行按钮或命令来直接运行Spring Boot应用程序。
使用命令行运行:可以使用命令行界面(如Windows的命令提示符或Linux的终端)来运行Spring Boot应用程序。进入应用程序所在的目录,使用java -jar命令来执行可执行的JAR文件。例如,java -jar myapp.jar。
使用Maven或Gradle插件运行:Spring Boot提供了Maven和Gradle插件,可以通过命令行或构建工具运行应用程序。在Maven项目中,使用mvn spring-boot:run命令;
打包成可执行的JAR文件并运行:可以使用Maven或Gradle将Spring Boot应用程序打包成可执行的JAR文件,然后通过命令行运行。通过执行java -jar命令,指定JAR文件的路径即可运行应用程序。
部署到服务器运行:将Spring Boot应用程序打包成WAR文件,并部署到支持Java Web容器的服务器(如Tomcat、Jetty等)上运行。可以将WAR文件复制到服务器的部署目录中,并启动服务器,应用程序将被自动部署并运行。
Spring:Spring是一个开源的Java应用程序框架,提供了一套全面的解决方案来开发企业级Java应用程序。它包含了许多模块和功能,如依赖注入(DI)、面向切面编程(AOP)、事务管理、数据访问等。Spring框架是一个核心的容器,通过IoC(控制反转)和依赖注入(DI)的概念来管理和组织应用程序中的组件。
Spring MVC:Spring MVC是Spring框架的一部分,是基于MVC(模型-视图-控制器)设计模式的Web应用程序框架。它提供了一个强大的基础设施来开发和管理Web应用程序。Spring MVC通过DispatcherServlet、控制器、视图解析器和模型对象等组件,将请求进行处理和响应,并实现灵活的视图呈现机制。Spring MVC提供了灵活的URL映射、请求参数绑定、验证、数据绑定等功能,使得开发Web应用程序变得更加简单和高效。
Spring Boot:Spring Boot是一个用于创建独立、可执行的Spring应用程序的开发框架。它是Spring框架的一部分,旨在简化Spring应用程序的开发和部署过程。Spring Boot通过提供默认配置、自动化配置和开发工具,减少了开发人员的样板代码量,加快了应用程序的开发速度。它还提供了内嵌的Servlet容器、与Spring Cloud的集成支持等功能,使得构建微服务架构变得更加容易。
Spring Boot的核心配置文件是application.properties或application.yml,它们是用于配置Spring Boot应用程序的主要配置文件。
跨域三种情况
(1) 协议不同,如 http 和 https;
(2) 域名不同;
(3) 端口不同。
使用 @CrossOrigin 注解实现跨域;
通过配置文件实现跨域;
通过 CorsFilter 对象实现跨域;
通过 Response 对象实现跨域;
通过实现 ResponseBodyAdvice 实现跨域。
可执行性:Spring Boot打包的jar是可执行的,可以直接通过java -jar命令运行。它包含了嵌入式的Servlet容器,可以独立运行Spring Boot应用程序,不需要外部的应用服务器。
内嵌依赖:Spring Boot打包的jar通常包含了应用程序所需的所有依赖项,这些依赖项被打包在同一个jar文件中。这使得部署和分发应用程序更加方便,不需要手动处理依赖项。
自包含性:Spring Boot打包的jar是自包含的,它包含了应用程序的所有资源文件(如配置文件、静态资源等)。这意味着你可以将整个应用程序作为一个独立的单元进行部署和交付。
版本控制:Spring Boot打包的jar通常使用Spring Boot的版本控制机制,可以简化依赖项的管理和版本选择。它会自动管理和选择与Spring Boot版本兼容的依赖项版本,避免了依赖项冲突和版本不一致的问题。
自动配置:Spring Boot打包的jar中包含了自动配置机制,它会根据应用程序的依赖和配置自动配置Spring框架和第三方库。这样,你可以更快速、方便地构建和部署Spring应用程序,不需要手动配置大量的组件和功能。
打包方式:Spring Boot打包的jar通常使用可执行的JAR打包方式(executable JAR packaging),它使用spring-boot-maven-plugin插件来生成可执行的jar文件。这种打包方式将应用程序的所有依赖项打包为一个独立的jar文件,并在MANIFEST.MF文件中指定了主类,方便直接运行。
在Spring Boot中,实现异常处理可以通过@ControllerAdvice注解和@ExceptionHandler注解来实现全局异常处理。@ControllerAdvice用于定义一个全局的异常处理类,@ExceptionHandler用于在该类中定义处理特定异常的方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。