《论语·卫灵公篇》
Dec
02
1
· Spring IOC常用注解 ·
Spring 的两大核心是 IOC(控制反转)和 AOP(面向切面编程)。
1.2、Spring IOC介绍
IOC是Inversion Of Control的简写,中文意思是控制反转。
IOC是一种程序设计思想,用于将对象的创建、初始化、销毁等操作交给Spring容器来管理。
1.3、Spring IOC常用注解
在现在SpringBoot应用开发中一般使用@ConfigurationProperties结合prefix的前缀参数将配置文件中的属性与Java类中的字段进行统一的匹配绑定。
注入的属性只有一两个就用@Value很方便,如果非常多则应该使用@ConfigurationProperties结合prefix来简化开发。
1.4、Spring Bean介绍
Spring bean的生命周期有:实例化、属性注入、初始化和销毁这四个阶段。
@Component:用于标记一个类作为Spring组件,自动注册为Spring容器中的一个bean,不能用在控制器类上。
Spring框架支持5种作用域,作用域写在@Scope注解括号里面。
Singleton:这是默认的作用域,Spring IOC容器仅存在一个Bean实例,Bean以单例方式存在,在创建容器时就同时自动创建了一个Bean对象。作用域范围是ApplicationContext中。 Prototype:每次从容器中调用Bean时,都会返回一个新的实例,即每次调用getBean时。作用域返回的是getBean方法调用直至方法结束。 Request:每次HTTP请求都会创建一个新的Bean,作用域范围是每次发起http请求直至拿到相应结果。 Session:首次http请求创建一个实例,作用域是浏览器首次访问直至浏览器关闭。 Global Session:也是每次HTTP请求都会创建一个新的Bean,但是它的范围是全局的,即在整个应用的生命周期内都存在。
@Lazy延迟初始化bean对象,需要用到bean对象时,才会创建bean对象并交给IOC容器管理。是否使用@Lazy,就看程序比较看重的是时间还是空间了。
1.5、Spring管理第三方Bean
@Configuration:用于标记一个配置类,该类可以使用Java配置的方式定义Spring容器中的bean。
@Bean:用于在配置类中定义一个bean,可以使用@Bean来指定bean的名称、依赖关系、初始化方法等。
在@Bean注解中没有指定bean的名称,所以Spring会默认使用方法名作为bean的名称。
在@Bean注解中指定bean的名称,需要注入的时候直接通过@Bean注解括号里面的名称进行注入即可。
1.6、Spring IOC两种实现方式
控制反转有两种实现方式,分别是依赖注入(Dependency Injection)和依赖查找(Dependency Lookup)。
1.6.1、DI依赖注入
@AutoWired:默认按照类型进行注入容器中的bean。是Spring框架提供的。
@Qualifier:和@AutoWired组合使用,当存在多个相同类型的bean时,可以用此注解指定具体注入哪一个bean。
登录框的图片验证码你是如何做的?
你项目中哪些地方使用到了多线程?
依赖查找的不同于依赖注入,他使用容器提供的方法,在运行时根据需要查找容器中的bean。
在Spring框架中可以通过ApplicationContext接口提供的getBean()方法来进行依赖查找。
DL依赖查找有3种查找方式:分别是根据名称、类型和名称及类型这三种方式进行查找。
贰
· Spring事务常用注解 ·
事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体,一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功,要么同时失败。
@Transactional是Spring框架提供的一个用于声明式事务管理的注解。
使用位置 :业务(service)层的方法上、类上、接口上。
作用 :将当前方法交给spring进行事务管理,方法执行前,开启事务,成功执行完毕,提交事务,出现异常,回滚事务。
可以在application.yml配置文件中开启事务管理日志,这样就可以在控制台看到和事务相关的日志信息了。
可以通过Grep Console插件对日志进行过滤筛选。
@Transational注解中常见属性分别有rollbackFor(控制异常回滚)、propagation(控制事务传播行为)和isolation(事务隔离级别)。
rollbackFor在默认情况下,只有出现RuntimeException(运行时异常)才回滚异常,如果不是运行时异常不会回滚。
如果想设置出现某种异常回滚,或者出现所有的异常都回滚,可以通过配置@Transactional的rollbackFor属性来控制出现某种异常回滚事务。
propagation事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。
propagation常用的属性就是REQUIRED和REQUIRED_NEW这两个属性。
propagation的默认传播行为的REQUIRED,A方法内部调用B方法,如果A方法存在事务,则B方法加入A方法的事务,如果A方法没有事务,则B方法按照自己的事务执行。
大部分情况下都是用REQUIRED默认的传播行为即可。
Propagation其他五种不太常用的属性:
SUPPORTS:A调用B方法时,如果A方法存在一个事务,则B方法加入该事务;否则以非事务的方式执行。 NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将当前事务挂起。 MANDATORY:A调用B方法时,A方法必须有事务,B方法加入A事务;否则B方法抛出异常。 NEVER:A调用B方法时,A方法不能有事务;否则B方法抛出异常。 NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作。
事务的隔离级别有四种,分别是读未提交、读已提交、可重复读和串行化:
TRANSACTION_READ_UNCOMMITTED:读未提交是最低的隔离级别,允许一个事务读取另一个未提交的事务的数据。可能导致脏读、不可重复读和幻读问题。 TRANSACTION_READ_COMMITTED:读已提交是指允许一个事务读取另一个已经提交的事务的数据。可以避免脏读问题,但仍可能出现不可重复读和幻读问题。 TRANSACTION_REPEATABLE_READ:可重复读能保证在同一个事务中多次读取同一数据时,结果始终一致。通过在读取时对数据加锁,避免脏读和不可重复读问题,但仍可能出现幻读问题。 TRANSACTION_SERIALIZABLE:串行化是最高的隔离级别,确保事务串行执行。通过对数据加锁,避免脏读、不可重复读和幻读问题,但可能导致性能问题。
@Transational默认的隔离级别是RANSACTION_REPEATABLE_READ。
@Transational使用在静态方法上会失效:在Spring框架中,@Transational的底层是基于AOP实现的,而AOP的底层是基于动态代理实现的。因此,如果事务被应用在一个静态方法上,事务代理将无法工作,而导致事务失效。 @Transational使用在非public修饰的方法会失效:如果事务使用在非public修饰的方法,事务代理将无法访问该方法,导致事务失效。因此,为了确保事务的有效性,需要确保事务方法是public修饰的类或者接口。 如果在事务方法中捕获了异常,Spring框架无法感知异常的存在,会导致事务失效。因此,为了确保事务的有效性,应该避免在事务方法中捕获异常,而应该让事务传递给Spring框架进行处理。 @Transational使用在final修饰的方法上会导致事务失效:如果包含事务的方法被final修饰,那么Spring框架将无法对方法进行增强。因此,如果要在Spring框架中管理事务,应该避免在方法上使用final修饰符。 当一个事务方法调用另一个事务时,如果被调用事务方法的传播行为是Propagation.REQUIRES_NEW,那么当被调用的B事务方法已经提交时,A方法出现异常,B方法的事务将无法回滚。
叁
· Spring AOP ·
连接点:JoinPoint,所有可以被AOP控制的方法都是连接点。 通知:advice,切面类中要对目标对象进行横向切入增强的代码。 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用。在通知类型的注解里面可以通过excution属性值或者@annotation注解这两种方法来定位要增强的方法。 切面:Aspect,当通知和切入点结合在一起,在类上打上@Aspect注解,就形成了一个切面。通过切面就能描述当前aop程序需要针对哪些原始方法,在什么时候执行什么样的操作。 目标对象:Target,通知所应用的对象,就是被横向切入增强的对象。
@Around :环绕通知,此注解标注的方法在目标方法前、后都执行一遍。
@Before :前置通知,此注解标注的通知方法在目标方法前被执行。
@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行。
@AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行。
@AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行。
@Around环绕通知的补充:
@Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行。
@Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值,否则原始方法执行完毕,是获取不到返回值的。
在项目开发中,我们定义了多个切面类,而多个切面类中多个切入点都匹配到同一个目标方法。此时,目标方法在运行的时候,这多个切面类当中的这些通知方法都会运行,都会执行就涉及执行顺序先后的问题。
在不同的切面类中,默认按照切面类字母排序执行:
* :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分。
.. :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数。
切入点表达式示例:
1.自定义注解
TYPE(用于类、接口或注解类型);
FIELD(用于字段);
METHOD(用于方法);
PARAMETER(用于参数);
CONSTRUCTOR(用于构造函数)。
SOURCE(仅在源代码中可用);
CLASS(编译时可用);
RUNTIME(运行时可用)。
1.需求
当访问部门管理和员工管理当中的增、删、改相关功能接口时,将操作日志记录到数据库表中,便于后期数据追踪。
肆
· Spring 框架常见的面试题 ·
Spring bean的生命周期包括实例化、属性注入、初始化和销毁四个阶段。
在实例化阶段,Spring通过构造器或反射创建bean的实例对象。
在属性注入阶段,Spring检查实例化的Bean是否存在其他依赖项,如果存在依赖项,则通过读取@AutoWired、@Setter等依赖注入的配置将属性值和依赖项注入到实例中。
在初始化阶段,如果bean实现了InitializingBean接口,Spring容器将调用afterPropertiesSet()方法;如果bean配置中声明了init-method属性,则Spring容器将调用指定的方法。这一阶段标志着bean已经准备就绪并可以供其他bean使用。
在销毁阶段,如果bean实现了DisposableBean接口,Spring容器将在关闭应用程序上下文时调用destroy()方法;如果bean配置中声明了destroy-method属性,则Spring容器将调用指定的方法。这一阶段标志着bean的生命周期结束。
总之,Spring bean的生命周期是指从创建到销毁的整个过程,这个过程包括实例化、属性注入、初始化和销毁四个阶段。在了解这个生命周期的基础上,可以更好地管理和使用Spring bean。
Spring框架通过三级缓存解决了循环依赖的问题。在Spring中,当一个Bean需要注入另一个Bean时,如果存在循环依赖,Spring会尝试使用三级缓存来解决问题。
首先,Spring会尝试从三级缓存中获取已经初始化的Bean,如果找到了合适的Bean,就会直接使用它,而不会重新初始化。
其次,如果三级缓存中没有找到合适的Bean,Spring会尝试从二级缓存中获取原始的Bean对象。如果找到了原始的Bean对象,就会使用它,并对其进行依赖注入。
最后,如果二级缓存中也没有找到原始的Bean对象,Spring会尝试从一级缓存中获取已经初始化并注入依赖的Bean对象。如果找到了这样的Bean对象,就会使用它,并对其进行依赖注入。
通过将Bean的实例化和属性注入这两个过程分离开来,Spring能够解决单循环依赖的问题。但是,对于多实例的注入,需要人工干预处理。例如,可以使用setter注入或构造函数注入等方式来避免循环依赖的问题。
总之,Spring通过三级缓存和分离实例化与属性注入的过程来解决循环依赖的问题。但是,对于多实例的注入问题,仍然需要开发人员自行处理。
伍
· 往期回顾 ·
吴灿锦
泰伯一百零一世孙,毕业于吉林财经大学。