适用于 Java 后端校招、实习面试。 回答原则:先一句话概括,再展开 2~5 个关键点。
定义:
循环依赖就是两个或多个 Bean 相互依赖,导致 Bean 无法正常创建。
例如:
@Service
class A{
@Autowired
private B b;
}
@Service
class B{
@Autowired
private A a;
}
A 创建需要 B,B 创建又需要 A。
注意:
Spring 使用三级缓存解决单例 Bean 的循环依赖。
三级缓存:
一级缓存:singletonObjects
↓
存放完整 Bean
二级缓存:earlySingletonObjects
↓
存放提前暴露的 Bean
三级缓存:singletonFactories
↓
存放 ObjectFactory,用于生成代理对象
创建流程:
创建A
↓
放入三级缓存
↓
创建B
↓
B依赖A
↓
从三级缓存获取A
↓
B创建完成
↓
A创建完成
↓
放入一级缓存
二级缓存可以解决普通循环依赖。
但是 Spring 支持 AOP。
如果 Bean 需要生成代理对象:
三级缓存保存的是
ObjectFactory
真正需要的时候才调用
getObject()
生成代理对象。
如果只有二级缓存:
可能提前暴露的是原始对象。
最终容器放进去的是代理对象。
导致:
A引用的是原始对象
别人获取的是代理对象
整个容器出现两个对象。
总结:
一级缓存:最终 Bean
二级缓存:提前暴露 Bean
三级缓存:延迟创建代理对象
IOC(Inversion of Control)
控制反转。
以前:
UserService service = new UserService();
现在:
对象交给 Spring 创建。
程序只负责使用对象。
控制权由程序员交给 Spring。
主要有:
DI(Dependency Injection)
依赖注入。
Spring 在创建 Bean 时,把依赖对象自动注入进去。
例如:
@Autowired
private UserService service;
IOC 是思想。
DI 是 IOC 的具体实现。
Bean 就是交给 Spring 容器管理的对象。
例如:
@Service
public class UserService{
}
Spring 会:
Spring 最底层 IOC 容器。
特点:
ApplicationContext 是 BeanFactory 的升级版。
特点:
BeanFactory:
ApplicationContext:
FactoryBean 是一个工厂 Bean。
作用:
创建其他 Bean。
例如:
class MyFactoryBean implements FactoryBean<User>{
}
获取:
getBean("myFactoryBean")
返回的是:
User
不是:
MyFactoryBean
如果获取 FactoryBean 本身:
getBean("&myFactoryBean")
ObjectFactory 是 Spring 提供的对象工厂接口。
作用:
延迟获取 Bean。
三级缓存保存的就是:
ObjectFactory
singleton(默认)
整个容器只有一个 Bean。
prototype
每次获取都是新对象。
request
一次 HTTP 请求。
session
一个 Session。
application
整个 ServletContext。
三种:
① 构造器注入(推荐)
② Setter 注入
③ 字段注入(@Autowired)
企业推荐:
构造器注入。
AOP:
面向切面编程。
作用:
不修改源码。
统一增强功能。
例如:
Spring Boot 默认:
CGLIB(Spring Boot 2.x+)。
JDK 动态代理:
CGLIB:
实例化
↓
依赖注入
↓
Aware 接口
↓
BeanPostProcessor.before
↓
@PostConstruct
↓
InitializingBean
↓
init-method
↓
Bean 可以使用
↓
@PreDestroy
↓
DisposableBean
↓
destroy-method
Spring 提供的 Web MVC 框架。
职责:
浏览器
↓
DispatcherServlet
↓
HandlerMapping
↓
HandlerAdapter
↓
Controller
↓
Service
↓
DAO
↓
返回 ModelAndView
↓
ViewResolver
↓
浏览器
前后端分离:
Controller 返回 JSON。
四种:
七种:
REQUIRED(默认)
SUPPORTS
MANDATORY
REQUIRES_NEW
NOT_SUPPORTED
NEVER
NESTED
重点:
常见情况:
@Autowired:
按类型注入。
多个 Bean:
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;
按名称指定 Bean。
@Component:
自动扫描注册。
@Bean:
手动注册。
通常第三方类:
使用 @Bean。
本质:
都是 Component。
区别:
Spring:
只保证单例。
不保证线程安全。
建议:
Bean 设计成无状态。
共享变量自己加锁。
main()
↓
SpringApplication.run()
↓
创建 ApplicationContext
↓
扫描 Bean
↓
IOC
↓
AOP
↓
自动装配
↓
启动 Tomcat
↓
启动完成
RESTful:
URL 表示资源。
HTTP 方法表示操作。
例如:
GET /users
POST /users
PUT /users/1
DELETE /users/1
| Filter | Interceptor |
|---|---|
| Servlet 规范 | Spring 提供 |
| Servlet 容器管理 | Spring 容器管理 |
| 可过滤所有请求 | 主要拦截 Controller 请求 |
| 生命周期早 | 生命周期晚 |
| 常用于编码、跨域、XSS | 常用于登录、权限、日志 |
⭐⭐⭐⭐⭐
⭐⭐⭐⭐