一、常用注解篇
1.1 Spring Boot常用注解有哪些?分别有什么作用?
✅ 正确回答思路:
我按功能分类来说明:
一、核心注解
1. @SpringBootApplication
这是Spring Boot的核心注解,组合了三个注解:
java
@SpringBootApplication
// 等价于
@SpringBootConfiguration // 相当于@Configuration
@EnableAutoConfiguration // 开启自动配置
@ComponentScan // 开启组件扫描
public class Application {
}
2. @Configuration
声明这是一个配置类,相当于XML配置文件:
java
@Configuration
public class AppConfig {
@Bean
public User user() {
return new User();
}
}
3. @Bean
在@Configuration类中,声明一个Bean:
java
@Bean(name = "user", initMethod = "init", destroyMethod = "destroy")
@Scope("singleton")
public User user() {
return new User();
}
二、组件注解
1. @Component
通用的组件注解:
java
@Component
public class MyComponent {
}
2. @Service
Service层的组件:
java
@Service
public class UserService {
}
3. @Repository
DAO层的组件:
java
@Repository
public class UserDao {
}
4. @Controller
Controller层的组件:
java
@Controller
public class UserController {
}
5. @RestController
RESTful API的Controller,组合了@Controller和@ResponseBody:
java
@RestController // 等价于@Controller + @ResponseBody
@RequestMapping("/api/user")
public class UserController {
}
这四个注解(@Service、@Repository、@Controller、@RestController)本质上都是@Component,只是语义不同。
三、依赖注入注解
1. @Autowired
自动注入Bean:
java
@Service
public class UserService {
@Autowired // 按类型注入
private UserDao userDao;
}
2. @Qualifier
配合@Autowired,按名称注入:
java
@Service
public class UserService {
@Autowired
@Qualifier("userDaoImpl") // 按名称注入
private UserDao userDao;
}
3. @Resource
Java标准注解,按名称注入:
java
@Service
public class UserService {
@Resource(name = "userDaoImpl") // 按名称注入
private UserDao userDao;
}
@Autowired vs @Resource:
| 注解 | 来源 | 默认方式 | 指定名称 |
|---|---|---|---|
| @Autowired | Spring | 按类型 | @Qualifier |
| @Resource | Java标准 | 按名称 | name属性 |
4. @Value
注入配置文件的值:
java
@Service
public class UserService {
@Value("${app.name}") // 从application.yml读取
private String appName;
@Value("${app.version:1.0}") // 默认值
private String version;
@Value("#{systemProperties['user.name']}") // SpEL表达式
private String userName;
}
四、配置属性注解
@ConfigurationProperties
批量注入配置:
java
@ConfigurationProperties(prefix = "app")
@Component
public class AppProperties {
private String name;
private String version;
private ServerConfig server;
// getter/setter
public static class ServerConfig {
private String host;
private int port;
// getter/setter
}
}
# application.yml
app:
name: MyApp
version: 1.0
server:
host: localhost
port: 8080
五、Web相关注解
1. @RequestMapping
映射请求URL:
java
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/list", method = RequestMethod.GET)
public String list() {
return "user/list";
}
}
2. @GetMapping、@PostMapping等
简化的请求映射:
java
@RestController
@RequestMapping("/api/user")
public class UserController {
@GetMapping("/{id}") // GET请求
public User getUser(@PathVariable Long id) {
return userService.getUser(id);
}
@PostMapping // POST请求
public User addUser(@RequestBody User user) {
return userService.addUser(user);
}
@PutMapping("/{id}") // PUT请求
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.updateUser(id, user);
}
@DeleteMapping("/{id}") // DELETE请求
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
3. @PathVariable
获取URL路径参数:
java
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
// URL: /user/123 → id = 123
}
@GetMapping("/user/{id}/order/{orderId}")
public Order getOrder(@PathVariable Long id, @PathVariable Long orderId) {
// URL: /user/123/order/456 → id = 123, orderId = 456
}
4. @RequestParam
获取URL查询参数:
java
@GetMapping("/user/search")
public List<User> search(
@RequestParam String name, // 必须有name参数
@RequestParam(required = false) Integer age, // age参数可选
@RequestParam(defaultValue = "1") int page // 默认值
) {
// URL: /user/search?name=张三&age=25&page=2
}
5. @RequestBody
获取请求体(JSON):
java
@PostMapping("/user")
public User addUser(@RequestBody User user) {
// 请求体: {"name": "张三", "age": 25}
// 自动转成User对象
}
6. @ResponseBody
返回JSON(而不是视图):
java
@Controller
public class UserController {
@GetMapping("/user/{id}")
@ResponseBody // 返回JSON
public User getUser(@PathVariable Long id) {
return userService.getUser(id);
}
}
// @RestController = @Controller + @ResponseBody
六、事务注解
@Transactional
声明事务:
java
@Service
public class UserService {
@Transactional(
propagation = Propagation.REQUIRED, // 传播行为
isolation = Isolation.DEFAULT, // 隔离级别
timeout = 30, // 超时时间(秒)
rollbackFor = Exception.class, // 回滚的异常
noRollbackFor = BusinessException.class // 不回滚的异常
)
public void addUser(User user) {
userDao.insert(user);
}
}
七、AOP注解
1. @Aspect
声明切面:
java
@Aspect
@Component
public class LogAspect {
}
2. @Pointcut
定义切点:
java
java
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
3. @Before、@After等
定义通知:
java
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("方法执行前: " + joinPoint.getSignature());
}
@After("execution(* com.example.service.*.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println("方法执行后: " + joinPoint.getSignature());
}
@Around("execution(* com.example.service.*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知-前");
Object result = pjp.proceed();
System.out.println("环绕通知-后");
return result;
}
}
八、条件注解
1. @Conditional
按条件注册Bean:
java
@Configuration
public class AppConfig {
@Bean
@Conditional(WindowsCondition.class) // Windows系统才注册
public DataSource windowsDataSource() {
return new DataSource();
}
}
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}
2. @ConditionalOnProperty
配置文件有指定属性才生效:
java
@Bean
@ConditionalOnProperty(name = "app.feature.enabled", havingValue = "true")
public FeatureService featureService() {
return new FeatureService();
}
3. @ConditionalOnClass
类路径有指定类才生效:
java
@Bean
@ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
public DataSource dataSource() {
return new DataSource();
}
九、异步和定时任务注解
1. @Async
异步执行:
java
@Service
public class AsyncService {
@Async // 异步执行,立即返回
public void sendEmail(String email) {
// 发送邮件(耗时操作)
}
@Async
public CompletableFuture<String> asyncMethod() {
// 异步执行,返回Future
return CompletableFuture.completedFuture("结果");
}
}
// 启用异步
@EnableAsync
@SpringBootApplication
public class Application {
}
2. @Scheduled
定时任务:
java
@Component
public class ScheduledTask {
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
public void dailyTask() {
System.out.println("定时任务执行");
}
@Scheduled(fixedRate = 5000) // 每5秒执行一次
public void fixedRateTask() {
System.out.println("固定频率任务");
}
@Scheduled(fixedDelay = 5000) // 上次执行完5秒后再执行
public void fixedDelayTask() {
System.out.println("固定延迟任务");
}
}
// 启用定时任务
@EnableScheduling
@SpringBootApplication
public class Application {
}
十、验证注解
JSR-303/JSR-380(Bean Validation)
java
public class User {
@NotNull(message = "ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度3-20")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 18, message = "年龄不能小于18")
@Max(value = 100, message = "年龄不能大于100")
private Integer age;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
@RestController
public class UserController {
@PostMapping("/user")
public User addUser(@RequestBody @Validated User user) { // @Validated触发验证
return userService.addUser(user);
}
}
💡 总结: Spring Boot常用注解分类:
- 核心: @SpringBootApplication、@Configuration、@Bean
- 组件: @Component、@Service、@Repository、@Controller、@RestController
- 注入: @Autowired、@Resource、@Value、@ConfigurationProperties
- Web: @RequestMapping、@GetMapping、@PathVariable、@RequestBody
- 事务: @Transactional
- AOP: @Aspect、@Before、@Around
- 条件: @ConditionalOnXxx
- 异步: @Async、@Scheduled
- 验证: @NotNull、@NotBlank、@Email
📌 二、Spring中的设计模式
2.1 Spring中用了哪些设计模式?
✅ 正确回答思路:
Spring框架大量使用了设计模式,我挑几个重要的说明:
一、工厂模式(Factory Pattern)
BeanFactory和ApplicationContext就是工厂:
java
// BeanFactory: Spring的Bean工厂
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
User user = (User) factory.getBean("user");
// ApplicationContext: 增强的工厂
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = context.getBean(User.class);
Spring的FactoryBean:
java
@Component
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
// 自定义创建逻辑
User user = new User();
user.setName("张三");
return user;
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
// 使用
@Autowired
private User user; // 注入的是getObject()返回的对象
二、单例模式(Singleton Pattern)
Spring Bean默认就是单例:
java
@Service
@Scope("singleton") // 默认就是singleton,可以不写
public class UserService {
}
Spring的单例和传统单例的区别:
- 传统单例: JVM内只有一个实例
- Spring单例: IOC容器内只有一个实例
Spring如何保证单例:
java
// 伪代码:Spring的单例池
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public Object getSingleton(String beanName) {
Object singleton = singletonObjects.get(beanName);
if (singleton == null) {
synchronized (this.singletonObjects) {
singleton = singletonObjects.get(beanName);
if (singleton == null) {
singleton = createBean(beanName); // 创建Bean
singletonObjects.put(beanName, singleton);
}
}
}
return singleton;
}
三、代理模式(Proxy Pattern)
Spring AOP就是基于代理模式:
- JDK动态代理
- CGLIB代理
前面讲过了,不再赘述。
四、模板方法模式(Template Method Pattern)
JdbcTemplate:
java
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
// 模板方法:jdbcTemplate封装了JDBC的通用流程
return jdbcTemplate.queryForObject(
"SELECT * FROM user WHERE id = ?",
new BeanPropertyRowMapper<>(User.class),
id
);
}
}
jdbcTemplate.query()的实现(简化版):
java
public <T> T query(String sql, RowMapper<T> rowMapper, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1. 获取连接(模板方法)
conn = getConnection();
// 2. 创建PreparedStatement(模板方法)
ps = conn.prepareStatement(sql);
// 3. 设置参数(模板方法)
setParameters(ps, args);
// 4. 执行查询(模板方法)
rs = ps.executeQuery();
// 5. 映射结果(钩子方法,由用户实现)
return rowMapper.mapRow(rs, 0);
} finally {
// 6. 释放资源(模板方法)
close(rs, ps, conn);
}
}
五、观察者模式(Observer Pattern)
Spring的事件机制:
java
// 1. 定义事件
public class UserRegisterEvent extends ApplicationEvent {
private User user;
public UserRegisterEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
// 2. 发布事件
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void register(User user) {
// 注册用户
userDao.insert(user);
// 发布事件
eventPublisher.publishEvent(new UserRegisterEvent(this, user));
}
}
// 3. 监听事件
@Component
public class EmailListener implements ApplicationListener<UserRegisterEvent> {
@Override
public void onApplicationEvent(UserRegisterEvent event) {
User user = event.getUser();
// 发送注册邮件
emailService.sendWelcomeEmail(user.getEmail());
}
}
// 或者用@EventListener注解
@Component
public class PointsListener {
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
// 赠送注册积分
pointsService.givePoints(event.getUser().getId(), 100);
}
}
六、策略模式(Strategy Pattern)
Resource资源加载:
java
// Resource接口:策略接口
public interface Resource {
InputStream getInputStream() throws IOException;
}
// 不同的实现:具体策略
public class ClassPathResource implements Resource {
// 从类路径加载
}
public class FileSystemResource implements Resource {
// 从文件系统加载
}
public class UrlResource implements Resource {
// 从URL加载
}
// 使用
Resource resource = new ClassPathResource("application.yml");
InputStream is = resource.getInputStream();
七、适配器模式(Adapter Pattern)
Spring MVC的HandlerAdapter:
java
// HandlerAdapter接口
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);
}
// 不同的适配器
public class RequestMappingHandlerAdapter implements HandlerAdapter {
// 适配@RequestMapping注解的方法
}
public class HttpRequestHandlerAdapter implements HandlerAdapter {
// 适配HttpRequestHandler接口
}
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
// 适配Controller接口
}
DispatcherServlet选择合适的适配器:
java
HandlerAdapter adapter = getHandlerAdapter(handler);
ModelAndView mav = adapter.handle(request, response, handler);
八、装饰器模式(Decorator Pattern)
Spring的BeanWrapper:
java
BeanWrapper wrapper = new BeanWrapperImpl(user);
wrapper.setPropertyValue("name", "张三"); // 增强了属性访问
九、责任链模式(Chain of Responsibility Pattern)
Spring MVC的拦截器链:
java
public class HandlerExecutionChain {
private final Object handler;
private HandlerInterceptor[] interceptors;
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) {
// 责任链模式:依次执行拦截器
for (HandlerInterceptor interceptor : interceptors) {
if (!interceptor.preHandle(request, response, handler)) {
return false;
}
}
return true;
}
}
十、总结表格
| 设计模式 | 应用场景 | 示例 |
|---|---|---|
| 工厂模式 | 创建Bean | BeanFactory、FactoryBean |
| 单例模式 | Bean作用域 | singleton Bean |
| 代理模式 | AOP | JDK动态代理、CGLIB |
| 模板方法 | 封装通用流程 | JdbcTemplate、RestTemplate |
| 观察者模式 | 事件机制 | ApplicationEvent、ApplicationListener |
| 策略模式 | 不同实现方式 | Resource加载 |
| 适配器模式 | 适配不同类型 | HandlerAdapter |
| 装饰器模式 | 增强功能 | BeanWrapper |
| 责任链模式 | 多个处理器 | 拦截器链 |
💡 总结: Spring框架大量使用了设计模式,这些设计模式让Spring具备了:
- 灵活性: 可以轻松扩展和替换
- 解耦性: 各个模块职责清晰
- 可维护性: 代码结构清晰,易于理解
💡 面试加分项: "Spring框架是学习设计模式的最佳实践,通过阅读Spring源码,可以深入理解这些设计模式的实际应用。"
📌 三、面试回答技巧总结
1. 分层次回答
- 先说"是什么"(概念)
- 再说"为什么"(原理)
- 最后说"怎么用"(实践)
2. 结合实际项目
- 不要只说理论,一定要说"我在项目中..."
- 说具体的场景和解决方案
- 体现你真正用过Spring
3. 对比说明
- 比如说IOC: 传统方式 vs IOC方式
- 说代理: JDK动态代理 vs CGLIB
- 对比能体现你理解深度
4. 画图辅助(如果可以)
- IOC容器启动流程
- SpringMVC请求处理流程
- Bean生命周期
- 能让面试官更直观理解
5. 适当展示深度
- 可以提到源码中的关键类
- 比如"AutoConfigurationImportSelector加载自动配置类"
- 但不要过度炫技,说不清楚反而减分
6. 诚实应对不会的
- 不会就说不会,但可以说"我的理解是..."
- 或者说"这个问题我回去研究一下"
- 表现出学习的态度
7. 控制时间
- 每个问题2-3分钟
- 不要太简短(显得不懂),也不要太啰嗦
- 看面试官反应,如果他想深入,会追问的
8. 高频必考题 一定要准备的:
- IOC和DI
- AOP原理(JDK动态代理vs CGLIB)
- Bean生命周期
- 三级缓存解决循环依赖
- 事务传播行为
- 事务失效场景
- SpringMVC流程
- Spring Boot自动配置原理
📌 四、总结
这篇Spring面试八股文,我尽量用"人话"把技术点讲清楚,并且提供了大量实际代码和项目经验。
重点回顾:
1. Spring核心
- IOC(控制反转)和DI(依赖注入)
- IOC容器启动流程
- 三级缓存解决循环依赖
2. AOP
- AOP概念和应用场景
- JDK动态代理 vs CGLIB代理
- Spring AOP实现原理
3. 事务
- 7种事务传播行为
- 事务失效的9种情况
4. Spring MVC
- SpringMVC的9步工作流程
- 拦截器vs过滤器
5. Spring Boot
- 自动配置原理(spring.factories + @ConditionalOnXxx)
- 启动流程
6. Bean生命周期
- 实例化→属性赋值→Aware回调→初始化→使用→销毁
7. 常用注解
- @SpringBootApplication、@Autowired、@Transactional等
8. 设计模式
- 工厂、单例、代理、模板方法、观察者等
最后的建议:
- 理解比背诵重要: 理解了原理,才能灵活回答
- 实战经验比理论重要: 能说出"我在项目中..."更有说服力
- 能说出"为什么"比知道"是什么"重要: 体现你的深度
如果这篇文章对你有帮助,记得收藏起来,面试前看一遍,效果更佳!