## 什么是spring Spring 是一款开源的轻量级 Java 开发框架,它使创建 Java 企业应用程序变得容易。它提供了在企业环境中使用 Java 语言所需的一切,并可以根据应用程序的需求灵活地创建多种架构。 Spring 提供的核心功能主要是 IoC 和 AOP ## Spring IoC **IoC(Inversion of Control:控制反转)** 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。 **为什么叫控制反转?** - **控制**:指的是对象创建(实例化、管理)的权力 - **反转**:控制权交给外部环境(Spring 框架、IoC 容器) ## 依赖查找和依赖注入的区别是什么? * 依赖查找:主动查找依赖的方式。依赖查找的对象包含spring beandefinition以及单例对象 * 依赖注入:spring容易自动依赖绑定的方式。依赖注入还包含Resolvable Dependency以及@value对象 ## Spring Bean 作用域 | 作用域 | 说明 | | ------------- | ---------------------------------------------------------- | | **singleton** | 默认 Spring Bean 作用域,一个 BeanFactory 有且仅有一个实例 | | **prototype** | 原型作用域,每次依赖查找和依赖注入生成新 Bean 对象 | | request | 将 Spring Bean 存储在 ServletRequest 上下文中 | | session | 将 Spring Bean 存储在 HttpSession 中 | | application | 将 Spring Bean 存储在 ServletContext 中 | ## @Autowired 和 @Resource 的区别是什么? * `@Autowired` 是 Spring 提供的注解,`@Resource` 是 JDK 提供的注解。 * `Autowired` 默认的注入方式为`byType`(根据类型进行匹配),`@Resource`默认注入方式为 `byName`(根据名称进行匹配)。 * 当一个接口存在多个实现类的情况下,`@Autowired` 和`@Resource`都需要通过名称才能正确匹配到对应的 Bean。`Autowired` 可以通过 `@Qualifier` 注解来显式指定名称,`@Resource`可以通过 `name` 属性来显式指定名称。 ## Bean 是线程安全的吗? Spring 框架中的 Bean 是否线程安全,取决于其作用域和状态。 大部分 Bean 实际都是无状态(没有定义可变的成员变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。 对于有状态单例 Bean 的线程安全问题,常见的有两种解决办法: 1. 在 Bean 中尽量避免定义可变的成员变量。 2. 在类中定义一个 `ThreadLocal` 成员变量,将需要的可变成员变量保存在 `ThreadLocal` 中(推荐的一种方式)。 ## Spring Boot自动装配原理 1. 在Spring Boot项目中有一个注解`@SpringBootApplication`,这个注解是对三个注解进行了封装:`@SpringBootConfiguration`、`@EnableAutoConfiguration`、`@ComponentScan` 其中`@EnableAutoConfiguration`是实现自动化配置的核心注解。 2. 该注解通过`@Import`注解导入`AutoConfigurationImportSelector`,这个类实现了一个导入器接口`ImportSelector`。在该接口中存在一个方法`selectImports`, 3. 该方法的返回值是一个数组,数组中存储的就是要被导入到`spring`容器中的类的全类名。在`AutoConfigurationImportSelector`类中重写了这个方法, 4. 该方法内部就是读取了项目的`classpath`路径下`META-INF/spring.factories`文件中的所配置的类的全类名。 5. 在这些配置类中所定义的`Bean`会根据条件注解所指定的条件来决定是否需要将其导入到`Spring`容器中。