Spring

一、Spring

1、什么是 Spring 框架?

Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性。

我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发,比如说 Spring 支持 IoC(Inversion of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、可以很方便地集成第三方组件(电子邮件,任务,调度,缓存等等)、对单元测试支持比较好、支持 RESTful Java 应用程序的开发。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywlI9SC2-1688351482061)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291222926.png)]

Spring 最核心的思想就是不重新造轮子,开箱即用,提高开发效率。

Spring 翻译过来就是春天的意思,可见其目标和使命就是为 Java 程序员带来春天啊!感动!

2、Spring 包含的模块有哪些?

Spring4.x 版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gim1G95V-1688351482062)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291224262.png)]

Spring5.x 版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zg9HT74u-1688351482063)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291224664.png)]

Spring5.x 版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了用于异步响应式处理的 WebFlux 组件。

Spring 各个模块的依赖关系如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zsr38flC-1688351482063)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291224721.png)]

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,Spring MVC,Spring Boot 之间什么关系?

很多人对 Spring,Spring MVC,Spring Boot 这三者傻傻分不清楚!这里简单介绍一下这三者,其实很简单,没有什么高深的东西。

Spring 包含了多个功能模块(上面刚刚提到过),其中最重要的是 Spring-Core(主要提供 IoC 依赖注入功能的支持) 模块, Spring 中的其他模块(比如 Spring MVC)的功能实现基本都需要依赖于该模块。

下图对应的是 Spring4.x 版本。目前最新的 5.x 版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了用于异步响应式处理的 WebFlux 组件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XOuI2dQd-1688351482063)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291239548.png)]

Spring MVC 是 Spring 中的一个很重要的模块,主要赋予 Spring 快速构建 MVC 架构的 Web 程序的能力。MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bZs6YqM-1688351482064)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291240497.png)]

使用 Spring 进行开发各种配置过于麻烦比如开启某些 Spring 特性时,需要用 XML 或 Java 进行显式配置。于是,Spring Boot 诞生了!

Spring 旨在简化 J2EE 企业应用程序开发。Spring Boot 旨在简化 Spring 开发(减少配置文件,开箱即用!)。

Spring Boot 只是简化了配置,如果你需要构建 MVC 架构的 Web 程序,你还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 帮你简化了 Spring MVC 的很多配置,真正做到开箱即用!

4、Spring IoC

谈谈自己对于 Spring IoC 的了解

IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spring 特有,在其他语言中也有应用。

为什么叫控制反转?

  • 控制:指的是对象创建(实例化、管理)的权力
  • 反转:控制权交给外部环境(Spring 框架、IoC 容器)

DI依赖注入:在SPring创建这个对象的过程中,将这个对象所依赖的属性注入进去。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-byeiWWd9-1688351482064)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291242322.png)]

​ 将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。

​ 在实际项目中一个 Service 类可能依赖了很多其他的类,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。

​ 在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。

Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mU8MJFXc-1688351482064)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031006906.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wTSfX2E-1688351482065)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301609774.png)]

5、什么是 Spring Bean?

简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。

我们需要告诉 IoC 容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。

<!-- Constructor-arg with 'value' attribute -->
<bean id="..." class="...">
   <constructor-arg value="..."/>
</bean>

下图简单地展示了 IoC 容器如何使用配置元数据来管理对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfOb433S-1688351482065)(https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/062b422bd7ac4d53afd28fb74b2bc94d.png)]

org.springframework.beansorg.springframework.context 这两个包是 IoC 实现的基础,如果想要研究 IoC 相关的源码的话,可以去看看

id和name都是spring 容器中bean 的唯一标识符。

  1. id: 一个bean的唯一标识 , 命名格式必须符合XML ID属性的命名规范
  2. name: 可以用特殊字符,并且一个bean可以用多个名称:name=“bean1,bean2,bean3”
    ,用逗号或者分号或者空格隔开。如果没有id,则name的第一个名称默认是id

spring 容器如何处理同名bean?

  • 同一个spring配置文件中,bean的 id、name是不能够重复的,否则spring容器启动时会报错。
    如果一个spring容器从多个配置文件中加载配置信息,则多个配置文件中是允许有同名bean的,并且后面加载的配置文件的中的bean定义会覆盖前面加载的同名bean。
    1、在spring同一个配置文件中,不能存在id相同的两个bean,否则会报错。
    2、在两个不同的spring配置文件中,可以存在id相同的两个bean,启动时,不会报错。这是因为spring
    ioc容器在加载bean的过程中,类DefaultListableBeanFactory会对id相同的bean进行处理:后加载的配置文件的bean,覆盖先加载的配置文件的bean。DefaultListableBeanFactory类中,有个属性allowBeanDefinitionOverriding,默认值为true,该值就是用来指定出现两个bean的id相同的情况下,如何进行处理。如果该值为false,则不会进行覆盖,而是抛出异常。
5.1将一个类声明为 Bean 的注解有哪些?
  • @Component:通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
  • @Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。
5.2、@Component 和 @Bean 的区别是什么?
  • @Component 注解作用于类,而@Bean注解作用于方法。
  • @Component通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。
  • @Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。

@Bean注解使用示例:

@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }

}

上面的代码相当于下面的 xml 配置

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

下面这个例子是通过 @Component 无法实现的。

@Bean
public OneService getService(status) {
    case (status)  {
        when 1:
                return new serviceImpl1();
        when 2:
                return new serviceImpl2();
        when 3:
                return new serviceImpl3();
    }
}
5.3、注入 Bean 的注解有哪些?

Spring 内置的 @Autowired 以及 JDK 内置的 @Resource@Inject 都可以用于注入 Bean。

AnnotaionPackageSource
@Autowiredorg.springframework.bean.factorySpring 2.5+
@Resourcejavax.annotationJava JSR-250
@Injectjavax.injectJava JSR-330

@Autowired@Resource使用的比较多一些。

5.4、@Autowired 和 @Resource 的区别是什么?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0EbDGFNI-1688351482065)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031013453.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I7sB2GHI-1688351482066)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301708232.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CgqSPsf3-1688351482066)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301708344.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDrPYjvj-1688351482066)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301721887.png)]

Autowired 属于 Spring 内置的注解,默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。

这会有什么问题呢? 当一个接口存在多个实现类的话,byType这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。

这种情况下,注入方式会变为 byName(根据名称进行匹配),这个名称通常就是类名(首字母小写)。就比如说下面代码中的 smsService 就是我这里所说的名称,这样应该比较好理解了吧。

// smsService 就是我们上面所说的名称
@Autowired
private SmsService smsService;

举个例子,SmsService 接口有两个实现类: SmsServiceImpl1SmsServiceImpl2,且它们都已经被 Spring 容器所管理。

// 报错,byName 和 byType 都无法匹配到 bean
@Autowired
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
private SmsService smsServiceImpl1;
// 正确注入  SmsServiceImpl1 对象对应的 bean
// smsServiceImpl1 就是我们上面所说的名称
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;

我们还是建议通过 @Qualifier 注解来显式指定名称而不是依赖变量的名称。

**@Resource属于 JDK 提供的注解,默认注入方式为 byName。**如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为byType

@Resource 有两个比较重要且日常开发常用的属性:name(名称)、type(类型)。

public @interface Resource {
    String name() default "";
    Class<?> type() default Object.class;
}

如果仅指定 name 属性则注入方式为byName,如果仅指定type属性则注入方式为byType,如果同时指定nametype属性(不建议这么做)则注入方式为byType+byName

// 报错,byName 和 byType 都无法匹配到 bean
@Resource
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Resource
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;

简单总结一下:

  • @Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解。
  • Autowired 默认的注入方式为byType(根据类型进行匹配),@Resource默认注入方式为 byName(根据名称进行匹配)。
  • 当一个接口存在多个实现类的情况下,@Autowired@Resource都需要通过名称才能正确匹配到对应的 Bean。Autowired 可以通过 @Qualifier 注解来显式指定名称,@Resource可以通过 name 属性来显式指定名称。
5.5、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 方式:

<bean id="..." class="..." scope="singleton"></bean>

注解方式:

@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Person personPrototype() {
    return new Person();
}
5.6、单例 Bean 的线程安全问题了解吗?

大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。

常见的有两种解决办法:

  1. 在 Bean 中尽量避免定义可变的成员变量。
  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

不过,大部分 Bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。

5.7、Bean 的生命周期了解么?
  • 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 属性,执行指定的方法。

图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wZHviRrs-1688351482066)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291338220.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Y7BJkbp-1688351482071)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301641376.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fWFeQLVQ-1688351482071)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301641168.png)]

Spring Bean 生命周期

与之比较类似的中文版本:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ViFvRfbo-1688351482071)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306291338466.jpeg)]Spring Bean 生命周期

5.8、Spring的属性注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gc9NIKrU-1688351482072)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301644505.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WzmPaVUa-1688351482072)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301644528.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w1OscGkk-1688351482072)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301646872.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-27UNBCd9-1688351482072)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301647632.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RzhANZVT-1688351482073)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301648176.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0kCs0GPi-1688351482073)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301649402.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vGFflKtk-1688351482073)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301650649.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exeLoVM7-1688351482074)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301649745.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ViBcwXDl-1688351482074)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301655968.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZtm9j7z-1688351482074)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301655200.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H1VO0TqK-1688351482074)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301656289.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ms8TbuKw-1688351482074)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301657569.png)]

5.9、SPring Bean管理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O31nf1x1-1688351482075)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301659496.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nbiXVXQn-1688351482075)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301702744.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GCF7yRAS-1688351482075)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301723991.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JO8m4hk5-1688351482075)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301724359.png)]

5.10、XML和注解配合使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lx9zwxLd-1688351482076)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301724829.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Oj9EPLH-1688351482076)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301726045.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YURNEZ9H-1688351482076)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301726335.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-li5ILIil-1688351482076)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301726654.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LkFrbiAu-1688351482077)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301727702.png)]

6、Spring AoP

6.1、 谈谈自己对于 AOP 的了解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DTtbbOB2-1688351482077)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301736858.png)]

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RiF9YxNL-1688351482077)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301737383.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9Pe46l9-1688351482077)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301737273.png)]

​ AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

​ Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-175HUOlV-1688351482077)(https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/230ae587a322d6e4d09510161987d346.jpeg)]SpringAOPProcess

当然你也可以使用 AspectJ !Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。

AOP 切面编程设计到的一些专业术语:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-evO1h9Lt-1688351482078)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301739607.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBicS5Yj-1688351482078)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301748638.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MqWNZQKt-1688351482078)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202306301749359.png)]

术语含义
目标(Target)被通知的对象
代理(Proxy)向目标对象应用通知之后创建的代理对象
连接点(JoinPoint)目标对象的所属类中,定义的所有方法均为连接点
切入点(Pointcut)被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点)
通知(Advice)增强的逻辑 / 代码,也即拦截到目标对象的连接点之后要做的事情
切面(Aspect)切入点(Pointcut)+通知(Advice)
Weaving(织入)将通知应用到目标对象,进而生成代理对象的过程动作
6.2、Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。

Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,

如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。

6.3、AspectJ 定义的通知类型有哪些?
  • Before(前置通知):目标对象的方法调用之前触发
  • After (后置通知):目标对象的方法调用之后触发
  • AfterReturning(返回通知):目标对象的方法调用完成,在返回结果值之后触发
  • AfterThrowing(异常通知):目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
  • Around (环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
6.4、多个切面的执行顺序如何控制?

1、通常使用@Order 注解直接定义切面顺序

// 值越小优先级越高
@Order(3)
@Component
@Aspect
public class LoggingAspect implements Ordered {

2、实现Ordered 接口重写 getOrder 方法。

@Component
@Aspect
public class LoggingAspect implements Ordered {

    // ....

    @Override
    public int getOrder() {
        // 返回值越小优先级越高
        return 1;
    }
}
6.5、动态代理代码案例

​ 在 Java 中,动态代理主要通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现。Proxy 类用于创建动态代理对象,而 InvocationHandler 接口则用于处理方法调用。

​ 在 JDK 中,动态代理是通过 java.lang.reflect.Proxy 类实现的。实际上,当您使用 newProxyInstance() 方法创建一个动态代理实例时,您需要提供一个 InvocationHandler 对象作为参数。
InvocationHandler 是一个接口,它包含一个方法 invoke(),用于处理代理实例上的方法调用。当代理对象上的方法被调用时,invoke() 方法将被调用,并传入代理对象、方法对应的 Method 对象以及传递给该方法的参数。然后,invoke() 方法可以执行任意自定义逻辑,并返回一个结果对象,作为代理方法的返回值。
​ 在 JDK 动态代理中,InvocationHandler 的作用非常重要,因为它使得我们能够在运行时动态地生成代理类,并在调用代理对象方法时进行前置或后置操作,例如记录日志、授权、缓存等。
简而言之,InvocationHandler 是 JDK 动态代理机制的核心,它允许我们在运行时动态地生成代理类,并且可以对代理对象上的方法调用进行拦截和处理。

java.lang.reflect.Proxy

//用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy)
//返回指定接口的代理类
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
//构造实现指定接口的代理类的一个新实例,所有方法会调用给定处理器对象的 invoke 方法
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
//返回 cl 是否为一个代理类
static boolean isProxyClass(Class<?> cl) 

InvocationHandler 接口只有一个方法:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

其中,invoke() 方法的参数含义如下:

  • Object proxy:代理类实例对象。
  • Method method:被代理的方法对象。
  • Object[] args:方法调用时所传递的参数。

在动态代理中,当客户端通过代理对象调用一个方法时,这个方法实际上会委托给 InvocationHandler 中的 invoke() 方法来处理。因此,invoke() 方法是动态代理的核心。

invoke() 方法中,我们可以根据需要进行任何自定义操作,例如记录日志、鉴权、缓存等。最后,再通过反射机制调用目标对象的方法并返回结果。

public interface UserDao {

    public void save(String name);
    public void update();

    public void delete();

    public void find();

}

public class UserDaoImpl implements UserDao{
    @Override
     public void save(String name) {
        System.out.println("save " + name);
    }

    @Override
    public void update() {
        System.out.println("update");
    }

    @Override
    public void delete() {
        System.out.println("delete");
    }

    @Override
    public void find() {
        System.out.println("find");
    }
}

public class MyJdkProxy implements InvocationHandler {

    private UserDao userDao;

    public MyJdkProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    public Object createProxy(){
        Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(),this);
        return proxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("save".equals(method.getName())){
            System.out.println("权限校验代码");
            return method.invoke(userDao,args);
        }
        return method.invoke(userDao,args);
    }
}

public class Demo1 {
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        UserDao proxy = (UserDao) new MyJdkProxy(userDao).createProxy();
        proxy.save("ysh"); 
        //权限校验代码
		//save ysh
        proxy.find();
        //find
    }
}

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I7I8QpXq-1688351482078)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021618773.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i5KRY1tf-1688351482079)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021622344.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eqs0ryhe-1688351482079)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021622247.png)]

6.6、Spring代理知识

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FZAcgVKe-1688351482079)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021704368.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-geMX6fzQ-1688351482079)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021704495.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R94LWzEz-1688351482080)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021737457.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RsKNuI27-1688351482080)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021737606.png)]

![img](file:///G:/images/spring/clipboard%20(49).png)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wpxsuaxa-1688351482080)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021738470.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PVVcW0gP-1688351482080)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021740815.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W0PHx0OR-1688351482081)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021740446.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sUbfVbvu-1688351482081)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021741623.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fYuJa595-1688351482081)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021741734.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7U4tnJ7W-1688351482081)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021742374.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPlBxqtb-1688351482082)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021743687.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SlFUWZ3u-1688351482082)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021759615.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4VkK472-1688351482082)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021759166.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1vI7k1Eu-1688351482082)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021800686.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEv52uZs-1688351482082)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021800760.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kADqgdQV-1688351482083)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307021815231.png)]

6.7、基于AspectJ的AOP开发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CpAE3QW4-1688351482083)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022017218.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-67BGi723-1688351482083)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022018696.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uJjfYnan-1688351482083)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022018455.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZO5g8Bd-1688351482084)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022020286.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TScugzjA-1688351482084)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022035721.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iu8Arqe6-1688351482084)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022036094.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eHKjeQLV-1688351482084)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022036438.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ucp8mEQ5-1688351482085)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022036727.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33s6ZiM0-1688351482085)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022037919.png)]

@After

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1sSUhF2D-1688351482085)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022052974.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S9hzoZeF-1688351482085)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022053168.png)]

@AfterReturning

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-df0O5gB5-1688351482085)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022044951.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z4Yry59j-1688351482086)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022045799.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pD8SvVB9-1688351482086)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022046904.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mTw1S0nC-1688351482086)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022048287.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xhQZjwxU-1688351482086)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031030391.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7EPS7VqX-1688351482087)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031031689.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6h1wlc37-1688351482087)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031031159.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOYwe8p9-1688351482087)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022051566.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aEOVbwga-1688351482087)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022051999.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-voulOM35-1688351482088)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307022051006.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qqgwgYjN-1688351482088)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030843282.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UJCugh3r-1688351482088)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030844928.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rUf9aiOC-1688351482088)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030844049.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qe9yWO0l-1688351482088)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030845506.png)]

7、Spring JDBC

7.1、SPring JDBC Template

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-frVUc7r3-1688351482089)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030848420.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FLCh2AeX-1688351482089)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031029637.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R1jtTQ6G-1688351482089)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030850193.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jwAFcoRe-1688351482089)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031029589.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ekoCn4ww-1688351482090)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030852547.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVJCHalc-1688351482090)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030852898.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-748KF8Gh-1688351482090)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031029902.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZrU12wfo-1688351482090)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030854747.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j269i2u4-1688351482090)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031029089.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YRHHubcr-1688351482091)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031030317.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ifNwgDON-1688351482091)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031030736.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6qVMJAG-1688351482091)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030858850.png)]

7.2、事务管理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eiTbyr14-1688351482091)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030900409.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unicck00-1688351482092)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030925617.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ESqyfFKa-1688351482092)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031027561.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5VEDzgs-1688351482092)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031027366.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S8jhSZTx-1688351482092)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030929875.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tAODCPwZ-1688351482093)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030931073.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3lij5Idh-1688351482093)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030932570.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FFlT8YbT-1688351482093)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030937733.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E12QslJP-1688351482093)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030940236.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vC4Ja8rS-1688351482093)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030940851.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lEZINR9W-1688351482094)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030941538.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0LakogFY-1688351482094)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030942170.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pr3WfH7K-1688351482094)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030942738.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TMggudmO-1688351482094)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030944124.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2XziVesz-1688351482095)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030944011.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bd6VwNw5-1688351482095)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030945675.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-izLysZtk-1688351482095)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030946683.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yjfv7gkv-1688351482095)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030947827.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MT38e6s1-1688351482096)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030947042.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-psapuMsR-1688351482096)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030949242.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWOst6y2-1688351482096)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030949827.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SFhGaa7C-1688351482096)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030949025.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-crXLPwjV-1688351482097)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307030951811.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-usS6fNT2-1688351482097)(https://gitee.com/satougaku/my-picture/raw/master/ysh/202307031027153.png)]

参考

Spring常见面试题总结 | JavaGuide(Java面试 + 学习指南)

慕课网

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值