【框架小结】Spring
1.1. 关于Spring框架
Spring框架主要解决了创建对象、管理对象相关的问题。
Spring框架在创建了各对象之后,会持有这些对象的引用,相当于“把这些对象管理了起来”,所以,Spring框架也经常被称之为“Spring容器”。
1.2. 关于Spring框架创建对象
1.2.1. 关于通过组件扫描来创建组件对象
组件:每个项目中重要的组件部分,即可称之为组件。
在使用Spring框架时,可以通过@Component
/ @Controller
/ @Service
/ @Repository
这4个注解中的任意一个,将某个类标记为“组件”,并且,在Spring框架的作用范围内,这4个注解是完全等效的!之所以存在4个注解,主要是希望通过使用不同的注解,表现出对应的语义!
另外,在配置类上,可以使用@ComponentScan
的注解,开启“组件扫描”,此注解可以配置一个根包(basePackage),例如:
@ComponentScan("cn.tedu.csmall")
则Spring框架会扫描这个根包及其子孙包下所有的类,如果扫描到的类是组件,则Spring框架会自动创建这个类的对象,并把对象保存到Spring容器中!
另外,@Configuration
是比较特殊的组件注解,添加了此注解的类将是”配置类“,Spring在创建此类的对象时,会使用CGLib代理模式进行处理。
还有@RestController
、@ControllerAdvice
、@RestControllerAdvice
也能把类标记为”组件“,但是,这些注解是Spring MVC框架中定义的。
通过组件扫描创建的对象,这些对象在Spring容器中都称之为Spring Bean,每个Spring Bean都有一个Bean Name(Bean的名称),默认情况下,当此对象的类名第1个字母大写,且第2个字母小写时,Bean Name就是将类名首字母改为小写,例如BrandController
类型的对象的Bean Name就是brandController
,如果前2个字母的大小写不符合前序规则,则Bean Name就是类名。如果需要自行指定类名,可以配置@Component
等注解的参数,例如:@Component("beanName")
。
1.2.2. 使用@Bean
方法创建对象
使用Spring框架时,可以在配置类中自定义创建对象的方法,并在方法上添加@Bean
注解,则Spring框架会自动调用此方法,并将此方法返回的对象保存在Spring容器中,例如:
@Configuration
public class BeanConfiguration {
// 假设某Controller并没有通过组件扫描的做法来创建对象
@Bean
public BrandController brandController() {
return new BrandController();
}
}
使用此做法,默认的Bean Name就是方法名称,或者,通过配置@Bean
的参数来指定名称!
1.2.3. 关于以上2种做法的选取
如果是自定义的类型,推荐使用组件扫描的做法,如果不是自定义的类型,只能使用@Bean
方法!
1.3. Spring管理的对象的作用域
Spring管理的对象,默认情况下,是单例的!
如果要修改,可以使用@Scope("prototype")
注解组件类或@Bean
方法。
单例:在任何时刻,此类型的对象最多只有1个!
注意:Spring并没有使用到设计模式中的单例模式,只是管理的对象具有相同的特征。
被Spring管理的单例的对象,默认情况下,是预加载的,相当于单例模式中的”饿汉式“!
如果要修改,可以使用@Lazy
注解组件类或@Bean
方法。
预加载:加载Spring环境时就会创建这些对象!与之相反的概念是单例模式中的”懒汉式“!
单例模式(饿汉式)示例:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
单例模式(懒汉式)示例:
public class Singleton {
private static volatile Singleton instance;
private static final Object lock = new Object();
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (lock) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
1.4. 关于自动装配
自动装配:当被Spring管理对象的某个属性,或被Spring自动调用的方法的参数需要值时,Spring框架会自动从容器中查找合适的对象,为此属性或参数赋值。
关于”合适的对象“:要么类型匹配,要么名称匹配。
当属性需要被自动装配时,需要在属性上添加自动装配的注解,即添加@Autowired
注解,例如:
@RestController
public class BrandController {
@Autowired
private IBrandService brandService;
}
关于“被Spring自动调用的方法”,通常包括:
- 构造方法
@Bean
方法- 添加了
@Autowired
注解的方法,通常可能是Setter方法
关于@Autowired
的自动装配机制:
- Spring会先从容器中查询匹配类型的Bean的数量
- 0个:取决于
@Autowired
注解的required
属性true
:装配失败,在加载Spring环境时直接抛出异常false
:放弃自动装配,则此属性的值为null
- 1个:直接装配,且成功
- 多个:将尝试按照名称来自动装配
- 存在名称匹配的Bean:成功装配
- 不存在名称匹配的Bean:装配失败,在加载Spring环境时直接抛出异常
- 提示:可以在被装配的值上添加
@Qualifier
注解以指定某个Bean Name
- 0个:取决于