Spring
Spring
基础
1.什么是Spring框架
Spring是一个开源的轻量级java框架,可以提高开发效率,以及系统的可维护性
Spring Framework有很多模块可以方便我们的开发。比如Spring支持IOC、还有AOP、还支持对数据库方便的访问,可以方便的支持第三方的组件,支持单元测试,支持RestFul JAVA应用程序开发
Spring 官网:**https://spring.io/**
官方文档**:** https://docs.spring.io/spring-framework/reference/core.htmlGithub 地址: https://github.com/spring-projects/spring-framework
2.Spring的核心模块有哪些
Spring5.x
Core Container
Spring 框架的核心模块,也可以说是基础模块,主要提供 IoC 依赖注入功能的支持。Spring 其他所有的功能基本都需要依赖于该模块,我们从上面那张 Spring 各个模块的依赖关系图就可以看出来。
- spring-core :Spring 框架基本的核心工具类。
- spring-beans :提供对 bean 的创建、配置和管理等功能的支持。
- spring-context :提供对国际化、事件传播、资源加载等功能的支持。
- spring-expression :提供对表达式语言(Spring Expression Language) SpEL 的支持,只依赖于 core 模块,不依赖于其他模块,可以单独使用。
AOP
- spring-aspects :该模块为与 AspectJ 的集成提供支持。
- spring-aop :提供了面向切面的编程实现。
- spring-instrument :提供了为 JVM 添加代理(agent)的功能。 具体来讲,它为 Tomcat 提供了一个织入代理,能够为 Tomcat 传递类文 件,就像这些文件是被类加载器加载的一样。没有理解也没关系,这个模块的使用场景非常有限。
Data Access/Integration
- spring-jdbc :提供了对数据库访问的抽象 JDBC。不同的数据库都有自己独立的 API 用于操作数据库,而 Java 程序只需要和 JDBC API 交互,这样就屏蔽了数据库的影响。
- spring-tx :提供对事务的支持。
- spring-orm : 提供对 Hibernate、JPA 、iBatis 等 ORM 框架的支持。
- spring-oxm :提供一个抽象层支撑 OXM(Object-to-XML-Mapping),例如:JAXB、Castor、XMLBeans、JiBX 和 XStream 等。
- spring-jms : 消息服务。自 Spring Framework 4.1 以后,它还提供了对 spring-messaging 模块的继承。
Spring Web
- spring-web :对 Web 功能的实现提供一些最基础的支持。
- spring-webmvc : 提供对 Spring MVC 的实现。
- spring-websocket : 提供了对 WebSocket 的支持,WebSocket 可以让客户端和服务端进行双向通信。
- spring-webflux :提供对 WebFlux 的支持。WebFlux 是 Spring Framework 5.0 中引入的新的响应式框架。与 Spring MVC 不同,它不需要 Servlet API,是完全异步。
Messaging
spring-messaging 是从 Spring4.0 开始新加入的一个模块,主要职责是为 Spring 框架集成一些基础的报文传送应用。
Spring Test
Spring 团队提倡测试驱动开发(TDD)。有了控制反转 (IoC)的帮助,单元测试和集成测试变得更简单。
Spring 的测试模块对 JUnit(单元测试框架)、TestNG(类似 JUnit)、Mockito(主要用来 Mock 对象)、PowerMock(解决 Mockito 的问题比如无法模拟 final, static, private 方法)等等常用的测试框架支持的都比较好。
3.Spring,SpringMVC,SpringBoot之间的关系
Spring一般是指SpringFrameWork,它是一个开源框架提供了很多模块例如Spring-Core提供了IOC、AOP的能力
SpringMVC是Spring框架的一个模块提供了快速构建MVC应用的能力
SpringBoot是一个基于Spring框架的脚手架,可以快速构建基于Spring的应用,简化了xml的文件配置,支持自动配置
IOC
4.谈谈自己对于SpringIOC的理解
IOC 就是控制反转,它思想就是转移对象依赖注入的控制权利,让Spring来管理对象,这样复杂的依赖关系就不需要手动进行维护,可以简化开发。Spring IOC实际上就可以看成一个对象工厂,需要用到对象的时候只需要从工厂中去取。一开始工厂中对象的创建是通过读取xml配置创建的并通过xml维护依赖关系,后来觉得xml配置比较麻烦,就有了SpringBoot的注解配置
5.什么是Spring的Bean
简单来说被SpringIOC容器管理的对象就是Bean
可以通过xml,注解或java配置类来告诉IOC容器我们要管理哪些对象
org.springframework.beans
和org.springframework.context
这两个包是 IoC 实现的基础,如果想要研究 IoC 相关的源码的话,可以去看看
6.将一个类声明成Bean的注解有哪些
@Component
:通用的注解,可标注任意类为Spring
组件。如果一个 Bean 不知道属于哪个层,可以使用@Component
注解标注。@Repository
: 对应持久层即 Dao 层,主要用于数据库相关操作。@Service
: 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。@Controller
: 对应 Spring MVC 控制层,主要用于接受用户请求并调用Service
层返回数据给前端页面。
7.@Component和@Bean的区别是什么
@Component
注解作用与类,@Bean
作用与方法@Component
通过类路径扫描,将Bean装配到容器当中。@Bean
的自定义能力更强,使用第三方类需要装配到Spring容器中时,只能通过@Bean
实现通过
@ComponentScan
注解来指定类扫描路径相当于xml的1
2
3
4
5
6
7
8
public class AppConfig {
public TransferService transferService() {
return new TransferServiceImpl();
}
}1
2
3<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>1
2
3
4
5
6
7
8
9
10
11
public OneService getService(status) {
case (status) {
when 1:
return new serviceImpl1();
when 2:
return new serviceImpl2();
when 3:
return new serviceImpl3();
}
}
8.注入Bean的注解有哪些
Spring内置的@Autowired
,以及JDK内置的@Resource
、@Inject
都可以用来注入Bean
Annotaion | Package | Source |
---|---|---|
@Autowired | org.springframework.bean.factory | Spring 2.5+ |
@Resource | javax.annotation | Java JSR-250 |
@Inject | javax.inject | Java JSR-330 |
9.@Autowired
与@Resource
有什么区别
@Autowired
是 Spring的内置注解,默认通过byType
进行匹配,会优先根据接口类型进行匹配。如果有多个Bean实现了相同的接口,通过bytype
进行匹配就会出现问题,Spring就不清楚到底使用哪个Bean进行注入。然后Spring会通过byName进行注入,默认是类名首字母小写。
1 | // 报错,byName 和 byType 都无法匹配到 bean |
@Resource
是JDK提供的注解,默认注入方式是byname
如果不能通过名称进行匹配,注入方式就会变成bytype
@Resource
有两个属性name 与 type
如果仅指定 name
属性则注入方式为byName
,如果仅指定type
属性则注入方式为byType
,如果同时指定name
和type
属性(不建议这么做)则注入方式为byType
+byName
。
1 | public Resource { |
1 | // 报错,byName 和 byType 都无法匹配到 bean |
总结:
- 注解来源不同 @Autowired是Spring的内置注解, @Resource是JDK提供的注解
- 默认的依赖注入方式不同 @Autowired默认是bytype进行依赖注入,@Resource默认是通过byname进行依赖注入
- 显示指定依赖注入的方式不同 当一个接口有多个实现类的情况下,@Autowired通过@Qualifier注解指定依赖注入的BeanName,@Resource通过name属性指定依赖注入的BeanName
10.Bean的作用域有哪些
Spring 中 Bean 的作用域通常有下面几种:
- singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
- prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续
getBean()
两次,得到的是不同的 Bean 实例。 - request (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。
- session (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。
- application/global-session (仅 Web 应用可用): 每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 bean 仅在当前应用启动时间内有效。
- websocket (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。
如何配置Bean的作用域
xml
1 | <bean id="..." class="..." scope="singleton"></bean> |
注解方式:
1 |
|
11.单例Bean的线程安全问题
单例Bean存在线程安全问题,当访问共享的成员变量时就会发生竞态条件
有以下解决方法:
- 尽量使用方法的局部变量,避免定义成员变量。使用局部变量可以避免线程安全问题是因为每个线程都有自己的方法栈,局部变量是存在与每个线程自己的的方法栈当中,所以不会出现多个线程同时操作同一个变量的情况
- 使用ThreadLocal成员变量,这样每个线程都能拥有自己的局部变量。可以在登陆拦截器当中使用ThreadLocal成员变量存储当前请求登陆的用户信息,在接下来使用当中直接从threadLocal当中取出当前登陆的用户
如果Bean是无状态的,Bean就是线程安全的
12.Bean的生命周期
https://www.cnblogs.com/zrtqsk/p/3735273.html
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用
set()
方法设置一些属性值。 - 如果 Bean 实现了
BeanNameAware
接口,调用setBeanName()
方法,传入 Bean 的名字。 - 如果 Bean 实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入ClassLoader
对象的实例。 - 如果 Bean 实现了
BeanFactoryAware
接口,调用setBeanFactory()
方法,传入BeanFactory
对象的实例。 - 与上面的类似,如果实现了其他
.Aware
接口,就调用相应的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessBeforeInitialization()
方法 - 如果 Bean 实现了
InitializingBean
接口,执行afterPropertiesSet()
方法。 - 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessAfterInitialization()
方法 - 当要销毁 Bean 的时候,如果 Bean 实现了
DisposableBean
接口,执行destroy()
方法。 - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
切面
13.谈一谈你对切面的理解
AOP(Aspect-Oriented Programming)就是面向切面编程,可以将业务无关的代码封装起来,例如日志、事务处理、权限处理的代码封装起来,减少系统重复代码,降低系统耦合度,有利于未来的扩展性和可维护性。
SpringAOP是基于动态代理的,如果实现了接口就会使用JDK Proxy来创建代理对象,如果没有实现接口就是用cglib生成被代理对象的子类来作为代理
术语 | 含义 |
---|---|
目标(Target) | 被通知的对象 |
代理(Proxy) | 向目标对象应用通知之后创建的代理对象 |
连接点(JoinPoint) | 目标对象的所属类中,定义的所有方法均为连接点 |
切入点(Pointcut) | 被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点) |
通知(Advice) | 增强的逻辑 / 代码,也即拦截到目标对象的连接点之后要做的事情 |
切面(Aspect) | 切入点(Pointcut)+通知(Advice) |
Weaving(织入) | 将通知应用到目标对象,进而生成代理对象的过程动作 |
14.Spring AOP 与AspectJ AOP有什么区别
Spring AOP 和 AspectJ AOP 是两种不同的 AOP 实现方式,它们在使用上有一些区别,尽管都是用于在应用程序中处理交叉关注点的。
- 织入时机:
- Spring AOP:织入发生在运行时(runtime)。Spring AOP 使用代理对象包装目标对象,以便在方法调用前后添加通知。
- AspectJ AOP:织入可以发生在编译时(compile-time)、加载时(load-time)或运行时(runtime)。这意味着 AspectJ 提供了更广泛的织入时机选择。
- 语法和功能:
- Spring AOP:使用纯粹的 Java 注解或 XML 配置来定义切面和通知。Spring AOP 对 AspectJ 的功能进行了一定程度的限制,主要关注于方法级别的切面。
- AspectJ AOP:使用自己的专有语法和注解来定义切面和通知。AspectJ 提供了更丰富的功能,允许更细粒度的切入点定义,以及更强大的通知类型(如前置、后置、环绕、异常、最终等)。
- 性能:
- Spring AOP:由于其基于动态代理的特性,可能在大规模应用中略有性能开销。
- AspectJ AOP:由于可以在编译时进行织入,因此可能更接近原生方法调用的性能。
- 使用场景:
- Spring AOP:适用于基本的交叉关注点处理,如日志记录、事务管理等。适合于那些希望与 Spring 框架集成并且需要轻量级AOP的应用。
- AspectJ AOP:适用于更复杂的交叉关注点处理,如性能监控、复杂的权限控制等。适合于那些需要更强大和灵活的AOP功能的应用。
总结:
- Spring AOP属于运行时增强,AspectJ属于编译时增强。Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
15.AspectJ的通知类型有哪些
- Before(前置通知):目标对象的方法调用之前触发
- After (后置通知):目标对象的方法调用之后触发
- AfterReturning(返回通知):目标对象的方法调用完成,在返回结果值之后触发
- AfterThrowing(异常通知) :目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
- Around (环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
16.多个切面的顺序如何控制
1.通过使用@Order注解直接定义切面的顺序
1 | // 值越小优先级越高 |
2.实现Order接口,重写getOrder方法
1 |
|
SpringMVC
17.说说对SpringMVC的了解
组织代码的方式,Model是模型、View是视图、Controller是控制器
mvc的发展阶段
Spring MVC 时代
随着 Spring 轻量级开发框架的流行,Spring 生态圈出现了 Spring MVC 框架, Spring MVC 是当前最优秀的 MVC 框架。相比于 Struts2 , Spring MVC 使用更加简单和方便,开发效率更高,并且 Spring MVC 运行速度更快。
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。
18.SpringMVC的核心组件有什么
DispatcherServlet
:核心的中央处理器,负责接收请求、分发,并给予客户端响应。HandlerMapping
:处理器映射器,根据 uri 去匹配查找能处理的Handler
,并会将请求涉及到的拦截器和Handler
一起封装。HandlerAdapter
:处理器适配器,根据HandlerMapping
找到的Handler
,适配执行对应的Handler
;Handler
:请求处理器,处理实际请求的处理器。ViewResolver
:视图解析器,根据Handler
返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给DispatcherServlet
响应客户端
流程
- 客户端(浏览器)发送请求,
DispatcherServlet
拦截请求。 DispatcherServlet
根据请求信息调用HandlerMapping
。HandlerMapping
根据 uri 去匹配查找能处理的Handler
(也就是我们平常说的Controller
控制器) ,并会将请求涉及到的拦截器和Handler
一起封装。DispatcherServlet
调用HandlerAdapter
适配执行Handler
。Handler
完成对用户请求的处理后,会返回一个ModelAndView
对象给DispatcherServlet
,ModelAndView
顾名思义,包含了数据模型以及相应的视图的信息。Model
是返回的数据对象,View
是个逻辑上的View
。ViewResolver
会根据逻辑View
查找实际的View
。DispaterServlet
把返回的Model
传给View
(视图渲染)。- 把
View
返回给请求者(浏览器)
19.如何统一进行异常处理
使用@ControllerAdvice、@ExceptionHandler注解会给所有或者指定的 Controller
织入异常处理的逻辑(AOP),当 Controller
中的方法抛出异常的时候,由被@ExceptionHandler
注解修饰的方法进行处理。
1 |
|
ExceptionHandlerMethodResolver
中 getMappedMethod
方法决定了异常具体被哪个被 @ExceptionHandler
注解修饰的方法处理异常。
1 | private final Map<Class<? extends Throwable>, Method> mappedMethods = new HashMap<>(16); |
从源代码看出: getMappedMethod()
会首先找到可以匹配处理异常的所有方法信息,然后对其进行从小到大的排序,最后取最小的那一个匹配的方法(即匹配度最高的那个)。
20.Spring框架中用到了哪些设计模式
- 工厂设计模式 : Spring 使用工厂模式通过
BeanFactory
、ApplicationContext
创建 bean 对象。 - 代理设计模式 : Spring AOP 功能的实现。
- 单例设计模式 : Spring 中的 Bean 默认都是单例的。
- 模板方法模式 : Spring 中
jdbcTemplate
、hibernateTemplate
等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。 - 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式 : Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配
Controller
Spring事务
21.Spring管理事务的方式有哪几种?
- 编程式事务 在代码中硬编码使用,通过TransactionTemplate或TransactionManager手动管理事务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private TransactionTemplate transactionTemplate;
public void testTransaction() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
// .... 业务代码
} catch (Exception e){
//回滚
transactionStatus.setRollbackOnly();
}
}
});
}1
2
3
4
5
6
7
8
9
10
11
12
13
private PlatformTransactionManager transactionManager;
public void testTransaction() {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
// .... 业务代码
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
}
} - 声明式事务 在XML中进行配置,或者基于注解使用
1
2
3
4
5
6
7
8
public void aMethod {
//do something
B b = new B();
C c = new C();
b.bMethod();
c.cMethod();
}
22.Spring事务中有哪几种事务传播行为
TransactionDefinition.PROPAGATION_REQUIRED
默认的事务传播行为,如果当前存在事务则加入该事务,否则开启一个事务TransactionDefinition.PROPAGATION_REQUIRES_NEW
如果当前存在事务则开启一个新的事务,新事务回滚,外部事务也回滚;外部事务回滚新事务不回滚。也就是开启的事务相互独立互不干扰TransactionDefinition.PROPAGATION_NESTED
如果当前存在事务则开启一个嵌套事务,嵌套事务回滚,不影响外部事务回滚,外部事务回滚则嵌套事务回滚。 如果当前不存在事务,则创建一个事务TransactionDefinition.PROPAGATION_MANDATORY
如果当前存在事务则加入该事务,如果不存在事务则抛出异常TransactionDefinition.PROPAGATION_SUPPORTS
: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。TransactionDefinition.PROPAGATION_NOT_SUPPORTED
: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。外部事务挂起,非事务运行的方法在一个隔离环境中,不会影响事务TransactionDefinition.PROPAGATION_NEVER
: 以非事务方式运行,如果当前存在事务,则抛出异常。
23.Spring事务中的隔离级别有哪几种
TransactionDefinition.ISOLATION_DEFAULT
默认隔离级别与数据库保持一致,MYSQL默认的事务隔离级别是REPEATABLE_READ
,Oracle是READ_COMMITED
TransactionDefinition.ISOLATION_READ_UNCOMMITTED
最低的隔离级别,一个事务可以读取另外一个事务未提交的数据,会有脏读、幻读、不可重复读的问题TransactionDefinition.ISOLATION_READ_COMMITTED
可以阻止脏读,但是还是有可能发生幻读和不可重复读TransactionDefinition.ISOLATION_REPEATABLE_READ
在一个事务中对同一行的数据的多次读取都是一致的,可以避免脏读、不可重复读,但是还是有可能发生幻读TransactionDefinition.ISOLATION_SERIALIZABLE
最高的隔离级别,事务按顺序依次执行,事务之间完全隔离,可以避免脏读、幻读、不可重复读,但是会影响性能
24.@Transational(rollbackFor = Exception.class)
这个注解就是指定触发回滚的异常,如果这个方法发生了Exception.class及其子类的异常事务就会回滚。
Exception.class异常可以分为已检查异常和未检查异常@Transational默认只会在发生未检查异常的时回滚,如果通过rollbackFor参数指定了异常类型,只有发生该异常类型及其子类的异常时才会触发事务回滚
Spring data JPA
Spring Data JPA是Spring框架的一个子项目,它简化了使用JPA(Java Persistence API)进行数据库访问的开发过程。它提供了一种更简洁和高级的方式来与数据库交互,减少了重复性的代码,并提供了一些常见的数据库操作功能。
以下是Spring Data JPA的主要特点和用法:
- 自动实现CRUD操作:Spring Data JPA自动为实体类生成CRUD(Create、Read、Update、Delete)操作的实现,你只需要定义相关的接口方法,无需手动编写SQL语句。
- 查询方法的自动生成:除了CRUD操作,Spring Data JPA还可以根据方法的命名规则自动生成查询方法。通过方法名中的关键字(如findBy、deleteBy等),可以快速定义查询条件,减少手动编写查询语句的工作量。
- 分页和排序支持:Spring Data JPA提供了对分页和排序的支持,使得分页查询和结果排序变得简单。
- 支持自定义查询:除了自动生成的查询方法,你还可以使用@Query注解来编写自定义的JPQL(Java Persistence Query Language)查询语句。
- 事务管理:Spring Data JPA与Spring框架无缝集成,可以利用Spring的事务管理机制来管理数据库事务。
- 集成各种数据源:Spring Data JPA可以与不同类型的数据源集成,包括关系型数据库(如MySQL、PostgreSQL、Oracle等)和非关系型数据库(如MongoDB、Cassandra等)。
- Repository接口:Spring Data JPA的核心是Repository接口,你可以通过继承Repository接口来使用自动实现的CRUD操作和查询方法。
- 扩展性:如果需要更高级的数据库操作,你还可以自定义Repository接口,通过继承Repository接口并添加自定义方法来实现。
使用示例:
当使用Spring Data JPA时,首先需要创建一个实体类,然后定义一个继承自JpaRepository
的Repository接口,以利用Spring Data JPA的自动实现功能。以下是一个简单的示例,演示如何使用Spring Data JPA来执行基本的CRUD操作。
假设你有一个简单的User
实体类,用于表示用户信息:
1 |
|
然后,你可以创建一个继承自JpaRepository
的UserRepository
接口,它将继承自动实现的CRUD操作:
1 | public interface UserRepository extends JpaRepository<User, Long> { |
现在,可以在Spring应用程序中使用UserRepository
来执行数据库操作。例如,在一个Spring Boot应用程序中,可以编写一个简单的示例:
1 |
|
在这个示例中,我们通过userRepository
执行了创建、保存、查询、删除等操作,所有的CRUD操作都由Spring Data JPA自动实现。这只是一个简单的示例,实际中可以根据需求自定义更复杂的查询方法。
需要注意,为了使用Spring Data JPA,你需要在项目的依赖中添加适当的Spring Data JPA库以及数据库驱动库。这个示例假设你已经配置了数据库连接和实体扫描等必要的配置。
25.如何使用JPA在数据库中非持久化一个字段
1 |
|
如果想让 secret这个字段不被持久化,可以采用下面的方法
1 | static String transient1; // not persistent because of static |
26.JPA的审计功能
JPA的审计功能是帮助记录数据库的操作的具体行为,比如数据的创建时间、更新时间、创建人、修改人、
1 |
|
@CreatedDate
: 表示该字段为创建时间字段,在这个实体被 insert 的时候,会设置值@CreatedBy
:表示该字段为创建人,在这个实体被 insert 的时候,会设置值@LastModifiedDate
、@LastModifiedBy
同理。
27.实体之间的关联关系的注解有哪些
@OneToOne
: 一对一。@ManyToMany
:多对多。@OneToMany
: 一对多。@ManyToOne
:多对一。
利用 @ManyToOne
和 @OneToMany
也可以表达多对多的关联关系。
Spring Security
28.如何对密码进行加密
Spring Security 提供了多种加密算法的实现,开箱即用,非常方便。这些加密算法实现类的父类是 PasswordEncoder
,如果你想要自己实现一个加密算法的话,也需要继承 PasswordEncoder
。
PasswordEncoder
接口一共也就 3 个必须实现的方法。
1 | public interface PasswordEncoder { |
官方推荐使用基于 bcrypt 强哈希函数的加密算法实现类。