Spring-面试题(76)
摘要:
1、通俗易懂,适合小白
2、仅做面试复习用,部分来源网络,博文免费,知识无价,侵权请联系!
1. 什么是 Spring 框架?有什么优势?
答案:Spring 是一个轻量级的开源 Java 开发框架,用于构建企业级应用程序。它的核心特性包括依赖注入(DI)和面向切面编程(AOP)。
优势:
- 轻量级和非侵入式
- 控制反转(IoC)和依赖注入(DI)
- 面向切面编程(AOP)
- 提供模板类简化JDBC、Hibernate等技术的使用
- 事务管理
- 模块化设计
- 易于测试
示例:
// 传统方式
UserService userService = new UserServiceImpl();// Spring方式
@Autowired
private UserService userService;
2. Spring框架的设计目标,设计理念,和核心是什么?
答案:
- 设计目标:简化Java企业级开发,提供一站式解决方案
- 设计理念:基于POJO的轻量级和最小侵入性编程
- 核心:IoC容器和AOP框架
3. Spring 框架中使用了哪些设计模式?
答案:
- 工厂模式:BeanFactory
- 单例模式:默认的bean作用域
- 代理模式:AOP实现
- 模板方法模式:JdbcTemplate等
- 观察者模式:事件驱动模型
- 适配器模式:HandlerAdapter
- 装饰者模式:BeanWrapper
- 策略模式:Resource接口的不同实现
4. 简述一下 Spring 依赖注入几种实现方式?
答案:
- 构造器注入
- Setter方法注入
- 字段注入(使用@Autowired)
- 方法注入
示例:
// 构造器注入
public class UserService {private UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}// Setter注入
public class UserService {private UserRepository userRepository;public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}
}// 字段注入
public class UserService {@Autowiredprivate UserRepository userRepository;
}
5. Spring 中常用的注解包含哪些?
答案:
- @Component, @Service, @Repository, @Controller
- @Autowired, @Qualifier
- @Configuration, @Bean
- @Scope
- @RequestMapping, @GetMapping, @PostMapping等
- @Transactional
- @Value
- @Aspect, @Before, @After等AOP注解
6. Spring 支持哪几种 bean 作用域?
答案:
- singleton:默认,每个容器中一个实例
- prototype:每次请求创建一个新实例
- request:每个HTTP请求一个实例
- session:每个HTTP会话一个实例
- application:整个Web应用生命周期一个实例
- websocket:每个WebSocket会话一个实例
示例:
@Bean
@Scope("prototype")
public MyBean myBean() {return new MyBean();
}
7. Spring 中通知类型有哪些?
答案:
- 前置通知(Before advice):方法执行前执行
- 后置通知(After returning advice):方法正常返回后执行
- 异常通知(After throwing advice):方法抛出异常后执行
- 最终通知(After (finally) advice):方法执行后执行(无论是否异常)
- 环绕通知(Around advice):包围方法执行,可控制是否执行方法
示例:
@Aspect
public class LoggingAspect {@Before("execution(* com.example.service.*.*(..))")public void beforeAdvice(JoinPoint joinPoint) {System.out.println("Before method: " + joinPoint.getSignature());}@Around("execution(* com.example.service.*.*(..))")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("Before method execution");Object result = joinPoint.proceed();System.out.println("After method execution");return result;}
}
8. Spring AOP 连接点和切入点是什么?
答案:
- 连接点(JoinPoint):程序执行过程中的特定点,如方法调用或异常抛出
- 切入点(Pointcut):用于定义哪些连接点会被通知匹配的表达式
9. Spring AOP 代理模式是什么?
答案:Spring AOP使用动态代理实现,主要有两种方式:
- JDK动态代理:基于接口的代理
- CGLIB代理:基于类的代理(当目标类没有实现接口时使用)
10. Spring 框架有哪些特点?
答案:
- 轻量级
- 控制反转(IoC)
- 面向切面编程(AOP)
- 容器化
- MVC框架
- 事务管理
- 异常处理
- 与各种技术集成(JDBC, ORM, JMS等)
11. 简述一下 Spring 源码架构及体系结构?
答案:Spring框架由多个模块组成,主要分为:
- 核心容器(Core Container):Beans, Core, Context, SpEL
- AOP和Instrumentation
- 数据访问/集成:JDBC, ORM, OXM, JMS, Transactions
- Web:Web, Web-MVC, Web-Socket, Web-Portlet
- Test:支持单元测试和集成测试
12. Spring 提供几种配置方式设置元数据?
答案:
- XML配置
- 注解配置
- Java配置(基于@Configuration和@Bean)
- Groovy DSL配置
示例:
// Java配置示例
@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}
}// XML配置示例
<bean id="myService" class="com.example.MyServiceImpl"/>
13. Spring 中单例 bean 是线程安全的吗?
答案:Spring框架本身不保证单例bean的线程安全性。单例bean的线程安全性取决于bean的实现。如果bean是无状态的(即不包含可变的成员变量),则它是线程安全的;如果有状态,则需要开发者自己处理线程安全问题。
示例:
// 无状态bean,线程安全
@Service
public class StatelessService {public String process(String input) {return input.toUpperCase();}
}// 有状态bean,非线程安全
@Service
public class StatefulService {private int counter; // 可变状态public void increment() {counter++;}// 需要同步处理public synchronized void safeIncrement() {counter++;}
}
14. Spring 中 @Component 和 @Bean 注解有什么区别?
答案:
比较点 | @Component | @Bean |
---|---|---|
使用方式 | 类级别注解 | 方法级别注解 |
自动发现 | 通过组件扫描 | 显式定义在配置类中 |
自定义ID | 通过value属性 | 通过name属性 |
适用场景 | 自己的类 | 第三方库的类 |
依赖注入 | 自动 | 通过方法参数 |
示例:
// @Component使用
@Component("myComponent")
public class MyComponent {// ...
}// @Bean使用
@Configuration
public class AppConfig {@Bean(name = "myBean")public MyBean myBean() {return new MyBean();}
}
15. Spring 事务管理的方式有几种?
答案:
- 编程式事务管理:通过TransactionTemplate或PlatformTransactionManager
- 声明式事务管理:通过@Transactional注解或XML配置
示例:
// 编程式事务
@Autowired
private TransactionTemplate transactionTemplate;public void doInTransaction() {transactionTemplate.execute(status -> {// 业务逻辑return null;});
}// 声明式事务
@Transactional
public void transactionalMethod() {// 业务逻辑
}
16. Spring 中事务有哪几种隔离级别?
答案:
- DEFAULT:使用数据库默认隔离级别
- READ_UNCOMMITTED:读未提交
- READ_COMMITTED:读已提交
- REPEATABLE_READ:可重复读
- SERIALIZABLE:串行化
示例:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void readCommittedMethod() {// ...
}
17. Spring 中事务有哪几种传播行为?
答案:
- REQUIRED:默认,如果当前有事务就加入,没有就新建
- SUPPORTS:支持当前事务,如果没有就不以事务方式执行
- MANDATORY:必须在事务中运行,否则抛出异常
- REQUIRES_NEW:新建事务,如果当前有事务就挂起
- NOT_SUPPORTED:不以事务方式执行,如果当前有事务就挂起
- NEVER:不以事务方式执行,如果当前有事务就抛出异常
- NESTED:如果当前有事务,则在嵌套事务中执行
示例:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNewMethod() {// ...
}
18. Spring 事务都有哪些特性?
答案:
- 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成
- 一致性(Consistency):事务执行前后,数据库从一个一致状态变到另一个一致状态
- 隔离性(Isolation):事务执行不受其他事务干扰
- 持久性(Durability):事务一旦提交,其结果就是永久性的
19. Spring 中如何开启定时任务?
答案:
- 在配置类上添加@EnableScheduling
- 在方法上添加@Scheduled注解
示例:
@Configuration
@EnableScheduling
public class SchedulingConfig {// 配置类
}@Component
public class ScheduledTasks {@Scheduled(fixedRate = 5000)public void reportCurrentTime() {System.out.println("Current time: " + new Date());}@Scheduled(cron = "0 15 10 * * ?")public void scheduledTask() {// 每天10:15执行}
}
20. Spring 中自动装配 Bean 有哪些方式?
答案:
- no:默认,不自动装配
- byName:根据属性名自动装配
- byType:根据属性类型自动装配
- constructor:通过构造器自动装配
- autodetect:已废弃,Spring 3.0后不再支持
示例:
// XML配置
<bean id="userService" class="com.example.UserService" autowire="byType"/>// 注解方式
@Service
public class UserService {@Autowired // byTypeprivate UserRepository userRepository;@Autowiredpublic UserService(@Qualifier("userRepo") UserRepository userRepository) {// constructor with qualifier}
}
21. Spring 中自动装配有那些局限性?
答案:
- 基本数据类型和String等简单类型无法自动装配
- 模糊性:当有多个相同类型的bean时,需要@Qualifier指定
- 覆盖可能性:显式配置会覆盖自动装配
- 不够直观:自动装配的依赖关系不如显式配置清晰
- 文档生成工具可能无法识别自动装配的依赖关系
22. Spring 管理事务默认回滚的异常有哪些?
答案:默认情况下,Spring事务只在遇到RuntimeException和Error时回滚,检查型异常(checked exception)不会导致回滚。
23. Spring 中事务如何指定回滚的异常?
答案:使用@Transactional注解的rollbackFor和rollbackForClassName属性指定回滚的异常类,使用noRollbackFor和noRollbackForClassName属性指定不回滚的异常类。
示例:
@Transactional(rollbackFor = {SQLException.class}, noRollbackFor = {IllegalArgumentException.class})
public void transactionalMethod() throws SQLException {// ...
}
24. 什么是Spring IOC 容器?
答案:IoC(Inversion of Control)容器是Spring框架的核心,负责实例化、配置和组装bean。它通过读取配置元数据(XML或注解)来管理应用对象的生命周期和依赖关系。
25. Spring 中 IOC的优点是什么?
答案:
- 松耦合:对象间依赖由容器管理
- 易于测试:可以轻松替换依赖的实现
- 可维护性:配置集中管理
- 灵活性:通过配置改变应用行为而不修改代码
- 复用性:bean可以被多个应用共享
26. Spring 中 IOC 和 DI 有什么区别?
答案:
- IoC(控制反转):是一种设计原则,将对象的创建和管理权从应用程序代码转移到容器
- DI(依赖注入):是实现IoC的一种方式,容器通过构造函数、setter方法或字段注入依赖关系
简单说:IoC是概念,DI是实现方式。
27. Bean 工厂和 Application contexts 有什么区别?
答案:
比较点 | BeanFactory | ApplicationContext |
---|---|---|
功能 | 基本功能 | 扩展功能(国际化、事件传播等) |
加载方式 | 延迟加载 | 预加载(启动时创建所有单例) |
实现类 | XmlBeanFactory | ClassPathXmlApplicationContext, AnnotationConfigApplicationContext等 |
适用场景 | 资源受限环境 | 大多数企业应用 |
28. 什么是Spring beans?
答案:Spring beans是由Spring IoC容器管理的对象,这些对象根据配置元数据(如XML或注解)创建、组装和管理。
29. 一个 Spring Bean 定义包含什么?
答案:
- 类名(实际实现类)
- Bean行为配置(作用域、生命周期回调等)
- 依赖关系(其他bean的引用)
- 其他配置值(如连接池大小)
示例:
<bean id="userService" class="com.example.UserServiceImpl" scope="singleton" init-method="init" destroy-method="cleanup"><property name="userRepository" ref="userRepository"/><property name="maxUsers" value="100"/>
</bean>
30. Spring 中如何定义类的作用域?
答案:使用@Scope注解或在XML中配置scope属性。
示例:
@Component
@Scope("prototype")
public class PrototypeBean {// ...
}// XML方式
<bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/>
31. Spring 中内部 bean 是什么?
答案:内部bean是在另一个bean的property或constructor-arg元素中定义的bean,它没有自己的id/name,不能被其他bean引用,只能用于包含它的bean。
示例:
<bean id="outerBean" class="com.example.OuterBean"><property name="innerBean"><bean class="com.example.InnerBean"/></property>
</bean>
32. Spring 中如何注入一个 java 集合?
答案:在XML中使用, ,
示例:
<bean id="collectionBean" class="com.example.CollectionBean"><property name="list"><list><value>value1</value><value>value2</value></list></property><property name="map"><map><entry key="key1" value="value1"/><entry key="key2" value="value2"/></map></property>
</bean>
@Configuration
public class CollectionConfig {@Beanpublic List<String> stringList() {return Arrays.asList("value1", "value2");}@Beanpublic Map<String, String> stringMap() {Map<String, String> map = new HashMap<>();map.put("key1", "value1");map.put("key2", "value2");return map;}
}
33. Spring 中什么是 bean 装配?有哪些方式?
答案:Bean装配是指将bean连接在一起的过程,Spring容器需要知道哪些bean需要被装配以及如何装配这些依赖关系。
装配方式:
- XML显式配置
- Java显式配置(@Configuration和@Bean)
- 隐式bean发现和自动装配(@ComponentScan和@Autowired)
34. Spring 中什么是 bean 的自动装配?
答案:自动装配是Spring容器自动识别和满足bean之间依赖关系的过程,开发者不需要显式指定依赖关系。通过@Autowired注解或XML中的autowire属性实现。
35. FileSystemResource 和 ClassPathResource 有何区别?
答案:
比较点 | FileSystemResource | ClassPathResource |
---|---|---|
路径前缀 | 无或file: | classpath: |
加载方式 | 文件系统 | 类路径 |
适用场景 | 绝对路径或相对于当前工作目录 | 打包在JAR/WAR中的资源 |
可移植性 | 较低(依赖文件系统) | 较高 |
示例:
Resource fileSystemResource = new FileSystemResource("/path/to/file.txt");
Resource classPathResource = new ClassPathResource("config/file.txt");
36. 什么是基于注解的容器配置?
答案:基于注解的容器配置是指使用Java注解(如@Component, @Autowired, @Configuration等)来定义bean和它们之间的依赖关系,而不是使用XML配置文件。
37. Spring 中如何开启注解装配?
答案:
- XML配置:context:annotation-config/或context:component-scan/
- Java配置:使用@Configuration和@ComponentScan
示例:
<!-- XML方式 -->
<context:annotation-config/>
<context:component-scan base-package="com.example"/><!-- Java方式 -->
@Configuration
@ComponentScan("com.example")
public class AppConfig {// ...
}
38. Spring 中如何更有效地使用 JDBC?
答案:
- 使用JdbcTemplate简化JDBC操作
- 使用NamedParameterJdbcTemplate支持命名参数
- 使用SimpleJdbcInsert简化插入操作
- 使用事务管理
- 使用异常转换器将SQLException转换为DataAccessException层次结构
示例:
@Repository
public class UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;public User findById(Long id) {return jdbcTemplate.queryForObject("SELECT * FROM users WHERE id = ?",new Object[]{id},(rs, rowNum) -> new User(rs.getLong("id"),rs.getString("name")));}
}
39. Spring 中支持那些 ORM?
答案:
- Hibernate
- JPA(Java Persistence API)
- JDO(Java Data Objects)
- MyBatis
- Apache OJB
- TopLink(已废弃)
40. 什么是 Spring AOP?
答案:Spring AOP(面向切面编程)是Spring框架的一个模块,提供声明式企业服务,特别是作为EJB声明式服务的替代品。它允许开发者通过定义横切关注点(如日志、事务、安全等)来模块化业务逻辑。
核心概念:
- 切面(Aspect):横切关注点的模块化
- 连接点(Join point):程序执行过程中的点
- 通知(Advice):在特定连接点执行的动作
- 切入点(Pointcut):匹配连接点的谓词
- 引入(Introduction):为类添加新方法或属性
- 目标对象(Target object):被一个或多个切面通知的对象
- AOP代理:由AOP框架创建的对象,用于实现切面契约
- 织入(Weaving):将切面与其他应用类型或对象连接起来的过程
Spring 面试题答案(续)
41. Spring AOP 中关注点和横切关注点有什么不同?
答案:
- 关注点(Concern):应用中一个模块的核心功能(如订单模块的业务逻辑)
- 横切关注点(Cross-cutting Concern):影响多个模块的功能(如日志、安全、事务等)
示例:
// 核心关注点
@Service
public class OrderService {public void createOrder(Order order) {// 业务逻辑}
}// 横切关注点
@Aspect
public class LoggingAspect {@Before("execution(* com.example.service.*.*(..))")public void logBefore(JoinPoint joinPoint) {// 日志逻辑}
}
42. Spring AOP 中切入点和连接点什么关系?
答案:
- 连接点(JoinPoint):程序执行过程中的特定点(如方法调用、异常抛出)
- 切入点(Pointcut):匹配连接点的表达式,决定哪些连接点会被通知
关系:切入点定义了一组连接点,通知将在这些连接点执行。
43. Spring AOP 代理是什么?
答案:Spring AOP代理是框架创建的用于实现AOP功能的对象。当目标对象被一个或多个切面通知时,Spring会创建一个代理对象来包装目标对象,在方法调用前后执行通知逻辑。
44. Java 中什么是 Aspect 切面?
答案:Aspect是模块化横切关注点的单元,包含:
- 切入点(定义何处)
- 通知(定义何时和做什么)
示例:
@Aspect
public class TransactionAspect {@Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}@Around("serviceMethods()")public Object manageTransaction(ProceedingJoinPoint pjp) throws Throwable {// 开启事务try {Object result = pjp.proceed();// 提交事务return result;} catch (Exception e) {// 回滚事务throw e;}}
}
45. BeanFactory 和 ApplicationContext 有什么区别?
答案:
特性 | BeanFactory | ApplicationContext |
---|---|---|
加载方式 | 延迟加载 | 启动时预加载单例bean |
功能 | 基本DI支持 | 扩展功能(AOP、事件发布等) |
国际化 | 不支持 | 支持 |
资源访问 | 有限 | 更丰富的资源访问方式 |
适用场景 | 资源受限环境 | 大多数应用 |
46. Spring 中有几种不同类型的自动代理?
答案:
- BeanNameAutoProxyCreator:基于bean名称自动创建代理
- DefaultAdvisorAutoProxyCreator:基于Advisor自动创建代理
- AnnotationAwareAspectJAutoProxyCreator:基于@Aspect注解自动创建代理
47. Spring 中什么是目标对象?
答案:目标对象是被一个或多个切面通知的对象,也称为被代理对象。代理对象会包装目标对象,在方法调用前后执行通知逻辑。
48. Spring 框架中事务管理有哪些优点?
答案:
- 一致的编程模型(不同事务API统一抽象)
- 声明式事务管理(非侵入式)
- 简化API(比JTA等更简单)
- 与Spring数据访问完美集成
- 支持多种事务传播行为
49. JDK 动态代理和 CGLIB 动态代理有什么区别?
答案:
特性 | JDK动态代理 | CGLIB代理 |
---|---|---|
基于 | 接口 | 类 |
性能 | 较慢 | 较快 |
限制 | 目标类需实现接口 | 无法代理final类/方法 |
创建方式 | Proxy.newProxyInstance() | Enhancer.create() |
50. Spring AOP 和 AspectJ AOP 有什么区别?
答案:
特性 | Spring AOP | AspectJ |
---|---|---|
实现 | 运行时代理 | 编译时/加载时织入 |
能力 | 仅方法级别 | 字段、构造器等 |
性能 | 较慢 | 更快 |
依赖 | 仅Spring | 需要AspectJ编译器 |
复杂度 | 简单 | 更复杂 |
51. Spring 中 ApplicationContext 通常的实现是什么?
答案:
- ClassPathXmlApplicationContext:从类路径加载XML配置
- FileSystemXmlApplicationContext:从文件系统加载XML配置
- AnnotationConfigApplicationContext:基于Java配置类
- WebApplicationContext:Web应用专用
示例:
// XML配置方式
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// 注解配置方式
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
52. Spring Native 框架是什么?
答案:Spring Native是Spring团队提供的将Spring应用编译为原生镜像(Native Image)的技术,使用GraalVM实现,可以显著减少启动时间和内存占用。
53. Spring Native 有什么优缺点?
答案:
优点:
- 极快的启动速度(毫秒级)
- 更低的内存占用
- 适合Serverless和容器环境
- 即时峰值性能
缺点:
- 构建时间较长
- 反射、动态代理等需要特殊配置
- 兼容性问题(不是所有库都支持)
- 调试更困难
54. Spring Native 和 JVM 有什么区别?
答案:
特性 | Spring Native | JVM |
---|---|---|
执行方式 | 原生可执行文件 | 字节码解释/JIT编译 |
启动速度 | 极快 | 较慢 |
内存占用 | 更低 | 较高 |
构建时间 | 长 | 短 |
动态特性支持 | 有限 | 完整 |
55. 什么是 Spring 配置文件?
答案:Spring配置文件是定义bean及其依赖关系的元数据文件,可以是:
- XML文件(传统方式)
- Java注解(现代方式)
- Java配置类(@Configuration)
- Groovy脚本
XML配置示例:
<beans><bean id="userService" class="com.example.UserService"><property name="userRepository" ref="userRepository"/></bean><bean id="userRepository" class="com.example.UserRepositoryImpl"/>
</beans>
56. Spring 中如何定义 Bean 的范围?
答案:使用@Scope注解或XML中的scope属性定义。
示例:
@Component
@Scope("prototype")
public class PrototypeBean {}// XML方式
<bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/>
57. Spring 框架中有哪些不同类型的事件?
答案:
- ContextRefreshedEvent:容器初始化或刷新时发布
- ContextStartedEvent:容器启动后发布
- ContextStoppedEvent:容器停止后发布
- ContextClosedEvent:容器关闭后发布
- RequestHandledEvent:Web请求处理后发布
- 自定义事件:扩展ApplicationEvent
示例:
// 发布事件
applicationContext.publishEvent(new MyCustomEvent(this, "Custom Message"));// 监听事件
@Component
public class MyEventListener implements ApplicationListener<MyCustomEvent> {@Overridepublic void onApplicationEvent(MyCustomEvent event) {// 处理事件}
}
58. Spring 应用程序有哪些不同组件?
答案:
- Bean:应用核心组件
- Configuration:配置元数据
- Aspect:横切关注点模块
- Controller(Web层)
- Service(业务逻辑层)
- Repository(数据访问层)
- Interceptor/Filter(Web请求处理)
59. Spring 如何设计容器的?BeanFactory 和 ApplicationContext 两者关系?
答案:
设计:
- 基于工厂模式(BeanFactory)
- 支持多种配置方式(XML、注解等)
- 分层设计(核心容器、AOP、数据访问等)
- 生命周期管理
关系:
- ApplicationContext是BeanFactory的子接口,提供了更多企业级功能
- BeanFactory是基础接口,提供基本DI支持
- 大多数应用使用ApplicationContext
60. Spring 如何处理线程并发问题?
答案:
- 无状态bean:默认线程安全
- 有状态bean:需要开发者处理(同步、ThreadLocal等)
- 并发工具:提供TaskExecutor抽象
- 事务管理:保证数据一致性
- 缓存注解:@Cacheable等
示例:
@Service
public class StatelessService { // 线程安全public String process(String input) {return input.toUpperCase();}
}@Service
@Scope("prototype") // 或使用ThreadLocal
public class StatefulService {private int counter;public synchronized void increment() {counter++;}
}
61. 解释 Spring 框架中 bean 的生命周期?
答案:
- 实例化
- 属性填充(依赖注入)
- BeanNameAware.setBeanName()
- BeanFactoryAware.setBeanFactory()
- ApplicationContextAware.setApplicationContext()
- 前置初始化(BeanPostProcessor.postProcessBeforeInitialization)
- InitializingBean.afterPropertiesSet()
- 自定义init方法
- 后置初始化(BeanPostProcessor.postProcessAfterInitialization)
- 使用中
- DisposableBean.destroy()
- 自定义destroy方法
62. 哪些是重要的 bean 生命周期方法?能否重载它们?
答案:
重要方法:
- afterPropertiesSet()(InitializingBean接口)
- destroy()(DisposableBean接口)
- 自定义init/destroy方法
重载方式:
- 实现接口
- XML配置:init-method/destroy-method属性
- 注解:@PostConstruct/@PreDestroy
示例:
public class MyBean implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() {// 初始化逻辑}@Overridepublic void destroy() {// 销毁逻辑}@PostConstructpublic void customInit() {// 另一种初始化方式}@PreDestroypublic void customDestroy() {// 另一种销毁方式}
}
63. 为什么 Spring 只支持方法级别的连接点?
答案:
- 简化设计:方法拦截已能满足大多数需求
- 性能考虑:字段/构造器拦截会增加复杂性
- 代理限制:JDK动态代理仅支持接口方法拦截
- 实用主义:80%的AOP需求可通过方法拦截实现
64. 解释一下 Spring AOP 中的几个名词?
答案:
- Aspect:横切关注点的模块化实现
- JoinPoint:程序执行过程中的点(如方法调用)
- Advice:在特定连接点执行的动作
- Pointcut:匹配连接点的谓词
- Target:被代理对象
- Proxy:生成的代理对象
- Weaving:将切面应用到目标对象的过程
65. 说一下 Spring 的事务隔离?
答案:
Spring支持标准的事务隔离级别:
- DEFAULT:使用数据库默认
- READ_UNCOMMITTED:可能读到未提交数据
- READ_COMMITTED:防止脏读
- REPEATABLE_READ:防止脏读和不可重复读
- SERIALIZABLE:最高隔离级别
示例:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateData() {// ...
}
66. Spring 中 @Autowire 和 @Resource 有什么区别?
答案:
特性 | @Autowired | @Resource |
---|---|---|
来源 | Spring | JSR-250 |
默认注入方式 | byType | byName |
必需性 | required=true | 默认必需 |
名称指定 | @Qualifier | name属性 |
适用场景 | Spring环境 | 通用JavaEE |
示例:
@Autowired
@Qualifier("mainService")
private MyService service;@Resource(name = "mainService")
private MyService service;
67. 将一个类声明为 Spring 的 bean 的注解有哪些?
答案:
- @Component:通用组件
- @Service:业务逻辑层
- @Repository:数据访问层
- @Controller:Web控制层
- @Configuration:配置类
- @Bean:方法级别声明
68. @Component、@Repository、@Service 三者有什么区别?
答案:
注解 | 用途 | 特殊处理 |
---|---|---|
@Component | 通用组件 | 无 |
@Repository | 数据访问 | 自动转换数据访问异常 |
@Service | 业务逻辑 | 无实际特殊处理,语义区分 |
本质:三者功能相同,区别在于语义和部分特殊处理。
69. Spring 中 restful 风格的几种注解区别与应用?
答案:
注解 | HTTP方法 | 示例 |
---|---|---|
@GetMapping | GET | 获取资源 |
@PostMapping | POST | 创建资源 |
@PutMapping | PUT | 更新资源 |
@DeleteMapping | DELETE | 删除资源 |
@PatchMapping | PATCH | 部分更新 |
示例:
@RestController
@RequestMapping("/users")
public class UserController {@GetMapping("/{id}")public User getUser(@PathVariable Long id) {// ...}@PostMappingpublic User createUser(@RequestBody User user) {// ...}
}
70. Spring 中允许注入一个null 或一个空字符串吗?
答案:
- null:默认不允许,需明确指定(@Nullable或required=false)
- 空字符串:允许,可通过@Value注入
示例:
@Autowired(required = false)
private OptionalService optionalService;@Value("${some.property:}")
private String emptyString;@Autowired
public void setNullableService(@Nullable NullableService service) {// ...
}
71. 构造器依赖注入和 Setter方法注入有什么区别?
答案:
特性 | 构造器注入 | Setter注入 |
---|---|---|
时机 | 对象创建时 | 对象创建后 |
不变性 | 可创建不可变对象 | 对象可变 |
循环依赖 | 不支持 | 支持 |
可选依赖 | 不适合 | 适合 |
推荐度 | 更高(Spring推荐) | 较低 |
示例:
// 构造器注入
@Service
public class ConstructorInjection {private final Dependency dependency;public ConstructorInjection(Dependency dependency) {this.dependency = dependency;}
}// Setter注入
@Service
public class SetterInjection {private Dependency dependency;@Autowiredpublic void setDependency(Dependency dependency) {this.dependency = dependency;}
}
72. Spring 中如何解决 @Cacheable 注解不生效?
解决方案:
- 确保启用缓存:@EnableCaching
- 检查方法是否为public
- 确保自调用问题(同类方法调用不经过代理)
- 检查缓存名称配置
- 确认key生成策略
- 检查缓存管理器配置
示例:
@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("books");}
}@Service
public class BookService {@Cacheable("books")public Book findBook(String isbn) {// ...}
}
73. Spring事务同一个类方法A和B,异常时方法A调用B是否回滚?
答案:
- 默认情况:不会回滚,因为自调用不经过代理
- 解决方案:
- 将方法B移到另一个类
- 通过AopContext获取当前代理
- 使用编程式事务
示例:
@Service
public class MyService {@Transactionalpublic void methodA() {try {((MyService) AopContext.currentProxy()).methodB();} catch (Exception e) {// 处理异常}}@Transactional(propagation = Propagation.REQUIRES_NEW)public void methodB() {// ...}
}
74. Spring 和 Spring Boot 有什么区别?
答案:
特性 | Spring | Spring Boot |
---|---|---|
配置 | 显式配置 | 自动配置 |
依赖管理 | 手动 | starter POMs |
部署 | 需要外部容器 | 内置容器 |
监控 | 有限 | Actuator |
入门难度 | 较高 | 较低 |
75. Spring 框架中七大核心模块分别是什么?
答案:
- Spring Core:IoC容器
- Spring AOP:面向切面编程
- Spring DAO:数据访问抽象
- Spring ORM:对象关系映射
- Spring Web:Web基础
- Spring Context:应用上下文
- Spring Web MVC:MVC框架
76. 简述一下 Spring 配置文件中元素的常用属性?
答案:
常用属性:
- id/name:bean标识符
- class:实现类
- scope:作用域
- init-method/destroy-method:生命周期方法
- autowire:自动装配模式
- lazy-init:延迟初始化
示例:
<bean id="userService" class="com.example.UserService"scope="singleton" init-method="init" destroy-method="cleanup"autowire="byType" lazy-init="true"><property name="userRepository" ref="userRepository"/>
</bean>