基础
Spring 是一款主流的 Java EE 轻量级开源框架,其目的是用于简化 Java 企业级应用的开发难度和开发周期。Spring 的用途不仅限于服务器端的开发。
Spring 有哪些常⽤注解呢

Spring 中应用了哪些设计模式呢

JDK 动态代理 (接口)和 cglib 动态代理 (继承)
分层解耦
- 分层解耦: 高内聚,低耦合
内聚 : 软件各个功能模块内部的功能联系(瑞士军刀)
耦合 : 衡量各个层/模块之间的依赖关联程度
IOC 控制反转 Inversion of Control
控制反转主要通过依赖注入 Dependency Injection,简称 DI 和依赖查找 Dependency Lookup DL 来实现
ApplicationContext 是 BeanFactory 子接口,功能更多,而 BeanFactory 不提供给开发者使用
当 Spring 应用程序启动时,ApplicationContext 会扫描指定的包(通常通过配置类或 XML 配置文件指定),寻找带有 @Component 注解的类。找到这些类后,ApplicationContext 会使用反射机制实例化这些类,并将它们注册到其内部管理的 Bean 工厂中。
在这个过程中,ApplicationContext 实际上是使用 BeanFactory 来管理和创建这些 Bean 的。可以简单理解为,ApplicationContext 是一个功能更强大的 BeanFactory,它不仅能管理 Bean 的创建和生命周期,还提供了更多的高级功能
控制反转就是把创建和管理 bean 的过程转移给了第三方。而这个第三方,就是 Spring IoC Container,对于 IoC 来说,最重要的就是容器。
何为反转,反转了什么?
答:把这个权利交给了 Spring 容器,而不是自己去控制,就是反转。由之前的自己主动创建对象,变成现在被动接收别人给我们的对象的过程,这就是反转
BeanFactory 简单粗暴,可以理解为 HashMap:
Key - bean nameValue - bean object
但它一般只有 get, put 两个功能,所以称之为“低级容器”。
而 ApplicationContext 多了很多功能,因为它继承了多个接口,可称之为“高级容器”。在下文的搭建项目中,我们会使用它。

BeanDefinition 相当于 Bean 的“蓝图”或“元数据”
① Bean 定义
@Component、@Service、@Repository 等 (xml 后来演变的)
使用以上四个注解都可以声明 bean,但是在 springboot 集成 web 开发中,声明控制器 bean 只能用 @Controller
② Bean 注册到 IOC (IOC 装载在对象创建之前)
注册一个 Bean 是指将一个类声明为 Spring 容器管理的对象。这个过程包括将类的信息(如类名、类型、作用域等)添加到 Spring 容器的内部数据结构中,以便在需要时可以创建和管理这个对象。
@ComponentScan(lazyinit= true) 注册而不实例化,而是在第一次使用这些Bean时才进行实例化。
使用 @Lazy 注解,@ComponentScan 扫描到的Bean会延迟到第一次使用时才实例化。
③ Bean 实例化
@ComponentScan 扫描到的Bean会在容器启动时立即实例化
Bean 实例化方式可根据类自身可实例化的方式进行选择
- 使用该类的有参/无参构造方法 (默认)(
Spring容器扫描到一个类被标记为@Component时,它会使用该类的默认构造方法(无参构造方法)来实例化bean) - 借助自身的静态/非静态工厂方法或自己生成一个工厂方法 (如
@Component中使用@Bean指定的) FactoryBean接口实例化 (FactoryBean是 Spring 提供的一个接口,允许你自定义Bean的创建逻辑)
当一个组件被注入时, Spring 会优先使用无参构造方法来实例化该类。如果该类没有无参构造方法,Spring 会尝试使用其他可用的构造方法,但这需要额外的配置。
@Import 定义+注册+实例化
@Import 注释允许从另一个配置类加载 @Bean 定义

BeanFactory --> ApplicationContext --> webapplicationContext
在现实中我们使用的大部分 SpringIoC 容器是
ApplicationContext 接口的实现类 (上面的实现类都算是 IOC 容器)
@Component@Service、@Repository和@Mapper 是标明哪个类被扫描进入 SpringIoC 容器
@ComponentScan 标明采用何种策略去扫描装配 Bean(在 @SpringBootApplication 包含了)
Spring 容器启动阶段会干什么
启动阶段: 加载配置-->分析配置信息-->装配到 BeanDefinition -->其他后处理
Bean 实例化阶段: 实例化对象-->装配依赖-->生命周期回调-->对象其他处理-->注册回调接口
Spring Bean ⽣命周期/IOC 加载流程

- 对象 A创建实例化 (调用
无参构造器)(相对 java 而言) 解析出每个 Bean 的定义信息,并将这些信息封装成BeanDefinition对象 {三级缓存} - 对象 A设置属性、属性注入 (set 方法) (Spring 会根据配置文件或注解中的信息,将依赖注入到 Bean 中。)
【早期引用/暴露阶段】
如果此时 A发生循环依赖 B,会将另一个对象 B初始化,然后 B 拿到 A 的三级缓存,放入二级缓存,删除原来的三级缓存如果被 AOP, 放入二级缓存的则是代理类 A 了,然后 B 使用二级缓存 A 完成了初始化 - 后置处理器(初始化之前)(修改属性值、验证配置信息、甚至可以替换或返回新的 Bean 实例)
- 对象初始化 (相对
spring而言的 )(init-method是@Bean的属性, 来指定的初始化方法) (@PostConstruct自定义的类可以使用, 配置类时声明init方法并指定@PostConstruct)(如果你有一个普通的类,且无法修改它的源码来添加注解,可以在@Bean注解中通过init-method指定初始化方法)
- 后置处理器(初始化之后)(一些自定义的初始化逻辑、注册监听器)(AOP)(此时如果 Bean 需要被代理,
Spring AOP的基础设施会在这里创建代理对象,并返回这个代理对象代替原始 Bean。){放入一级缓存}``Spring AOP的基础设施会通过调用三级缓存中的ObjectFactory生成代理对象,并放入一级缓存, 并从二级缓存和三级缓存中移除,如果只有二级缓存,就会导致二级缓存是普通 bean, 一级缓存时代理 bean, 没有被移除 - bean 对象就绪,然后放入单例池
- bean 对象销毁(
@PreDestroy需在配置 bean 时指定销毁方法destory-method) - IOC 容器关闭

title: 完整流程

解决

循环依赖问题
循环依赖(Circular Dependency)是指两个或多个 Bean 相互依赖,形成了一个闭环。例如,Bean A 依赖于 Bean B,而 Bean B 又依赖于 Bean A。这种情况会导致 Spring 在创建 Bean 时出现问题
可以使用 @lazy 注解
Spring 不支持基于构造器注入的循环依赖
构造器注入意味着刚刚开始,实例化就需要
AB 都是构造器注入不可以
A 中的 B为构造器注入不可以,为 setter 注入可以

Spring 怎么解决循环依赖的呢?
任何已经完全创建并初始化好的单例(singleton)Bean 都会被存储在一级缓存中。
一级缓存是 Spring 容器中最主要的缓存,用于存储已经完全初始化并可以直接使用的单例 Bean 实例。
就是 3 中不同实例化阶段的 Bean
- 一级缓存(singletonObjects):存放完全初始化的单例Bean
- 二级缓存(earlySingletonObjects):早期引用,实例化完成的
Bean - 三级缓存(singletonFactories):存放
Bean工厂
当 Spring 检测到循环依赖时,会将尚未完全初始化的 Bean 提前暴露到二级缓存中,以便其他 Bean 可以引用它。这种机制可以解决大部分单例模式下的循环依赖问题,包括属性自动注入的情况。
如果不互相依赖会直接创建放入一级缓存

title: 循环依赖

将 代理bean 和 普通bean 都存了进去,无论是否存在都会存入三级缓存,出现了再执行进行 AOP
三级缓存内部会判断是否被 AOP




@autowired 的实现原理
title:简介


说说 Spring AOP 和 Aspect AOP 区别?


代理失效情况
- 代理对象的类型 :
- AOP 代理只能对被 Spring 管理的 Bean 生效 (没有交给 IOC 容器的)。同样如果你直接调用一个对象的内部方法(不是通过 Spring 容器获取的),那么 AOP 不会生效。
- 访问修饰符 :
- private 方法 :由于 Java 的访问控制,private 方法不能被外部代理调用,因此 AOP 对 private 方法的切面不会生效。
- final 方法 :同样,final 方法不能被子类重写,AOP 代理也无法应用。
- static方法 ; 静态方法是属于类本身,而不是类的实例
- Bean 的作用域 :
- 如果 Bean 的作用域是 prototype,而你又在 singleton 的 Bean 中注入了这个 prototype Bean,可能导致 AOP 失效。
这些失效适用于 @Transactional/@Cacheable 等注解,因为这些也依靠 AOP 来实现
失效
public boolean testcall(int id)throws Exception {
return testcompileException2(id);
}
testcompileException2上虽然加了如@Transactional/@Cacheable,但是不会生效,因为这是内部调用
解决:return springUtil.getBean(this.getclass()).testcompileException2(id)
失效
@Transactiona
private boolean testspecialException(int id)throws Exception
事物
事物管理底层也是 AOP
sping 事物分类
编程式(代码块级别)
声明式: xml 或注解 transactional(方法级别)


事物传播机制
@Transactional(readOnly = true)
@Transactional(timeout = 3)
[[../数据库/mysql/Mysql面试#^sz3dj3|Mysql/Mysql面试 > ^sz3dj3)
声明式事物实现原理
就是通过 AOP/动态代理



声明式事务在哪些情况下会失效

MVC
![[../../IT/JAVA微服务核心/JAVAWEB/assets/JavaWeb/image-20240122142832335.png|assets/JavaWeb/image-20240122142832335.png)
M 模型 V 视图 C 控制层,接受和响应
springMVC 将软件按照模型,视图,控制器来划分
Spring MVC 是 Spring 框架中用于构建基于 Java 的 Web 应用程序的模块,提供了基于 MVC 架构的方式来处理 HTTP 请求并返回响应。
MVC 执行流程
![[../../IT/Utility/Excalidraw/springmvc执行流程.excalidraw|../../Utility/Excalidraw/springmvc执行流程.excalidraw)
DispacherServlet -> HandlerMapping -> Interceptor -> HandlerAadapter ->调用前准备 handleMethodArgumentResolver(参数解析器) 和 handleMethodReturnValueHandler(返回值处理器)
handleMethodReturnValueHandler(返回值处理器)
RequestMappingHandlerAdapter 准备好 handleMethodArgumentResolver(参数解析器) 和 handleMethodReturnValueHandler(返回值处理器) 后,来调用 invokeHandlerMethod() 来执行目标方法(自己写的 handler),然后生成返回值对象,根据前面准备好的 handleMethodReturnValueHandler 进行返回值的处理
内容协商
RequestResponseBodyMethodProcessor
在 Spring 框架中既是一个返回值处理器,也是一个参数解析器。
使得 HandlerAadapter 可以调用 HttpMessageConverter 将 请求报文转换为 Java 对象,或将 Java 对象转换为响应报文
HttpMessageConverter
是 RequestResponseBodyMethodProcessor 返回值处理器所调用的 , 调用writeWithMessageConverters利用messageConverter把返回值写出去
自定义转换器与 ObjectMapper
HttpMessageConverter 是所有转换器的接口
转换器 -> 消息转换器 messageConvert
ObjectMapper 是 Jackson 库的核心类,负责将 Java 对象和各种数据格式(如 JSON、YAML)之间进行转换。
ObjectMapper.writeValue(OutputStream out, Object value):这是 ObjectMapper 的一个方法,用于将 Java 对象 value 序列化为指定的数据格式,并写入到输出流 out 中
如果你的项目中没有特殊的需求,使用默认的 ObjectMapper 就足够了。Jackson 的默认配置已经能够处理大多数基本的 YAML 序列化和反序列化需求。
在配置类中声明一个方法, 的方法命名是固定的 extendMessageConverters/configureMessageConverters
![[../../IT/Utility/Excalidraw/自定义转换器.excalidraw|../../Utility/Excalidraw/自定义转换器.excalidraw)
为 configureMessageConverters 时,-该方法用于替换 Spring MVC 的默认消息转换器列表。
为 extendMessageConverters 时,该方法用于在保留 Spring MVC 默认消息转换器的基础上,添加自定义的消息转换器。
自定义 JSON 转换器 (JacksonObjectMapper)
由于默认的JSON转换器虽然存在,但无法满足需求,所以需要自定义ObjectMapper
如果你的项目中没有特殊的需求,使用默认的 ObjectMapper 就足够了。Jackson 的默认配置已经能够处理大多数基本的 YAML 序列化和反序列化需求。
title: 自定义 JSON 转换器(JacksonObjectMapper)
为消息转换器`MappingJackson2HttpMessageConverter`设置对象转换器`JacksonObjectMapper`
这行代码的作用是为 `MappingJackson2HttpMessageConverter` 设置一个自定义的 `ObjectMapper`,`ObjectMapper` 是 Jackson 库中的一个核心类,负责将Java对象和JSON数据之间进行转换。
![[assets/Spring面试/image-20240629181507086.png)
![[assets/苍穹外卖/image-20231029215203117.png)
![[assets/苍穹外卖/image-20231029215121733.png)
不使用消息转换器时, 数据库的时间类型(2022-02-17 09:16:20)直接被序列化为字符串(202221791620), 没有经过格式化。
![[assets/苍穹外卖/image-20231029215138915.png)
```java
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
自定义 Yaml 转换器
如果你的项目中没有特殊的需求,使用默认的 ObjectMapper 就足够了。Jackson 的默认配置已经能够处理大多数基本的 YAML 序列化和反序列化需求。所以无需自定义ObjectMapper,只需要引入yaml依赖后自定义一个MyYamlHttpMessageConverter即可,因为Spring MVC 默认并不支持 YAML 格式的请求和响应
title: 自定义Yaml转换器
将Yaml依赖传入了ObjectMapper
将`@responseBody/@requestBody`通过自己的转换器
直接使用方式

@RequestMapping(
value = {"/testRequestMapping", "/test"}
,method = {RequestMethod.GET, RequestMethod.POST}
,params = {"username","password!=123456"}
,header={"Host=localhost:8081"}
,consumes={"multipart/form-data"}//用于指定请求的 `Content-Type`
,produces={"application/json"}//用于指定响应的 `Content-Type`
,name={"testHandler"}//用于为映射提供一个逻辑名称。通常用于工具或框架需要根据名称进行查找的情况。
)
处理get请求的映射-->`@GetMapping`
处理post请求的映射-->`@PostMapping`
处理put请求的映射-->`@PutMapping`
处理 delete 请求的映射--> `@DeleteMapping`
获取数据
[[../../IT/JAVA微服务核心/SpringBoot/SpringMvc#通过控制器方法的形参获取请求参数|../spring/SpringMvc > 通过控制器方法的形参获取请求参数)
@RequestParam
@DateTimeFormat(pattern= "")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@RequestBody
@pathVariable
@RequestHeader
@CookieValue

使用 jwt 则不会创建会话
除了上面的还可以获取
HttpServletRequest
HttpServletResponse
HttpSession
title: HttpServletRequest
- **核心作用:**
- HttpServletRequest 代表一个客户端(通常是浏览器)发送给服务器的 HTTP 请求。
- 它封装了请求的所有信息,包括请求方法、请求 URL、请求头、请求参数、请求体等。
- 通过 HttpServletRequest,服务端可以获取客户端传递的数据,并进行相应的处理。
- **主要功能:**
- **获取请求方法:** getMethod() (例如 "GET", "POST", "PUT", "DELETE")
- **获取请求 URL:**
- getRequestURL(): 获取完整的 URL (例如: http://localhost:8080/myapp/users?id=123).
- getRequestURI(): 获取 URL 的路径部分 (例如: /myapp/users).
- getContextPath(): 获取上下文路径 (例如: /myapp).
- getServletPath(): 获取 Servlet 的路径 (例如: /users).
- **获取请求参数:**
- getParameter(String name): 获取指定名称的请求参数的值,返回 String 类型。适用于简单参数。
- getParameterValues(String name): 获取指定名称的所有请求参数的值,返回 String[] 类型。适用于同一个参数有多个值的情况。
- getParameterMap(): 获取所有请求参数的 Map,Key 是参数名,Value 是 String[]。
- getQueryString(): 获取 URL 中的查询字符串(? 之后的部分)。
- **获取请求头:**
- getHeader(String name): 获取指定名称的请求头的值。
- getHeaders(String name): 获取指定名称的所有请求头的值,返回 Enumeration<String>。
- getHeaderNames(): 获取所有请求头的名称,返回 Enumeration<String>。
- **获取请求体:**
- getInputStream(): 获取请求体的输入流,用于读取二进制数据 (例如上传文件)。
- getReader(): 获取请求体的字符输入流,用于读取文本数据。
- **注意:** 如果使用 @RequestBody 注解, Spring MVC 会自动处理请求体,您不需要手动读取输入流。
- **获取客户端信息:**
- getRemoteAddr(): 获取客户端的 IP 地址。
- getRemoteHost(): 获取客户端的主机名。
- getRemotePort(): 获取客户端的端口号。
- **获取会话信息:**
- getSession(): 获取当前请求的会话对象,如果不存在则创建新的会话。
- getSession(boolean create): 获取当前请求的会话对象。create=true则如果不存在则创建新的会话,create=false 如果不存在返回null。
- **获取 Cookie:**
- getCookies(): 获取当前请求的所有Cookie对象,返回Cookie[]
title: **HttpServletResponse**
- **核心作用:**
- HttpServletResponse 代表服务器发送给客户端的 HTTP 响应。
- 它封装了响应的所有信息,包括响应状态码、响应头、响应体等。
- 通过 HttpServletResponse,服务端可以向客户端返回数据,例如 HTML、JSON、图片等。
- **主要功能:**
- **设置响应状态码:** setStatus(int sc) (例如: 200 表示成功, 404 表示找不到资源, 500 表示服务器内部错误)。
- **设置响应头:**
- setHeader(String name, String value): 设置响应头的键值对。
- addHeader(String name, String value): 添加一个响应头的键值对。
- setContentType(String type): 设置响应内容的 MIME 类型(例如: text/html, application/json, image/jpeg)。
- **设置响应体:**
- getWriter(): 获取字符输出流,用于写入文本数据。
- getOutputStream(): 获取字节输出流,用于写入二进制数据。
- **注意:** Spring MVC 通常会自动处理响应体,您不需要直接使用输出流。 例如使用@ResponseBody 注解,会由 Spring MVC 自动将返回值转换成 JSON 或 XML。
- **设置 Cookie:** addCookie(Cookie cookie): 向客户端添加一个 Cookie。
- **重定向:** sendRedirect(String location): 将客户端重定向到新的 URL。
- **使用场景:**
- 设置响应状态码,通知客户端请求处理的结果。
- 设置响应头,例如 Content-Type,告诉浏览器如何处理响应体。
- 写入响应体,将数据返回给客户端。
- 添加 Cookie,用于跟踪用户状态或存储用户偏好。
- 重定向到其他页面。
- 设置缓存策略,减少请求量。
title:HttpSession
- **用户首次访问:** 当一个用户第一次访问你的 Web 应用时,服务器(通常是Servlet 容器,比如 Tomcat)会执行以下操作:
4. **检查请求头/Cookie:** 服务器首先会检查客户端的请求头中是否包含名为 JSESSIONID 的 Cookie (默认 Session Cookie 名)。
5. **没有 Cookie:** 如果请求头中没有 JSESSIONID Cookie 或者 Cookie 中的 JSESSIONID 值与服务器端已有的任何会话都不匹配,那么服务器会认为这是一个新的用户会话。
6. **创建会话:** 服务器会创建一个新的 HttpSession 对象,并生成一个唯一的会话 ID(session ID),这个 ID 是一个随机字符串。
7. **设置 Cookie:** 服务器会将这个新的会话 ID 通过一个 Cookie(默认名为 JSESSIONID)设置到响应头中发送给客户端。浏览器收到响应后,会自动存储这个 Cookie,以便在后续请求中发送给服务器。
- **核心作用:**
- HttpSession 代表一个用户的会话,用于在多个请求之间存储和共享用户特定的数据。
- HTTP 协议是无状态的,因此需要 HttpSession 来跟踪用户的状态。
- **主要功能:**
- **存储数据:** setAttribute(String name, Object value): 将数据存储到会话中。
- **获取数据:** getAttribute(String name): 从会话中获取数据。
- **删除数据:** removeAttribute(String name): 从会话中删除数据。
- **使会话失效:** invalidate(): 使当前会话失效,会话中的数据将被删除。
- **获取会话 ID:** getId(): 获取当前会话的唯一标识符。
- **判断会话是否是新的:** isNew(): 判断当前会话是否是新的。
- **设置会话过期时间:** setMaxInactiveInterval(int interval):设置会话的最大不活动时间,单位为秒。 如果超过这个时间没有新的请求,会话将自动失效。
- **使用场景:**
- 存储用户的登录信息,例如用户名、用户 ID 等。
- 存储用户的购物车信息。
- 跟踪用户的访问状态。
- 存储用户偏好设置。
- 实现多步骤表单的中间数据存储。
过滤器和拦截器的区别
[[../../IT/JAVA微服务核心/JAVAWEB/JavaWeb#过滤器 Filter|JAVA微服务核心/JAVAWEB/JavaWeb > 过滤器 Filter)
filter 实现 Filter 接口
filterChain.doFilter(servletRequest,servletResponse)
可以设置过滤器链
interceptor 实现 HandlerInterceptor 接口
[[../../IT/JAVA微服务核心/JAVAWEB/JavaWeb#拦截器 Interceptor|JAVA微服务核心/JAVAWEB/JavaWeb > 拦截器 Interceptor)
实现接口,创建 WebMvcConfigurer 的配置类,重写 addInterceptors 方法,注册 HandlerInterceptor 实现类
[[../../IT/JAVA微服务核心/JAVAWEB/JavaWeb#^trzlo0|拦截路径)
RestFul
[[../../IT/JAVA微服务核心/SpringBoot/SpringMvc#RESTful|../spring/SpringMvc > RESTful)
保存 Post, 更新 PUT
删除 Delete, 查询 Get




使用配置文件
- 方式一 (繁琐):-
@Value ("${配置文件中的KEY}")(@Value注解只能一个一个的进行外部属性的注入) (适合偶尔使用) - 方式二: 创建一个 Bean 对象, 加上注解
@Data,@Component,@ConfigurationProperties (prefix = "aliyun. oss")[自动注入]注解,其他类需要使用时只需要@Autowired获取该 bean 对象 - 类中属性名必须与 yml 文件中 key 保持一致
其他
proxyBeanMethods = true(默认值) 是 @Configuration 注解的一个属性
proxyBeanMethods 参数设置为 false 时即为:Lite 模式。该模式下注入容器中的同一个组件无论被取出多少次都是不同的 bean 实例,直接返回新实例对象,在该模式下 SpringBoot 每次启动会跳过检查容器中是否存在该组件,每次调用配置类中的@Bean 方法都会创建一个新的 Bean 实例。
@autowire(required=false)
- 如果将
@Autowired注解的required属性设置为false(默认为true),则表示注入这个bean是非强制性的,如果找不到匹配的bean,Spring不会抛出异常,而是将目标字段或方法参数设置为null。
@autowire 注解在方法上则代表注入形参声明的类型
开发
![[../../IT/JAVA微服务核心/JAVAWEB/assets/JavaWeb/file-20241010014048986.png|assets/JavaWeb/file-20241010014048986.png)