|
|
@ -0,0 +1,43 @@ |
|
|
|
|
|
# 复习 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
依赖注入方面,`@Autowired` 是用得最多的,可以标注在字段、setter 方法或者构造方法上。`@Qualifier` 在有多个同类型 Bean 的时候用来指定具体注入哪一个。`@Resource` 和 `@Autowired` 功能差不多,不过它是按名称注入的。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
配置相关的注解也很常用。`@Configuration` 标识配置类,`@Bean` 用来定义 Bean,`@Value` 用来注入配置文件中的属性值。我们项目里的数据库连接信息、Redis 配置这些都是用 `@Value` 来注入的。`@PropertySource` 用来指定配置文件的位置。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
单例模式也是 Spring 的默认行为。默认情况下,Spring 容器中的 Bean 都是单例的,整个应用中只会有一个实例。这样可以节省内存,提高性能。可以通过 `@Scope` 注解来改变 Bean 的作用域,比如设置为 prototype 就是每次获取都创建新实例。 |
|
|
|
|
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
|
|
|
|
#### 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。 |