文章目录
- Spring基础
- 1、Spring、SpringMVC、Mybatis与SpringBoot的区别
- 2、Spring中常用的注解及作用
- Spring IoC 、 DI、Bean
- 3、Spring IoC是什么,有什么好处,Spring中是怎么实现的?
- 4、Bean相关
- 5、@Component 和 @Bean 的区别是什么?
- 6、注入Bean的注解有哪些,@Autowired与@Resource的区别在哪?
- 7、Bean是线程安全的吗?
- 8、Bean的生命周期是怎么样的?
- Spring AoP
- Spring MVC
- SpringBoot
- Mybatis
Spring基础
1、Spring、SpringMVC、Mybatis与SpringBoot的区别
- Spring是一个轻量级的Java企业级开发框架,提供了很多功能和特性,如:
- 控制反转(IOC)
- 依赖注入(DI)
- 面向切面编程(AOP)
- Spring事务管理
- Spring MVC则是Spring框架的一部分,专注于Web应用程序的开发,提供如下功能:
- 接收请求
- 设置请求拦截器
- 响应数据
- 全局异常处理
- Mybatis则是数据持久层框架,与数据库打交道,可以使用简单的XML或者注解配置和映射数据库表格中的原始信息,完成系统中Java实体类与数据库中记录的映射。
- Spring Boot是一个简化了Spring应用开发的框架,通过起步依赖和自动配置,大大简化了spring配置的流程,使得开发者可以更专注于业务逻辑的实现。
2、Spring中常用的注解及作用
- 配置Bean相关:
- @Autowire:让Spring容器自动装配Bean到类中。
- @ComponentScan:通过自动扫描机制来发现和注册满足条件的组件。
- @Configuration:用于指定配置类,替代传统的XML配置文件。
- @Bean:用于在@Configuration类中声明Bean定义,供Spring容器管理。
- @Qualifier:与@Autowired一起使用,通过指定Bean名称解决自动装配的歧义性。
- @Value:用于注入简单值或表达式到Bean的属性。
- @Scope:用于指定Bean的作用域,如单例(Singleton)或原型(Prototype)。
- @ConfigurationProperties:用于绑定配置文件中的属性到Java类的字段上,支持批量绑定。
- SpringMVC相关:
- @Component:通用注解,标明该类是应该交由Spring管理的。如果一个Bean不知道属于哪个层,使用该注解。
- @RequestMapping:用于将HTTP请求映射到控制器的处理方法,例如:@RequestMapping(“/books”)
- @PathVariable:用于获取URL路径变量值并映射到方法参数。
// 处理URL: /books/{id}
@GetMapping("/{id}")
public String getBookById(@PathVariable Long id) {
// 处理方法逻辑
return "book_details";
}
- @RequestParam:用于获取请求参数的值并映射到方法参数。
// 处理URL: /books?category=fiction
@GetMapping
public String getBooksByCategory(@RequestParam("category") String category) {
// 使用category进行业务逻辑处理
// ...
return "books_by_category";
}
- @ResponseBody:用于将方法返回值直接作为HTTP响应的内容返回。
@RestController
@RequestMapping("/api")
public class BookController {
@PostMapping("/books")
public ResponseEntity<String> createBook(@RequestBody Book book) {
// 处理从请求体中解析出来的 Book 对象
// ...
return new ResponseEntity<>("Book created successfully", HttpStatus.CREATED);
}
}
- @Controller:控制层注解,处理HTTP请求并返回响应。此外还有@RestController注解,它是@Controller和@ResponseBody的合集。
- @Service:用于标识服务层类,通常用于注解Service组件。
- @Repository:用于标识数据访问层类,通常用于注解DAO组件。
- @Transactional:用于标识事务方法,启用方法级别的事务管理。
Spring IoC 、 DI、Bean
3、Spring IoC是什么,有什么好处,Spring中是怎么实现的?
IoC(Inversion of Control:控制反转) 是一种设计思想,是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理,即将对象的创建和管理的权力交由Spring容器。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/=或者注解即可,完全不用考虑对象是如何被创建出来的。简化应用开发,利用实现分层解耦。
在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value)注册表,Map 中存放的是各种Bean对象,key就是Bean的名称(或ID),value 是 Bean 的定义信息,包括类名、依赖关系、初始化方法、销毁方法等。
4、Bean相关
简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。
Bean的配置可以通过XML文件配置,也可以通过注解在设置。比如:
- @Component:通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用* @Component 注解标注。
- @Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。
- @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
- @Repository(仓库) : 对应持久层即 Dao 层,主要用于数据库相关操作。
5、@Component 和 @Bean 的区别是什么?
- @Component 注解作用于类,而@Bean注解作用于方法。
- @Component通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。
- @Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。
6、注入Bean的注解有哪些,@Autowired与@Resource的区别在哪?
Spring 内置的 @Autowired 以及 JDK 内置的 @Resource 和 @Inject 都可以用于注入 Bean。
- @Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解。Autowired 默认的注入方式为byType(根据类型进行匹配),
- @Resource默认注入方式为 byName(根据名称进行匹配)。
当一个接口存在多个实现类的情况下,@Autowired 和@Resource都需要通过名称才能正确匹配到对应的 Bean。
- @Autowired 可以通过 @Qualifier 注解来显式指定名称
- @Resource可以通过 name 属性来显式指定名称。
举个例子,SmsService 接口有两个实现类: SmsServiceImpl1和 SmsServiceImpl2,且它们都已经被 Spring 容器所管理。
// 报错,byName 和 byType 都无法匹配到 bean
@Autowired
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean
// smsServiceImpl1 就是我们上面所说的名称
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;
// 报错,byName 和 byType 都无法匹配到 bean
@Resource
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Resource
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;
7、Bean是线程安全的吗?
Spring 框架中的 Bean 是否线程安全,取决于其作用域和状态。
在多例(prototype)的作用域下,每次获取都创建一个新的bean实例,不存在资源竞争问题,所有没有线程安全问题。
在单例(singleton)作用域下,IoC容器只有唯一的bean实例,可能存在资源竞争问题,如果bean有状态即包含可变的成员变量,那么就存在线程安全问题。
对于有状态且为单例Bean的线程安全问题,常见的有两种解决办法:
- 在Bean中尽量避免定义可变的成员 变量
- 在类中定义ThreadLocal,将需要的成员变量保存在TheadLoacl使其线程私有化。
8、Bean的生命周期是怎么样的?
- IoC容器找到配置文件中Spring Bean的定义
- IoC容器利用Java 反射创建一个Bean的实例
- 如果涉及到一些Bean的属性赋值如使用了@Value注解,则利用set()方法设置属性值。
- 如果Bean实现了BeanNameAware接口,则调用setBeanName方法,传入Bean的名字。
Aware接口是在编译阶段内置在Bean中,用来与IoC容器打交道,获取Bean的相关信息时用的。4 - 7 都是一些Aware接口,了解Aware接口的概念即可,不用记得那么细致。
- 如果Bean实现了BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
- 如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory()方法,传入 BeanFactory对象的实例。
- 如果实现了其他 *.Aware接口,就调用相应的方法。
- 如果有和加载这个Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法。
即初始化前的Bean后处理器
- 如果 Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法。
InitializingBean是与Aware类似 的接口,是与Bean耦合的,InitializingBean接口会执行初始化逻辑
- 如果 Bean 在配置文件中的定义包含 init-method 属性,则执行init-method 指定的方法。
8 - 10 是Bean初始化时可以设置的三种回调,它们的顺序分别是 Bean初始化前的后处理器、InitializingBean内置接口、配置属性init - method
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
即销毁前的Bean后处理器
- 如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
DisposableBean 接口是与InitializingBean类似的耦合接口
- 如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
11-13是与初始化时相对应的,在销毁前的3种回调,它们的执行顺序与初始化是一样的,即 后处理器 、耦合接口、配置属性
上边列举的Bean的生命周期有点儿过长了:
简单来记忆:
Bean生命周期的主要脉络包括:
- 1、Bean配置
- 2、Bean实例化
- 3、Bean初始化
- 5、Bean的使用
- 4、Bean销毁
展开来讲包括:
- 1、找到配置文件中Bean定义
- 2、基于反射实例化Bean
- 3、如果Bean实现了Aware相关耦合接口,则执行对应实现方法
- 4、Bean初始化:
- Bean后处理器:前置处理
- 耦合接口: InitializingBean
- Bean配置属性:init-method指定的方法
- Bean后处理器:后置处理
- 5、Bean的使用
- 6、Bean销毁:
- Bean后处理器:销毁前置处理
- 耦合接口: DisposableBean
- Bean配置属性:destroy-method指定的方法
Spring AoP
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制
等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。