【Java八股文总结】之Spring

news2024/10/5 12:24:19

文章目录

  • Spring
    • 一、Spring介绍
      • 1、Spring是什么?特性?
      • 2、Spring有哪些模块?
      • 3、Spring中的设计模式?
    • 二、IOC
      • 1、基本概念
      • 2、什么是IOC?什么是DI?
        • Q:为什么要使用 IOC 呢?
      • 3、Spring IOC的实现机制?
      • 4、BeanFactory和ApplicationContext?
      • 5、Spring容器启动时做些什么?
      • 6、Spring容器IOC的生命周期
      • 7、Spring Bean的生命周期?
      • 8、依赖注入的方法有?
      • 9、Spring的自动装配方式?
        • 什么是自动装配?
        • Spring提供了哪几种自动装配类型?
      • 10、Spring中bean的作用域有?
      • 11、Spring中的单例bean会存在线程安全问题么?
        • Q:单例 Bean 线程安全问题怎么解决呢?
        • Q:Spring中bean创建完成后执行指定代码有哪几种方式?
      • 12、循环依赖?
      • 12、如何解决循环依赖问题?
        • Q:为什么要用三级缓存?二级缓存行不行?
      • 13、@Autowired的实现原理?
      • 14、bean实例化的4种方式?
      • 15、创建容器的方式
      • 16、获取bean的方式
    • 三、AOP
      • 1、什么是AOP?
      • 2、AOP的核心概念
      • 3、AOP的环绕方式有?
      • 4、AOP的使用?
      • 5、Spring代理模式有?
      • 6、JDK动态代理和CGLIB动态代理的区别?
      • 7、Spring AOP 和 AspectJ AOP 区别?
      • 8、面向切面编程和面向对象编程的区别?
        • 1、面向过程(POP)和面向对象(OOP)的区别:
        • 2、面向对象(OOP)和面向切面(AOP)的区别:
    • 三、Spring事务
      • 1、Spring事务的种类?
      • 2、声明式事务实现原理
      • 3、声明式事务什么时候失效?
      • 4、Spring事务隔离级别?
      • 5、Spring事务传播机制?
    • 四、Spring注解
        • 1、Web
        • 2、容器
        • 3、AOP
        • 4、事务
        • Q:@Resource 和 @Autowired 的区别
        • Q:@bean 和 @Component 的区别
        • Q:为什么有了@Component,还需要@Bean?

Spring

在这里插入图片描述

一、Spring介绍

1、Spring是什么?特性?

Spring 是一个轻量级、非入侵式的 控制反转 (IoC) 和 面向切面 (AOP) 的框架。
在这里插入图片描述

  • IOC 和 DI 的支持
    Spring 的核心就是容器,可以维护所有对象的创建和依赖关系,Spring 工厂用于生成 Bean,并且管理 Bean 的生命周期,实现 高内聚低耦合 的设计理念。
  • AOP 编程的支持
    Spring 提供了面向切面编程,可以方便的实现对程序进行 权限拦截、运行监控 等切面功能。
  • 声明式事务的支持
    支持通过配置就能完成对事务的管理,而不需要通过硬编码的方式,以前重复的一些事务提交、回滚的JDBC代码,都可以不用自己写了。
  • 快捷测试的支持
    Spring 对 Junit 提供支持,可以通过注解快捷地测试 Spring 程序。
  • 快速集成功能
    方便集成各种优秀框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持。
  • 复杂 API 模板封装
    Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了模板化的封装,这些封装 API 的提供使得应用难度大大降低。

2、Spring有哪些模块?

  • Spring CoreSpring核心容器,它是框架最基础的部分,提供IOC和依赖注入DI特性。
  • Spring ContextSpring上下文容器,它是BeanFactory功能加强的一个子接口。
  • Spring Web:它提供Web应用开发的支持。
  • Spring MVC:它针对Web应用中MVC思想的实现。
  • Spring DAO:Data Access Object,是用于 访问数据的对象 。提供对JDBC抽象层,简化了JDBC编码,同时,编码更具有健壮性。
  • Spring ORM:它支持用于流行的ORM框架的整合,比如:Spring + Hibernate、Spring + MyBatis、Spring + JDO 的整合等。
  • Spring AOP:即 面向切面编程,它提供了与AOP联盟兼容的编程实现。

3、Spring中的设计模式?

在这里插入图片描述

  • 工厂模式:Spring 容器本质是一个大工厂,使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
  • 代理模式:Spring AOP 功能就是通过代理模式来实现的,分为动态代理和静态代理。
  • 单例模式:Spring 中的 Bean 默认都是单例的,这样有利于容器对 Bean 的管理。
  • 模板模式:Spring 中 JdbcTemplate、RestTemplate 等以 Template 结尾的对数据库、网络等等进行操作的模板类,就使用到了模板模式。
  • 观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用。
  • 适配器模式:Spring ==AOP 的增强或通知 (Advice) ==使用到了适配器模式、Spring MVC 中也是用到了适配器模式适配 Controller。
  • 策略模式:Spring 中有一个 Resource 接口,它的不同实现类,会根据不同的策略去访问资源。

二、IOC

1、基本概念

IoC(Inversion of Control)控制反转: 对象的创建控制权由程序转移到外部,这种思想称之为控制反转(目的:解耦)。
IoC容器:“外部”创建对象的容器。
Bean: IoC容器中创建或管理的对象。
DI(Dependency Injection)依赖注入: 在容器中建立bean与bean之间的依赖关系的整个过程,称之为依赖注入。
自动装配: Ioc容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。
AOP(Aspect Oriented Programming): 面向切面编程,用来功能增强。
连接点(JoinPoint): 方法执行的任意位置。
切入点(PointCut): 匹配连接点的式子。
通知(Advice): 切入点处执行的操作。
通知类: 定义通知的类;
切面(Aspect): 描述通知与切入点的对应关系。

2、什么是IOC?什么是DI?

Java 是面向对象的编程语言,一个个实例对象相互合作组成了业务逻辑,原来,我们都是在代码里创建对象和对象的依赖。
所谓的 IOC(控制反转): 就是==由容器来负责控制对象的生命周期和对象间的关系。==以前是我们想要什么,就自己创建什么,现在是我们需要什么,容器就给我们送来什么(将对象的创建控制权由程序转移到外部,这种思想称为控制反转)。
也就是说,控制对象生命周期的不再是引用它的对象,而是容器。对具体对象,以前是它控制其它对象,现在所有对象都被容器控制,所以这就叫控制反转。
DI(依赖注入): 指的是容器在实例化对象的时候把它依赖的类注入给它。

Q:为什么要使用 IOC 呢?

最主要的是两个字 解耦 ,硬编码会造成对象间的过度耦合,使用IOC之后,我们可以不用关心对象间的依赖,专心开发应用就行。

3、Spring IOC的实现机制?

Spring 的 IOC 本质就是一个大工厂 ,我们想想一个工厂是怎么运行的呢?
生产产品:一个工厂最核心的功能就是生产产品。在 Spring 里,不用 Bean 自己来实例化,而是交给 Spring,应该怎么实现呢?——答案毫无疑问,反射
那么这个厂子的生产管理是怎么做的?你应该也知道——工厂模式
库存产品:工厂一般都是有库房的,用来库存产品,毕竟生产的产品不能立马就拉走。Spring 我们都知道是一个容器,这个容器里存的就是对象,不能每次来取对象,都得现场来反射创建对象,得把创建出的对象存起来。
订单处理:还有最重要的一点,工厂根据什么来提供产品呢?订单。这些订单可能五花八门,有线上签签的、有到工厂签的、还有工厂销售上门签的……最后经过处理,指导工厂的出货。
在 Spring 里,也有这样的订单,它就是我们 bean 的定义和依赖关系,可以是 xml 形式,也可以是我们最熟悉的注解形式。

4、BeanFactory和ApplicationContext?

BeanFactory 是 Spring 的“心脏”,ApplicantContext 是完整的“身躯”。
BeanFactory (Bean工厂) 是 Spring 框架的基础设施,面向 Spring 本身。
ApplicationContext (应用上下文) 建立在 BeanFactoty 基础上,面向使用 Spring 框架的开发者。

  • BeanFactory 接口
    BeanFactory 是类的通用工厂,可以 创建并管理各种类的对象
    在这里插入图片描述
    BeanFactory 接口位于类结构树的顶端,它最主要的方法就是 getBean(String var1),这个方法 从容器中返回特定名称的 Bean
    BeanFactory 的功能通过其它的接口得到了不断的扩展,比如 AbstractAutowireCapableBeanFactory 定义了将容器中的 Bean 按照某种规则(比如按名字匹配、按类型匹配等)进行自动装配的方法。

  • ApplicationContext 接口
    ApplicationContext 由 BeanFactory 派生而来,提供了更多面向实际应用的功能。可以这么说,使用 BeanFactory 就是手动档,使用 ApplicationContext 就是自动档。
    在这里插入图片描述
    ApplicationContext继承了HierachicalBeanFactory和ListableBeanFactory接口,在此基础上,还通过其他的接口扩展了BeanFactory的功能,包括:
    Bean instantiation/wiring、Bean 的实例化/串联、自动的 BeanPostProcessor 注册、自动的 BeanFactoryPostProcessor 注册、方便的 MessageSource 访问(i18n)、ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在 ApplicationContext 启动之后实例化。

5、Spring容器启动时做些什么?

Spring 的 IOC 容器工作的过程,其实可以划分为两个阶段:容器启动阶段和Bean 实例化阶段
其中容器启动阶段主要做的工作是 加载和解析配置文件 ,保存到对应的 Bean 定义中。
在这里插入图片描述

6、Spring容器IOC的生命周期

4个阶段: 刷新阶段、启动阶段、关闭阶段、停止阶段。

  • 刷新阶段是IoC生命周期中最为重要的一个阶段,里面包括 上下文准备、容器创建、各种生命周期回调以及内部Bean创建 等的操作。
    在这里插入图片描述

7、Spring Bean的生命周期?

在 Spring 中,基本容器 BeanFactory 和扩展容器 ApplicationContext 的实例化时机不太一样,BeanFactory 采用的是 延迟初始化 的方式,也就是只有在第一次getBean()的时候,才会实例化Bean;ApplicationContext 启动之后会实例化所有的 Bean 定义
Spring IOC 中 Bean 的生命周期大致分为四个阶段:实例化(Instantiation)、属性赋值(Populate)、初始化(Initialization)、销毁(Destruction)。
在这里插入图片描述
详细步骤如下:
实例化: 第 1 步,实例化一个 Bean 对象。主要包括:①读取spring配置文件相关标签封装生成BeanDefinition对象;②通过反射进行bean的实例化(此时的Bean是空对象信息)。
属性赋值: 第 2 步,为 Bean 设置相关属性和依赖。主要包括:①解析BeanDefinition的属性(beanName、beanType等)并赋值;②如果Bean对象里的属性需要引用容器内部的对象,那么需要调用aware接口的子类方法进行统一设置;③循环依赖。
初始化: 初始化阶段的步骤比较多,5、6 步是真正的初始化,第 3、4 步为在初始化前执行,第 7 步在初始化后执行,初始化完成之后,Bean 就可以被使用了。主要包括:①调用XXXAware回调方法;②调用初始化生命周期回调;③如果bean实现aop创建动态代理。
销毁: 第 8~10 步,第 8 步其实也可以算到销毁阶段,但不是真正意义上的销毁,而是先在使用前注册了销毁的相关调用接口,为了后面第 9、10 步真正销毁 Bean 时再执行相应的方法。主要包括:①在spring容器关闭的时候进行调用;②调用初始化生命周期回调。
在这里插入图片描述
在这里插入图片描述

8、依赖注入的方法有?

Spring 支持 构造方法注入、属性注入(Setter)、工厂方法注入,其中工厂方法注入,又可以分为 静态工厂方法注入和非静态工厂方法注入
在这里插入图片描述

9、Spring的自动装配方式?

什么是自动装配?

IOC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。

Spring提供了哪几种自动装配类型?

在这里插入图片描述

  • byName:根据名称进行自动匹配。
  • byType:根据类型进行自动匹配。
  • constructor:与 byType 类似, 只不过它是针对构造函数注入而言的。
  • autodetect:根据 Bean 的自省机制决定采用 byType 还是 constructor 进行自动装配,如果 Bean 提供了默认的构造函数,则采用 byType,否则采用 constructor。
    注意: 自动装配bean的优先级是最低的

10、Spring中bean的作用域有?

在这里插入图片描述

  • singleton : 在 Spring 容器仅存在一个 Bean 实例,Bean 以单实例的方式存在,是 Bean 默认的作用域。
  • prototype : 每次从容器中重新调用 Bean 时,都会返回一个新的实例。
    注意:以下三个作用域于只在 Web 应用中适用:
  • request : 每一次 HTTP 请求都会产生一个新的 Bean,该 Bean 仅在当前 HTTP Request 内有效。
  • session : 同一个 HTTP Session 共享一个 Bean,不同的 HTTP Session 使用不同的 Bean。
  • globalSession:同一个全局 Session 共享一个 Bean,只用于基于 Protlet 的 Web 应用,Spring5 中已经不存在了。

11、Spring中的单例bean会存在线程安全问题么?

Spring 中的单例 Bean不是线程安全的。
因为单例 Bean,是全局只有一个 Bean,所有线程共享。如果说单例 Bean,是一个 无状态的 ,也就是线程中的操作不会对 Bean 中的成员变量执行查询以外的操作,那么这个单例 Bean 是 线程安全 的。比如 Spring mvc 的 Controller、Service、Dao 等,这些 Bean 大多是无状态的,只关注于方法本身。
假如这个 Bean 是 有状态的 ,也就是会对 Bean 中的成员变量进行写操作,那么可能就 存在线程安全的问题

Q:单例 Bean 线程安全问题怎么解决呢?

①将 Bean 定义为多例
这样每一个线程请求过来都会创建一个新的 Bean,但是不利于容器管理 Bean。
②在 Bean 对象中尽量避免定义可变的成员变量
③将 Bean 中的 成员变量保存在 ThreadLocal 中 ★。
我们知道 ThredLocal 能保证多线程下变量的隔离,可以在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 里,这是推荐的一种方式。

Q:Spring中bean创建完成后执行指定代码有哪几种方式?

①实现ApplicationListener接口;
②实现InitializingBean接口;
③使用@PostConstruct注解。

12、循环依赖?

在这里插入图片描述
注意: Spring不支持基于构造器注入的循环依赖。
在这里插入图片描述

12、如何解决循环依赖问题?

单例bean初始化要经过3步:实例化、属性赋值、初始化。 注入就发生在属性赋值过程中,Spring通过 三级缓存解决循环依赖 问题。

  • 一级缓存:Map<String,Object> singletonObjects,单例池,用于保存实例化、属性赋值(注入)、初始化完成的 bean 实例。
  • 二级缓存:Map<String,Object> earlySingletonObjects,早期曝光对象,用于保存实例化完成的 bean 实例。
  • 三级缓存:Map<String,ObjectFactory<?>> singletonFactories,早期曝光对象工厂,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。
    在这里插入图片描述

Q:为什么要用三级缓存?二级缓存行不行?

不行,主要是为了生成代理对象。如果是没有代理的情况下,使用二级缓存解决循环依赖也是 OK 的。但是如果存在代理,三级没有问题,二级就不行了。
因为三级缓存中放的是生成具体对象的匿名内部类,获取 Object 的时候,它可以生成代理对象,也可以返回普通对象。使用三级缓存主要是为了保证不管什么时候使用的都是一个对象。
假设只有二级缓存的情况,往二级缓存中放的显示一个普通的 Bean 对象,Bean 初始化过程中,通过 BeanPostProcessor 去生成代理对象之后,覆盖掉二级缓存中的普通 Bean 对象,那么可能就导致取到的 Bean 对象不一致了。

13、@Autowired的实现原理?

实现@Autowired 的关键是: AutowiredAnnotationBeanPostProcessor
在 Bean 的初始化阶段,会通过 Bean 后置处理器BeanPostProcessor来进行一些前置和后置的处理。
实现 @Autowired 的功能,也是通过 后置处理器 来完成的。这个后置处理器就是 AutowiredAnnotationBeanPostProcessor。
Spring 在创建 bean 的过程中,最终会调用到 doCreateBean()方法,在 doCreateBean()方法中会调用 populateBean()方法,来为 bean 进行属性填充,完成自动装配等工作。
在 populateBean()方法中一共调用了两次后置处理器,第一次是为了判断是否需要属性填充,如果不需要进行属性填充,那么就会直接进行 return,如果需要进行属性填充,那么方法就会继续向下执行,后面会进行第二次后置处理器的调用,这个时候,就会调用到 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues()方法,在该方法中就会进行@Autowired 注解的解析,然后实现自动装配。
在这里插入图片描述
AutowiredAnnotationBeanPostProcessor实现了BeanPostProcessor接口,当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有@Autowired 注解时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。

14、bean实例化的4种方式?

①构造函数(默认,使用反射机制)
②静态工厂
③实例工厂
④工厂对象(实现FactoryBean接口,指定泛型)

15、创建容器的方式

①类路径加载配置文件(ClassPathXmlApplicationContext)
②文件路径加载配置文件(FileSystemXmlApplicationContext)

16、获取bean的方式

①使用bean名称
②使用bean名称,同时指定类型
③使用bean类型

三、AOP

1、什么是AOP?

AOP: 面向切面编程。简单说,就是 把一些业务逻辑中的相同的代码抽取到一个独立的模块中 ,让业务逻辑更加清爽,如常见的日志记录和数据校验等。
AOP 的核心其实就是 动态代理,如果是 实现了接口的话就会使用 JDK 动态代理,否则使用 CGLIB 代理 ,主要应用于处理一些具有横切性质的系统级服务,如日志收集、事务管理、安全检查、缓存、对象池管理等。

2、AOP的核心概念

  • 切面(Aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象。
  • 连接点(Joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
  • 切点(Pointcut):对连接点进行拦截的定位。
  • 通知(Advice):所谓通知指的就是拦截到连接点之后要执行的代码,也可以称作增强。
  • 目标对象(Target):代理的目标对象。
  • 织入(Weabing):织入是将增强添加到目标类的具体连接点上的过程。
    • 编译期织入:切面在目标类编译时被织入。
    • 类加载期织入:切面在目标类加载到 JVM 时被织入。需要特殊的类加载 器,它可以在目标类被引入应用之前增强该目标类的字节码。
    • 运行期织入:切面在应用运行的某个时刻被织入。一般情况下,在织入切 面时,AOP 容器会为目标对象动态地创建一个代理对象。Spring AOP 就 是以这种方式织入切面。
    • Spring 采用运行期织入,而 AspectJ 采用编译期织入和类加载器织入。
  • 引介(introduction):引介是一种特殊的增强,可以动态地为类添加一些属性和方法。

3、AOP的环绕方式有?

AOP一般有5种环绕方式:前置通知(@Before)、返回通知 (@AfterReturning)、异常通知(@AfterThrowing)、后置通知(@After)、环绕通知(@Around)。
在这里插入图片描述
注意: 多个切面的情况下,可以通过 @Order 指定先后顺序,数字越小,优先级越高。

4、AOP的使用?

SpringBoot 项目中,常使用 AOP 打印接口的入参和出参日志,以及执行时间等。
使用步骤: ①引入依赖 --> ②自定义一个注解作为切点 --> ③配置AOP切面类 --> ④需要使用AOP时直接加上注解即可。

5、Spring代理模式有?

JDK 动态代理 和 CGLIB 动态代理。

6、JDK动态代理和CGLIB动态代理的区别?

  • JDK 动态代理
    ① Interface:对于 JDK 动态代理,目标类需要实现一个接口Interface
    ② InvocationHandler:InvocationHandler是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在此过程,可以包装逻辑,对目标方法进行前置后置处理。
    ③ Proxy:Proxy利用InvocationHandler动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。
  • CGLIB 动态代理
    ① 使用 JDK创建代理有一大限制,它只能为接口创建代理实例 ,而 CGLIB 动态代理就没有这个限制。
    ② CGLIB 动态代理是 使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
    ③ CGLIB 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLIB 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLIB 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLIB 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

7、Spring AOP 和 AspectJ AOP 区别?

  • Spring AOP
    Spring AOP 属于 运行时增强,主要具有如下特点:
    ① 基于 动态代理 来实现,默认如果使用接口的,用 JDK 提供的动态代理实现,如果是方法则使用 CGLIB 实现。
    ② Spring AOP 需要 依赖 IOC 容器来管理,并且只能作用于 Spring 容器,使用纯 Java 代码实现。
    ③ 在性能上,由于 Spring AOP 是基于动态代理来实现的,在容器启动时需要生成代理实例,在方法调用上也会增加栈的深度,使得 Spring AOP 的性能不如 AspectJ 的那么好
    ④ Spring AOP 致力于解决 企业级 开发中最普遍的 AOP(方法织入)。

  • AspectJ
    ① AspectJ 是一个易用的功能强大的 AOP 框架,属于 编译时增强, 可以单独使用,也可以整合到其它框架中,是 AOP 编程的完全解决方案。AspectJ 需要用到单独的编译器 ajc。
    ② AspectJ 属于静态织入,通过修改代码来实现,在实际运行之前就完成了织入,所以说它生成的类是没有额外运行时开销的,一般有如下几个织入的时机:

    1. 编译期织入(Compile-time weaving):如类 A 使用 AspectJ 添加 了一个属性,类 B 引用了它,这个场景就需要编译期的时候就进行织入, 否则没法编译类 B。
    2. 编译后织入(Post-compile weaving):也就是已经生成了 .class 文件, 或已经打成 jar 包了,这种情况我们需要增强处理的话,就要用到编译后织 入。
    3. 类加载后织入(Load-time weaving):指的是在加载类的时候进行织 入,要实现这个时期的织入,有几种常见的方法。
      在这里插入图片描述

8、面向切面编程和面向对象编程的区别?

1、面向过程(POP)和面向对象(OOP)的区别:

两者的主要区别在于解决问题的方式不同:

  • 面向过程把解决问题的 过程拆成一个个方法,通过一个个方法的执行 解决问题。
  • 面向对象会先 抽象出对象,然后用对象执行方法 的方式解决问题。
    另外,面向对象开发的程序一般更易维护、易复用、易扩展。

2、面向对象(OOP)和面向切面(AOP)的区别:

  • 面向目标不同:简单来说OOP是面向名词领域,AOP面向动词领域。
  • 思想结构不同:OOP是纵向结构,AOP是横向结构。
  • 注重方面不同:OOP注重业务逻辑单元的划分,AOP偏重业务处理过程的某个步骤或阶段。

OOP和AOP联系: 两者之间是一个相互补充和完善的关系。
总的来说:
AOP是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性。 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
OOP针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。

三、Spring事务

Spring 事务的本质其实就是 数据库对事务的支持 ,没有数据库的事务支持,Spring 是无法提供事务功能的。Spring 只提供 统一事务管理接口 ,具体实现都是由各数据库自己实现,数据库事务的提交和回滚是通过数据库自己的事务机制实现。

1、Spring事务的种类?

Spring支持 编程式事务管理声明式事务管理
在这里插入图片描述
编程式事务: 编程式事务管理使用 TransactionTemplate,需要 显式执行事务。
声明式事务: 声明式事务管理建立在 AOP 之上的。其本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务 ,在执行完目标方法之后根据执行情况提交或者回滚事务。优点是不需要在业务逻辑代码中掺杂事务管理的代码,只需在 配置文件中做相关的事务规则声明或通过 @Transactional 注解的方式,便可以将事务规则应用到业务逻辑中,减少业务代码的污染。唯一不足地方是,声明式事务最细粒度 只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别

2、声明式事务实现原理

就是通过 AOP/动态代理 。

  • 在Bean初始化阶段创建代理对象: Spring容器在初始化每个单例bean的时候,会遍历容器中的所有BeanPostProcessor实现类,并执行其 postProcessAfterInitialization方法,在执行AbstractAutoProxyCreator类的postProcessAfterInitialization方法时会遍历容器中所有的切面,查找与当前实例化bean匹配的切面,这里会获取事务属性切面,查找@Transactional注解及其属性值,然后根据得到的切面创建一个代理对象,默认是使用JDK动态代理创建代理,如果目标类是接口,则使用JDK动态代理,否则使用CGLIB。
  • 在执行目标方法时进行事务增强操作: 当通过代理对象调用bean方法的时候,会触发对应的AOP增强拦截器,声明式事务是一种环绕增强,对应接口为MethodInterceptor,事务增强对该接口的实现为TransactionInterceptor,类图如下:
    在这里插入图片描述
    事务拦截器TransactionInterceptor在invoke方法中,通过调用父类TransactionAspectSupport的invokeWithinTransaction方法进行事务处理,包括开启事务、事务提交、异常回滚。

3、声明式事务什么时候失效?

在这里插入图片描述

4、Spring事务隔离级别?

Spring事务的隔离级别对应数据库的事务隔离级别,以MySQL数据库为例,主要包括:读未提交、读已提交、可重复读、串行化。

5、Spring事务传播机制?

Spring 事务的传播机制说的是,当多个事务同时存在的时候,一般指的是 多个事务方法相互调用时,Spring 如何处理这些事务的行为。
事务传播机制是使用简单的 ThreadLocal 实现的,所以,如果调用的方法是在新线程调用的,事务传播实际上是会失效的。
在这里插入图片描述
Spring 默认的事务传播行为是 PROPAFATION_REQUIRED 。

四、Spring注解

在这里插入图片描述
Spring的注解主要分为两类:

  • 类注解:@Component、@Repository、@Controller、@Service
  • 类内部注解(字段和方法上):@Bean、@Autowired、@Value、@Resource

1、Web

@Controller:组合注解(组合了@Component注解),应用在MVC层(控制层)。
@RestController:该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。
@RequestMapping:用于映射Web请求,包括访问路径和参数。如果是Restful风格接口,还可以根据请求类型使用不同的注解:@GetMapping、@PostMapping、@PutMapping、@DeleteMapping。
@ResponseBody:支持将返回值放在response内,而不是一个页面,通常用户返回 json 数据。
@RequestBody:允许request的参数在request体中,而不是在直接连接在地址后面。
@PathVariable:用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。
@RestController:该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。

2、容器

@Component:表示一个带注释的类是一个“组件”,成为Spring管理的 Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component还是一个元注解。
@Service:组合注解(组合了@Component注解),应用在service层(业务逻辑层)。
@Repository:组合注解(组合了@Component注解),应用在dao层(数据访问层)。
@Autowired:Spring 提供的工具(由Spring的依赖注入工具(BeanPostProcessor、BeanFactoryPostProcessor)自动注入)。
@Qualifier:该注解通常跟@Autowired一起使用,当想对注入的过程做更多的控制,@Qualifier可帮助配置,比如两个以上相同类型的Bean时Spring无法抉择,用到此注解。
@Configuration:声明当前类是一个配置类(相当于一个 Spring 配置的 xml 文件)
@Value:可用在字段,构造器参数跟方法参数,指定一个默认值,支持 #{} 跟 ${} 两个方式。一般将 SpringBoot 中的 application.properties 配置的属性值赋值给变量。
@Bean:注解在方法上,声明当前方法的返回值为一个Bean。返回的Bean对应的类中可以定义init()方法和destroy()方法,然后在@Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行init,在销毁之前执行destroy。
@Scope:定义我们采用什么模式去创建Bean(方法上,得有@Bean) 其设置类型包括:Singleton 、Prototype、Request 、 Session、GlobalSession。

3、AOP

@Aspect:声明一个切面(类上) 使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
@After:在方法执行之后执行(方法上)。
@Before:在方法执行之前执行(方法上)。
@Around:在方法执行之前与之后执行(方法上)。
@PointCut:声明切点 在 java 配置类中使用@EnableAspectJAutoProxy 注解开启 Spring 对 AspectJ 代理的支持(类上)。

4、事务

@Transactional:在要开启事务的方法上使用@Transactional 注解,即可声明式开启事务。

声明bean的注解:@Component(通用注解方式)、@Service(业务层注解)、@Repository(数据层注解)、@Controller(表现层注解)。
注入bean的注解: @Autowired(Spring提供)、@Qualifier(配和@Autowired使用)、@Inject、@Resource 。
配置类相关注解:@Configuration(声明当前类为配置类,相当于xml形式的Spring配置(类上))、@Bean(注解,方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上))、@Configuration(声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean(类上))、@ComponentScan(用于对Component进行扫描,相当于xml中的(类上))。
AOP相关注解:@Aspect(声明当前类为切面类(类上))、使用@After、@Before、@Around定义通知(advice),可直接将拦截规则(切点)作为参数。(@After 在方法执行之后执行(方法上)、@Before 在方法执行之前执行(方法上)、@Around 在方法执行之前与之后执行(方法上))、@PointCut(声明切点)、在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)。
Bean属性设置注解:@Scope(bean的生命周期)、@PostConstruct(在构造方法和init方法(如果有的话)之间得到调用,且只会执行一次。等价于xml配置文件中bean的initMethod)、@PreDestory(在Bean销毁之前执行,等价于xml配置文件中bean的destroyMethod)

Q:@Resource 和 @Autowired 的区别

  • @Resource是 Java自己的注解,有两个属性比较重要,分别是name和type;Spring将@Resource注解的 name属性 解析为 bean的名字,而 type属性 则解析为 bean的类型。所以如果i) 使用name属性,则使用byName的自动注入策略,而ii)使用type属性时则使用byType自动注入策略。默认按name进行注入。
  • @AutoWired是 Spring的注解,@Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。使用@Autowired方式最好使用构造函数的方式注入。
  • @Resource默认 按名称 方式进行bean匹配,@Autowired默认 按类型 方式进行bean匹配。

Q:@bean 和 @Component 的区别

@Component 和 @Bean是两种使用注解来 定义bean的方式,都可以使用@Autowired或者@Resource注解注入

  • @Component(和@Service和@Repository)用于 自动检测和使用类路径扫描自动配置bean 。注释类和bean之间存在隐式的一对一映射(即每个类一个bean)。@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。
  • @Bean用于 显式声明单个bean ,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许您精确地创建和配置bean。@Bean常和@Configuration注解搭配使用。@Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。

Q:为什么有了@Component,还需要@Bean?

如果想将 第三方的类变成组件,你又没有没有源代码,也就没办法使用@Component进行自动配置,这种时候 使用@Bean 就比较合适了。不过同样的也可以通过xml方式来定义。
另外 @Bean注解的方法返回值是对象 ,可以在方法中为对象设置属性。
此外Spring的Starter机制,就是通过@Bean注解来定义bean。
可以搭配@ConditionalOnMissingBean注解 @ConditionalOnMissingClass注解,如果本项目中没有定义该类型的bean则会生效。避免在某个项目中定义或者通过congfig注解来声明大量重复的bean。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文快速学会hadoop完全分布式集群搭建,很详细

文章目录前言一、准备工作二、克隆三台虚拟机并进行网络配置克隆虚拟机克隆引导修改网络配置验证验证方式一验证方式二三、安装jdk和hadoop四、ssh免密登录配置概述生成公钥和私钥把公钥拷贝到三台虚拟机上面去验证把hadoop103 和 hadoop104的免密登录配置安装上面的操作再做一…

ZYNQ - 无DDR固化程序(代码运行在OCM上)

写在前面 ZYNQ固化时&#xff0c;正常情况下都需要DDR参与&#xff0c;但是有时硬件设计时&#xff0c;可能将DDR去掉或设计出错&#xff0c;这将导致ZYNQ无法正常固化&#xff0c;之前有写过一个使用静态链接库进行无DDR固化的文章&#xff0c;当时那个是压缩了FSBL的相关代码…

yolov5剪枝实战3: yolov5-slimming项目运行演示

1. 下载项目文件 从百度网盘下载并解压 网盘地址,文末有链接:包括项目完整源代码、数据集、原理的课件说明等。 解压源码: yolov5-6.1-slimming.zip项目没有从yolov5 github上直接克隆项目文件,而是从百度网盘上下载项目文件并解压,因为yolov5原始的代码是没有带网络剪枝的,…

ElasticSearch - ​开启搜索的新境界

You Know&#xff0c; for Search ElasticSearch官网 开启搜索的新境界 Elasticsearch 是一个开源的搜索引擎&#xff0c;建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。 Lucene 可以说是当下最先进、高性能、全功能的搜索引擎库。但是 Lucene 仅仅只是一个库。为了充分…

STM32+ MAX30102通过指尖测量心率+血氧饱和度

一、前言 重要的事情放在最前面&#xff1a;max30102只适用于指尖手指测量&#xff0c;不适用与手腕手指测量&#xff0c;如需做成可穿戴样式选择传感器的小伙伴请pass掉他&#xff0c;因为他只有红光和红外2种光&#xff0c;不够充足的数据源去运算。 由于一些原因&#xff0c…

个人开发者轻松接入支付回调

易支付&#xff08;https://epay.jylt.cc&#xff09;- 个人支付如此简单 随着技术的发展&#xff0c;现在个人构建一个网站的成本越来越低&#xff0c;越来越多的个人开发者拥有了自己的网站。个人搭建网站除了带来成就感之外如果能赚一些额外的收入岂不更好&#xff1f; 事…

多目标优化问题的研究概述(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

ECMAScript

介绍 JavaScript和ECMAScript的区别 html和css的解析在两款浏览器是不同的效果&#xff0c;比如一个页面能在IE解析&#xff0c;但是不能在网景浏览器解析 后面出现了脚本语言&#xff0c;JavaScript&#xff0c;提供了丰富功能&#xff0c;比如输入密码进行正则的判断提示 …

【算法】用动态规划求解背包问题

1.问题描述 有n种物品&#xff0c;每种物品的单件重量为w[i],价值为v[i]。现有一个容量为V的背包&#xff0c;如何选取物品放入背包&#xff0c;使得背包内物品的总价值最大。 下面是本题中我们使用的例子&#xff1a; 有三个物品&#xff0c;第一个物品的重量为3&#xff0c;…

【附源码】Python计算机毕业设计图书销售系统设计

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

用友vs金蝶产品分析(云星空与YonSuite)

产品定位 用友与金蝶二者面对的客户群体是相同的&#xff1a;都是为成长型企业提供一体化服务&#xff0c;由于金蝶云星空发展较早&#xff0c;在部分产品功能上具备一定的先发优势&#xff1b;在产品的架构上&#xff0c;由于YS采用目前最先进的云原生和微服务架构&#xff0…

Bootstrap(一)

目录&#xff1a; &#xff08;1&#xff09;bootstrap容器 1.简单框架使用 2.流体容器 3.固定容器 4.栅格系统 &#xff08;1&#xff09;bootstrap容器 1.简单框架使用 bootstrap-3.3.7、bootstrap-3.3.7-dist 是原码文件&#xff0c;带dist是编译完的&#xff0c;里面…

5.C语言常见运算符及其优先级

运算符 用算术运算符将运算对象&#xff08;也称操作数&#xff09;连接起来的、符合C语言规则的式子&#xff0c;称为C算术表达式。运算对象包括常量、变量、函数等。 例如&#xff1a;a * b / c - 1.5 ‘a’ 运算符的分类 1.双目运算符&#xff1a;即参加运算的操作数有两…

SpringBoot--获取路径中的参数(x-www-form-urlencoded)--方法/实例

原文网址&#xff1a;SpringBoot--获取路径中的参数(x-www-form-urlencoded)--方法/实例_IT利刃出鞘的博客-CSDN博客 简介 本文用示例介绍SpringMVC如何获取路径中的参数。也就是&#xff1a; Content-Type为x-www-form-urlencoded。 代码 Controller BasicController.java…

在线考试系统

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

Prometheus邮件告警

一. 部署Alertmanager&#xff1a; 1. 解压Alertmanager压缩包&#xff1a; [rootnode5 ~]# tar xf alertmanager-0.24.0.linux-amd64.tar.gz -C /usr/local/ 2. 为解压后的文件做软连接&#xff1a; [rootnode5 ~]# ln -sv /usr/local/alertmanager-0.24.0.linux-amd64/ …

SSM整合(三)

redis之简单使用 1.准备工作 1.1 在resource资源文件夹下面创建redis.properties文件,并填写如下内容 #连接端口 redis.port6379 #连接地址 redis.host127.0.0.1 #超时时间&#xff1a;单位ms redis.timeout3000 #授权密码 redis.password #最大连接数&#xff1a;能够同时建…

GUI编程--PyQt5--QLineEdit

文章目录键盘文本输入框文本占位符密码显示与隐藏自动补全输入限制掩码字符光标移动设置文本区域常用编辑功能输入控件&#xff0c;用于捕获用户的信息键盘文本输入框 QLineEdit, 单行&#xff0c;纯文本输入框 # 实例化 文本输入框 le QLineEdit("默认值", windo…

Material Design之CoordinatorLayout 与AppbarLayout与CollapsingToolbarLayout

Material Design 之 CoordinatorLayout 第一次接触CoordinatorLayout 你可能有这些疑问&#xff0c;CoordinatorLayout 到底是个什么玩意儿呢&#xff1f;它到底能帮我们做什么&#xff1f;我们要了解它&#xff0c;肯定是先看官方文档了。文档的第一句话就非常醒目&#xff1a…

高职网络系统管理比赛实例

同一交换机不同端口配置不同vlan&#xff0c;实现同一交换机内不同业务部门隔离。 在路由器中配置斜面的内容 1 输入enableRuijie>enable 2 第一次使用该交换机时&#xff0c;需要设置密码&#xff0c;然后再次确认密码 Please Set the password:*** Please check the pass…