Browse Source

4.3

libolin/feature-20260327153128-学习笔记
libolin 2 weeks ago
parent
commit
425d7237db
  1. 43
      李柏霖学习笔记/4.3.md

43
李柏霖学习笔记/4.3.md

@ -0,0 +1,43 @@
# 复习
依赖注入方面,`@Autowired` 是用得最多的,可以标注在字段、setter 方法或者构造方法上。`@Qualifier` 在有多个同类型 Bean 的时候用来指定具体注入哪一个。`@Resource` 和 `@Autowired` 功能差不多,不过它是按名称注入的。
配置相关的注解也很常用。`@Configuration` 标识配置类,`@Bean` 用来定义 Bean,`@Value` 用来注入配置文件中的属性值。我们项目里的数据库连接信息、Redis 配置这些都是用 `@Value` 来注入的。`@PropertySource` 用来指定配置文件的位置。
单例模式也是 Spring 的默认行为。默认情况下,Spring 容器中的 Bean 都是单例的,整个应用中只会有一个实例。这样可以节省内存,提高性能。可以通过 `@Scope` 注解来改变 Bean 的作用域,比如设置为 prototype 就是每次获取都创建新实例。
![二哥的 Java 进阶之路:@Scope注解](https://cdn.paicoding.com/stutymore/spring-20250618113356.png)
#### Spring如何实现单例模式
传统的单例模式是在类的内部控制只能创建一个实例,比如用 private 构造方法加 `static getInstance()` 这种方式。但是 Spring 的单例是容器级别的,同一个 Bean 在整个 Spring 容器中只会有一个实例。
具体的实现机制是这样的:Spring 在启动的时候会把所有的 Bean 定义信息加载进来,然后在 DefaultSingletonBeanRegistry 这个类里面维护了一个叫 singletonObjects 的 ConcurrentHashMap,这个 Map 就是用来存储单例 Bean 的。key 是 Bean 的名称,value 就是 Bean 的实例对象。
当我们第一次获取某个 Bean 的时候,Spring 会先检查 singletonObjects 这个 Map 里面有没有这个 Bean,如果没有就会创建一个新的实例,然后放到 Map 里面。后面再获取同一个 Bean 的时候,直接从 Map 里面取就行了,这样就保证了单例。
还有一个细节就是 Spring 为了解决循环依赖的问题,还用了三级缓存。除了 singletonObjects 这个一级缓存,还有 earlySingletonObjects 二级缓存和 singletonFactories 三级缓存。这样即使有循环依赖,Spring 也能正确处理。
而且 Spring 的单例是线程安全的,因为用的是 ConcurrentHashMap,多线程访问不会有问题。
#### bean
Bean 本质上就是由 Spring 容器管理的 Java 对象,但它和普通的 Java 对象有很大区别。普通的 Java 对象我们是通过 new 关键字创建的。而 Bean 是交给 Spring 容器来管理的,从创建到销毁都由容器负责。
从实际使用的角度来说,我们项目里的 Service、Dao、Controller 这些都是 Bean。比如 UserService 被标注了 `@Service` 注解,它就成了一个 Bean,Spring 会自动创建它的实例,管理它的依赖关系,当其他地方需要用到 UserService 的时候,Spring 就会把这个实例注入进去。
`@Primary` 注解标注主数据源,用 `@Qualifier` 来指定备用数据源。
当我们直接用 `@Autowired` 注解注入 DataSource 时,Spring 默认会使用 HikariDataSource;当加上 `@Qualifier("secondary")` 注解时,Spring 则会注入 BasicDataSource。
#### @Component@Bean 有什么区别?
首先从使用上来说,`@Component` 是标注在类上的,而 `@Bean` 是标注在方法上的。`@Component` 告诉 Spring 这个类是一个组件,请把它注册为 Bean,而 `@Bean` 则告诉 Spring 请将这个方法返回的对象注册为 Bean。
Loading…
Cancel
Save