2025年Spring框架(不包含Spring Cloud + Spring Boot)面试题大全(精选120题)

1. 解释Spring框架的核心设计理念(IoC/DI)及其优势?

答案
Spring的核心设计理念是控制反转(IoC)依赖注入(DI)

  • IoC:将对象的创建和管理权从代码中转移到容器,降低组件间的耦合度。
  • DI:通过容器自动将依赖注入到对象中,支持构造器注入、Setter注入和字段注入。
    优势:解耦组件、提高可测试性、支持AOP、统一资源管理。

2. Spring Bean的作用域有哪些?默认作用域是什么?

答案

  • singleton:全局单例(默认)。
  • prototype:每次请求创建新实例。
  • request:HTTP请求生命周期内有效。
  • session:HTTP会话生命周期内有效。
  • application:ServletContext生命周期内有效。

3. @Autowired@Resource的区别是什么?

答案

  • @Autowired:按类型匹配Bean,支持required=false允许注入为null
  • @Resource:默认按名称匹配,可配置按类型(需指定type属性)。
  • @Autowired是Spring特有,@Resource是JSR-250标准。

4. 如何配置Spring Bean的初始化与销毁回调?

答案

  • 注解方式
    @PostConstruct
    public void init() { ... }
    
    @PreDestroy
    public void destroy() { ... }
    
  • XML方式
    <bean init-method="init" destroy-method="destroy" />
    

5. Spring中ApplicationContextBeanFactory的区别?

答案

  • BeanFactory:基础接口,延迟加载Bean。
  • ApplicationContext:扩展接口,支持国际化、事件发布、AOP等高级功能,启动时预加载Bean。

6. Spring AOP的核心术语有哪些?

答案

  • 切面(Aspect):横切关注点的模块化(如日志、事务)。
  • 连接点(JoinPoint):程序执行点(如方法调用)。
  • 通知(Advice):切面在连接点的具体行为(如@Before@After)。
  • 切入点(Pointcut):定义通知应用的连接点。
  • 织入(Weaving):将切面与目标对象结合的过程。

7. 基于XML和注解的AOP配置方式有何不同?

答案

  • XML配置
    <aop:config>
      <aop:aspect ref="loggingAspect">
        <aop:before method="logBefore" pointcut="execution(* com.example.service.*.*(..))"/>
      </aop:aspect>
    </aop:config>
    
  • 注解配置
    @Aspect
    @Component
    public class LoggingAspect {
      @Before("execution(* com.example.service.*.*(..))")
      public void logBefore() { ... }
    }
    

8. Spring如何管理数据库事务?

答案

  • 使用@Transactional注解声明事务边界。
  • 配置PlatformTransactionManager(如DataSourceTransactionManager)。
  • 支持传播行为(如REQUIREDREQUIRES_NEW)和隔离级别。

9. JdbcTemplate的作用是什么?相比原生JDBC有何优势?

答案

  • 作用:简化JDBC操作,封装资源管理和异常转换。
  • 优势
    • 自动管理ConnectionStatementResultSet
    • SQLException转换为Spring的DataAccessException
    • 支持模板方法模式(如queryForObjectupdate)。

10. Spring MVC的请求处理流程是怎样的?

答案

  1. DispatcherServlet接收请求。
  2. 查找匹配的HandlerMapping(如@RequestMapping)。
  3. 调用HandlerAdapter执行控制器方法。
  4. 返回ModelAndView
  5. ViewResolver解析视图名称。
  6. 渲染视图并返回响应。

11. Spring中Bean的生命周期包括哪些阶段?

答案

  1. 实例化(Instantiation)。
  2. 属性注入(Populate Properties)。
  3. 初始化(Initialization):调用@PostConstructinit-method
  4. 使用(In Use)。
  5. 销毁(Destruction):调用@PreDestroydestroy-method

12. 如何解决Bean的循环依赖问题?

答案

  • Spring通过三级缓存解决:
    1. 提前暴露半成品Bean(一级缓存)。
    2. 完成依赖注入后存入二级缓存。
    3. 初始化完成后存入三级缓存。
  • 使用@Lazy延迟加载或重构代码消除循环。

13. Spring的ApplicationContext初始化流程?

答案

  1. 加载Bean定义(XML、注解)。
  2. 解析Bean定义(作用域、依赖关系)。
  3. 实例化Bean(按需创建单例Bean)。
  4. 注入依赖。
  5. 调用初始化方法。
  6. 发布ContextRefreshedEvent事件。

14. Spring事件机制的实现原理?

答案

  • 发布者通过ApplicationEventPublisher发布事件。
  • 监听器实现ApplicationListener接口。
  • 容器通过ApplicationEventMulticaster异步或同步分发事件。
  • 示例:
    // 发布事件
    applicationContext.publishEvent(new CustomEvent(this, "Data"));
    
    // 监听事件
    @Component
    public class CustomListener implements ApplicationListener<CustomEvent> {
      @Override
      public void onApplicationEvent(CustomEvent event) { ... }
    }
    

15. Spring如何集成第三方框架(如MyBatis)?

答案

  1. 配置SqlSessionFactoryBean
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource"/>
    </bean>
    
  2. 使用@MapperScan扫描Mapper接口:
    @Configuration
    @MapperScan("com.example.mapper")
    public class MyBatisConfig { ... }
    

16. @Configuration@Component注解的区别?

答案

  • @Configuration:标记类为配置类,Spring会通过CGLIB代理确保Bean的单例性。
  • @Component:通用注解,标记类为Spring组件,不保证单例性(需配合@Scope)。

17. Spring中@Import注解的三种使用场景?

答案

  1. 导入配置类:@Import(DatabaseConfig.class)
  2. 动态导入Bean:通过ImportSelector接口。
  3. 注册Bean定义:通过ImportBeanDefinitionRegistrar接口。

18. 如何动态注册Bean?

答案
实现BeanDefinitionRegistryPostProcessor接口:

public class CustomBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    GenericBeanDefinition definition = new GenericBeanDefinition();
    definition.setBeanClass(MyBean.class);
    registry.registerBeanDefinition("myBean", definition);
  }
}

19. Spring的国际化(i18n)支持如何实现?

答案

  1. 配置MessageSource
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
      <property name="basename" value="messages"/>
    </bean>
    
  2. 使用LocaleResolver解析请求语言。
  3. 通过#{messageSource.getMessage('key', null, locale)}获取消息。

20. Spring如何处理文件上传?

答案

  1. 配置MultipartResolver
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
    
  2. 控制器方法接收MultipartFile参数:
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) { ... }
    

21. Spring的@Conditional注解家族有哪些典型应用场景?

答案
@Conditional根据条件决定是否注册Bean,典型场景包括:

  • 按操作系统类型
    @Conditional(WindowsCondition.class)
    @Bean
    public String windowsService() { return "Windows"; }
    
  • 按配置文件存在性
    @ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
    
  • 按类路径是否存在
    @ConditionalOnClass(DataSource.class)
    

22. Spring的FactoryBean和普通Bean的区别?

答案

  • FactoryBean用于创建复杂对象(如代理、连接池)。
  • 示例:
    public class CarFactoryBean implements FactoryBean<Car> {
      @Override
      public Car getObject() { return new Car(); }
      @Override
      public Class<?> getObjectType() { return Car.class; }
    }
    
  • 普通Bean直接通过构造函数或工厂方法实例化。

23. 如何自定义Spring的Scope?

答案

  1. 实现Scope接口:
    public class ThreadLocalScope implements Scope {
      private final ThreadLocal<Map<String, Object>> threadScope = new ThreadLocal<>();
      // 实现get、remove、registerDestructionCallback等方法
    }
    
  2. 注册到容器:
    @Configuration
    public class AppConfig {
      @Bean
      public static CustomScopeConfigurer scopeConfigurer() {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        configurer.addScope("thread", new ThreadLocalScope());
        return configurer;
      }
    }
    

24. Spring的@Profile注解如何实现环境隔离?

答案

  • 通过@Profile("dev")标记Bean仅在开发环境激活。
  • 激活方式:
    # application.properties
    spring.profiles.active=dev
    
    或启动时指定:
    SpringApplication.run(App.class, "--spring.profiles.active=prod");
    

25. Spring的缓存抽象(Cache Abstraction)如何工作?

答案

  1. 启用缓存:@EnableCaching
  2. 使用@Cacheable缓存结果:
    @Cacheable("users")
    public User getUser(String id) { ... }
    
  3. 配置缓存管理器(如Redis):
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
      return RedisCacheManager.builder(factory).build();
    }
    

26. Spring的@Scheduled注解如何实现定时任务?

答案

  1. 启用调度:@EnableScheduling
  2. 配置任务:
    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() { ... }
    
  3. 线程池配置:
    @Bean
    public TaskScheduler taskScheduler() {
      ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
      scheduler.setPoolSize(10);
      return scheduler;
    }
    

27. Spring的TaskExecutor接口有哪些实现类?

答案

  • SimpleAsyncTaskExecutor:简单异步执行。
  • SyncTaskExecutor:同步执行(默认)。
  • ThreadPoolTaskExecutor:线程池实现(推荐):
    @Bean
    public TaskExecutor taskExecutor() {
      ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      executor.setCorePoolSize(5);
      executor.setMaxPoolSize(10);
      return executor;
    }
    

28. Spring如何集成JUnit 5进行单元测试?

答案

  1. 使用@ExtendWith(SpringExtension.class)
  2. 配置测试上下文:
    @SpringBootTest
    @ContextConfiguration(classes = TestConfig.class)
    public class UserServiceTest {
      @Autowired
      private UserService userService;
    }
    

29. Spring的@Value注解如何注入配置值?

答案

  1. 注入属性文件值:
    @Value("${app.name}")
    private String appName;
    
  2. 注入SpEL表达式:
    @Value("#{systemProperties['user.home']}")
    private String userHome;
    

30. Spring框架在JDK 8+中的新特性适配?

答案

  • Lambda表达式:简化监听器注册(如@EventListener)。
  • 重复注解:@Repeatable支持多个@Scheduled任务。
  • 接口默认方法:增强ApplicationContext的扩展性。

31. Spring中Bean的初始化方法有哪些配置方式?

答案

  • @PostConstruct注解。
  • InitializingBean接口:
    public class MyBean implements InitializingBean {
      @Override
      public void afterPropertiesSet() { ... }
    }
    
  • XML配置init-method属性。

32. @Autowired(required=false)的作用是什么?

答案

  • 允许依赖为null,避免因Bean不存在导致启动失败。
  • 示例:
    @Autowired(required = false)
    private Optional<DataSource> dataSource;
    

33. 如何在Spring中配置多个数据源?

答案

  1. 使用@Primary标记主数据源:
    @Bean
    @Primary
    public DataSource primaryDataSource() { ... }
    
  2. 动态路由数据源:
    @Bean
    public DataSource dataSource() {
      AbstractRoutingDataSource router = new AbstractRoutingDataSource();
      router.setDefaultTargetDataSource(primaryDataSource());
      return router;
    }
    

34. Spring MVC的@Controller@RestController有何区别?

答案

  • @RestController = @Controller + @ResponseBody
  • 示例:
    @RestController
    public class UserController {
      @GetMapping("/user")
      public User getUser() { return new User(); } // 直接返回JSON
    }
    

35. @Transactional注解在什么情况下会失效?

答案

  • 异常被捕获未抛出。
  • 非public方法。
  • 自调用(同一类内方法调用)。
  • 错误的事务传播行为配置。

36. 如何自定义Spring的BeanFactoryPostProcessor

答案

  1. 实现接口:
    public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
      @Override
      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 修改Bean定义属性
      }
    }
    
  2. 注册为Bean:
    @Bean
    public static BeanFactoryPostProcessor customBeanFactoryPostProcessor() {
      return new CustomBeanFactoryPostProcessor();
    }
    

37. Spring事件机制中,如何实现异步事件监听?

答案

  1. 配置事件多播器:
    @Bean
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
      SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
      multicaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
      return multicaster;
    }
    
  2. 发布异步事件:
    applicationEventPublisher.publishEvent(new CustomEvent(this, "Data"));
    

38. @ImportResource注解的作用及典型场景?

答案

  • 作用:导入XML配置文件到注解驱动的上下文。
  • 场景:混合使用XML和注解配置(如遗留系统迁移)。
  • 示例:
    @Configuration
    @ImportResource("classpath:legacy-context.xml")
    public class AppConfig { ... }
    

39. Spring如何集成JUnit 5进行模块化测试?

答案

  1. 使用@ContextConfiguration指定配置类:
    @SpringJUnitConfig(TestConfig.class)
    public class ModuleTest { ... }
    
  2. 结合@MockBean隔离依赖:
    @MockBean
    private RemoteService remoteService;
    

40. @Cacheable注解支持哪些条件表达式?举例说明。

答案

  • unless:否定条件(不缓存结果):
    @Cacheable(value = "users", unless = "#result.size() < 1")
    
  • condition:肯定条件(仅当满足时缓存):
    @Cacheable(value = "users", condition = "#name.length() > 3")
    
  • SpEL表达式:#root.method.name#p0(方法参数)。

41. Spring如何处理BeanCreationException?常见原因有哪些?

答案

  • 异常链分析:检查根因(如循环依赖、Bean配置错误)。
  • 常见原因:
    • 循环依赖未解决。
    • Bean定义错误(如缺少构造函数参数)。
    • 资源加载失败(如文件路径错误)。
    • 事务管理器配置错误。

42. @Lazy注解在单例Bean中的作用是什么?

答案

  • 延迟初始化Bean,减少启动时间。
  • 示例:
    @Bean
    @Lazy
    public HeavyBean heavyBean() { return new HeavyBean(); }
    
  • 结合@DependsOn解决初始化顺序问题。

43. 如何在Spring中注册自定义属性编辑器(PropertyEditor)?

答案

  1. 实现PropertyEditor接口:
    public class CustomDateEditor extends PropertyEditorSupport {
      @Override
      public void setAsText(String text) {
        setValue(LocalDate.parse(text));
      }
    }
    
  2. 注册到CustomEditorConfigurer
    @Bean
    public CustomEditorConfigurer customEditorConfigurer() {
      CustomEditorConfigurer configurer = new CustomEditorConfigurer();
      configurer.setCustomEditors(Collections.singletonMap(LocalDate.class, new CustomDateEditor()));
      return configurer;
    }
    

44. Spring的MessageSource如何实现国际化?

答案

  1. 配置资源文件:
    # messages.properties
    greeting=Hello
    # messages_zh_CN.properties
    greeting=你好
    
  2. 使用MessageSource
    @Autowired
    private MessageSource messageSource;
    public String getGreeting(Locale locale) {
      return messageSource.getMessage("greeting", null, locale);
    }
    

45. @Autowired@Inject注解的异同?

答案

  • 相同点:均支持依赖注入。
  • 不同点:
    • @Inject是JSR-330标准,无required属性。
    • @Autowired是Spring特有,支持required=false

46. 如何实现方法级别的切面(Method-level Aspect)?

答案

  1. 定义切面:
    @Aspect
    @Component
    public class LoggingAspect {
      @Around("execution(* com.example.service.*.*(..))")
      public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Before method: " + joinPoint.getSignature());
        Object result = joinPoint.proceed();
        System.out.println("After method: " + joinPoint.getSignature());
        return result;
      }
    }
    
  2. 启用AOP:@EnableAspectJAutoProxy

47. @Profile@Conditional如何协同工作?

答案

  • @Profile激活Bean,@Conditional细化条件。
  • 示例:
    @Profile("dev")
    @ConditionalOnProperty(name = "debug.enabled", havingValue = "true")
    @Bean
    public DebugLogger debugLogger() { ... }
    

48. 如何在Spring中定义自定义XML标签(如<mytag:config>)?

答案

  1. 实现NamespaceHandler
    public class MyNamespaceHandler extends NamespaceHandlerSupport {
      @Override
      public void init() {
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      }
    }
    
  2. 实现BeanDefinitionParser
    public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
      @Override
      public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 解析XML元素并创建Bean定义
      }
    }
    
  3. 注册到META-INF/spring.handlers
    http\://example.com/schema/mytag=com.example.MyNamespaceHandler
    

49. TaskExecutor接口有哪些实现类?如何配置异步任务?

答案

  • 实现类:SimpleAsyncTaskExecutorSyncTaskExecutorThreadPoolTaskExecutor
  • 配置异步任务:
    @Bean
    public TaskExecutor taskExecutor() {
      ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      executor.setCorePoolSize(5);
      executor.setMaxPoolSize(10);
      executor.setQueueCapacity(25);
      return executor;
    }
    

50. @PostConstructInitializingBean的使用场景对比?

答案

  • @PostConstruct:注解方式更简洁,推荐用于新代码。
  • InitializingBean:接口方式适用于类无法修改的场景(如第三方库)。
  • 示例:
    // 注解方式
    @PostConstruct
    public void init() { ... }
    
    // 接口方式
    public class LegacyService implements InitializingBean {
      @Override
      public void afterPropertiesSet() { ... }
    }
    

51. Spring如何解决循环依赖中的代理对象问题?

答案
Spring通过三级缓存机制解决循环依赖中的代理问题:

  1. 一级缓存(singletonObjects):存储完全初始化的Bean。
  2. 二级缓存(earlySingletonObjects):存储已实例化但未注入依赖的半成品Bean。
  3. 三级缓存(singletonFactories):存储Bean工厂对象,用于生成代理(如AOP增强)。

流程

  • BeanA实例化后暴露工厂到三级缓存。
  • BeanB注入BeanA时,从三级缓存获取工厂并提前生成代理对象。
  • BeanA完成初始化后存入一级缓存,BeanB使用代理对象完成注入。

52. 如何在Spring中集成Hibernate作为ORM框架?

答案

  1. 添加依赖:
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
    </dependency>
    
  2. 配置LocalSessionFactoryBean
    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
      LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
      sessionFactory.setDataSource(dataSource);
      sessionFactory.setPackagesToScan("com.example.entity");
      Properties hibernateProps = new Properties();
      hibernateProps.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
      sessionFactory.setHibernateProperties(hibernateProps);
      return sessionFactory;
    }
    
  3. 启用事务管理:
    @Bean
    public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) {
      return new HibernateTransactionManager(sessionFactory);
    }
    

53. @EventListener如何与事务阶段绑定?

答案
使用@TransactionalEventListenerphase属性:

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleEvent(CustomEvent event) {
  // 事务提交后执行
}

阶段选项

  • BEFORE_COMMIT:事务提交前。
  • AFTER_COMMIT:事务提交后(默认)。
  • AFTER_ROLLBACK:事务回滚后。
  • AFTER_COMPLETION:事务完成(提交或回滚)后。

54. @Order注解在多个切面中的优先级如何控制?

答案

  • 值越小优先级越高。
  • 示例:
    @Aspect
    @Order(1) // 高优先级
    public class LoggingAspect { ... }
    
    @Aspect
    @Order(2) // 低优先级
    public class AuditAspect { ... }
    
  • 或通过实现Ordered接口:
    public class CustomAspect implements Ordered {
      @Override
      public int getOrder() { return 1; }
    }
    

55. 如何自定义BeanPostProcessor实现Bean的动态增强?

答案

  1. 实现接口:
    public class CustomBeanPostProcessor implements BeanPostProcessor {
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 初始化前处理
        return bean;
      }
      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 初始化后处理(如动态代理)
        if (bean instanceof TargetInterface) {
          return Proxy.newProxyInstance(...);
        }
        return bean;
      }
    }
    
  2. 注册为Bean:
    @Bean
    public static BeanPostProcessor customBeanPostProcessor() {
      return new CustomBeanPostProcessor();
    }
    

56. @Scheduled注解支持哪些触发器配置?

答案

  • fixedRate:固定速率(毫秒)。
  • fixedDelay:固定延迟(毫秒)。
  • cron:Cron表达式。
  • zone:时区配置。

示例

@Scheduled(cron = "0 0 8 * * ?", zone = "Asia/Shanghai")
public void dailyTask() { ... }

57. @Qualifier注解在自动装配中的底层逻辑?

答案

  • 根据Bean名称或限定符名称匹配候选Bean。
  • 示例:
    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource dataSource;
    
  • 底层通过QualifierAnnotationAutowireCandidateResolver解析注解。

58. 如何实现AOP的环绕通知(Around Advice)?

答案

  1. 定义切面:
    @Aspect
    @Component
    public class LoggingAspect {
      @Around("execution(* com.example.service.*.*(..))")
      public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Before method: " + joinPoint.getSignature());
        Object result = joinPoint.proceed(); // 执行目标方法
        System.out.println("After method: " + joinPoint.getSignature());
        return result;
      }
    }
    
  2. 启用AOP:@EnableAspectJAutoProxy

59. ApplicationContextAware接口如何获取应用上下文?

答案

  1. 实现接口:
    @Component
    public class ContextHolder implements ApplicationContextAware {
      private static ApplicationContext context;
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) {
        context = applicationContext;
      }
      public static <T> T getBean(Class<T> type) {
        return context.getBean(type);
      }
    }
    
  2. 通过静态方法获取Bean:
    UserService userService = ContextHolder.getBean(UserService.class);
    

60. @Import@ComponentScan的扫描机制有何不同?

答案

  • @Import:显式导入配置类或Bean定义。
  • @ComponentScan:按包路径扫描组件(如@Service@Repository)。
  • 示例:
    @Configuration
    @Import(DatabaseConfig.class) // 导入配置类
    @ComponentScan("com.example.service") // 扫描服务层组件
    public class AppConfig { ... }
    

61. Spring中Bean的初始化方法有哪些配置方式?

答案

  • @PostConstruct注解。
  • InitializingBean接口。
  • XML配置init-method属性。
  • 优先级@PostConstruct > InitializingBean.afterPropertiesSet() > init-method

62. @Autowired(required=false)的作用是什么?

答案

  • 允许依赖为null,避免因Bean不存在导致启动失败。
  • 示例:
    @Autowired(required = false)
    private Optional<DataSource> dataSource;
    

63. Spring MVC的DispatcherServlet如何处理请求映射?

答案

  1. 查找匹配的HandlerMapping(如@RequestMapping)。
  2. 调用HandlerAdapter执行控制器方法。
  3. 返回ModelAndView
  4. 通过ViewResolver解析视图名称。
  5. 渲染视图并返回响应。

64. 事务的Propagation.REQUIRES_NEW行为具体表现?

答案

  • 无论外层事务是否存在,始终开启新事务。
  • 外层事务回滚不影响内层事务。
  • 示例:
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerTransactionalMethod() { ... }
    

65. 如何配置Spring管理多个数据源?

答案

  1. 使用@Primary标记主数据源:
    @Bean
    @Primary
    public DataSource primaryDataSource() { ... }
    
  2. 动态路由数据源:
    @Bean
    public DataSource dataSource() {
      AbstractRoutingDataSource router = new AbstractRoutingDataSource();
      router.setDefaultTargetDataSource(primaryDataSource());
      return router;
    }
    

66. @PreDestroy注解在Bean销毁时的触发条件?

答案

  • Bean从容器移除前调用(如ConfigurableApplicationContext.close())。
  • 示例:
    @PreDestroy
    public void cleanup() { ... }
    

67. Spring的依赖注入方式有哪些?

答案

  • 构造器注入:推荐方式,支持不可变对象。
  • Setter注入:适用于可选依赖。
  • 字段注入:简洁但不利于单元测试(不推荐)。

示例

@Service
public class UserService {
  private final UserRepository userRepository;

  @Autowired // 构造器注入
  public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
  }
}

68. prototype作用域的Bean在依赖注入时的行为特点?

答案

  • 每次注入时创建新实例。
  • 需结合@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)解决代理问题:
    @Bean
    @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public PrototypeBean prototypeBean() { ... }
    

69. Spring如何解决三级缓存中的循环依赖?

答案

  • 通过早期暴露对象引用(半成品Bean)的机制。
  • 流程:
    1. BeanA实例化后存入三级缓存。
    2. BeanB注入BeanA时,从三级缓存获取工厂并生成代理。
    3. BeanA完成初始化后存入一级缓存,BeanB使用代理对象。

70. JdbcTemplate相比原生JDBC的优势?

答案

  • 自动管理ConnectionStatementResultSet
  • 异常转换(SQLExceptionDataAccessException)。
  • 支持模板方法模式(如queryForObjectupdate)。
  • 集成事务管理。

71. 如何自定义Spring事件监听器并实现异步处理?

答案

  1. 定义事件:
    public class CustomEvent extends ApplicationEvent { ... }
    
  2. 实现监听器:
    @Component
    public class CustomListener {
      @Async
      @EventListener
      public void handleEvent(CustomEvent event) { ... }
    }
    
  3. 配置异步支持:
    @EnableAsync
    @Configuration
    public class AsyncConfig implements AsyncConfigurer {
      @Override
      public Executor getAsyncExecutor() {
        return Executors.newFixedThreadPool(10);
      }
    }
    

72. Spring国际化(i18n)的完整配置流程?

答案

  1. 配置资源文件:
    # messages.properties
    greeting=Hello
    # messages_zh_CN.properties
    greeting=你好
    
  2. 定义MessageSource
    @Bean
    public MessageSource messageSource() {
      ResourceBundleMessageSource source = new ResourceBundleMessageSource();
      source.setBasename("messages");
      return source;
    }
    
  3. 使用LocaleResolver解析语言:
    @Bean
    public LocaleResolver localeResolver() {
      SessionLocaleResolver resolver = new SessionLocaleResolver();
      resolver.setDefaultLocale(Locale.ENGLISH);
      return resolver;
    }
    

73. @Cacheablekey生成策略有哪些?

答案

  • 默认使用方法参数。
  • SpEL自定义表达式:
    @Cacheable(value = "users", key = "#userId")
    public User getUser(String userId) { ... }
    
  • 复合键:
    @Cacheable(value = "orders", key = "#userId + '-' + #orderId")
    

74. @Scheduled如何配置固定延迟任务?

答案

  • 使用fixedDelay属性:
    @Scheduled(fixedDelay = 5000)
    public void processTask() { ... }
    
  • 线程池隔离:
    @Bean
    public TaskScheduler taskScheduler() {
      ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
      scheduler.setPoolSize(5);
      return scheduler;
    }
    

75. 如何自定义属性编辑器(PropertyEditor)?

答案

  1. 实现接口:
    public class CustomDateEditor extends PropertyEditorSupport {
      @Override
      public void setAsText(String text) {
        setValue(LocalDate.parse(text));
      }
    }
    
  2. 注册到CustomEditorConfigurer
    @Bean
    public CustomEditorConfigurer customEditorConfigurer() {
      CustomEditorConfigurer configurer = new CustomEditorConfigurer();
      configurer.setCustomEditors(Collections.singletonMap(LocalDate.class, new CustomDateEditor()));
      return configurer;
    }
    

76. 注解驱动的AOP配置与XML方式的区别?

答案

  • 注解驱动
    @EnableAspectJAutoProxy
    @Configuration
    public class AppConfig { ... }
    
  • XML方式
    <aop:aspectj-autoproxy/>
    
  • 区别:注解方式更简洁,XML方式适合遗留系统或复杂切面配置。

77. Spring测试如何加载部分配置类?

答案

  • 使用@ContextConfiguration指定配置类:
    @SpringJUnitConfig(classes = {TestConfig.class, DatabaseConfig.class})
    public class UserServiceTest { ... }
    

78. @Conditional注解如何实现条件化Bean注册?

答案

  • 通过Condition接口判断条件:
    public class WindowsCondition implements Condition {
      @Override
      public boolean matches(ConditionContext ctx, AnnotatedTypeMetadata metadata) {
        return ctx.getEnvironment().getProperty("os.name").contains("Windows");
      }
    }
    
  • 使用注解:
    @Bean
    @Conditional(WindowsCondition.class)
    public String windowsService() { ... }
    

79. 如何自定义Spring的Scope?

答案

  1. 实现Scope接口:
    public class ThreadLocalScope implements Scope {
      private final ThreadLocal<Map<String, Object>> threadScope = new ThreadLocal<>();
      // 实现get、remove、registerDestructionCallback等方法
    }
    
  2. 注册到容器:
    @Bean
    public static CustomScopeConfigurer scopeConfigurer() {
      CustomScopeConfigurer configurer = new CustomScopeConfigurer();
      configurer.addScope("thread", new ThreadLocalScope());
      return configurer;
    }
    

80. 动态注册Bean的两种方式?

答案

  1. BeanDefinitionRegistryPostProcessor
    public class CustomRegistrar implements BeanDefinitionRegistryPostProcessor {
      @Override
      public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        GenericBeanDefinition definition = new GenericBeanDefinition();
        definition.setBeanClass(MyBean.class);
        registry.registerBeanDefinition("myBean", definition);
      }
    }
    
  2. DefaultListableBeanFactory.registerBeanDefinition
    DefaultListableBeanFactory factory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
    factory.registerBeanDefinition("dynamicBean", new RootBeanDefinition(DynamicBean.class));
    

81. 自定义BeanFactoryPostProcessor的典型场景?

答案

  • 修改Bean定义属性(如替换占位符)。
  • 动态注入属性:
    public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
      @Override
      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        BeanDefinition bd = beanFactory.getBeanDefinition("dataSource");
        bd.getPropertyValues().add("url", "jdbc:mysql://new-host:3306/db");
      }
    }
    

82. Spring性能优化的关键策略?

答案

  • 延迟加载:使用@Lazy减少启动时间。
  • 缓存配置:启用@Cacheable减少重复计算。
  • 减少Bean作用域:避免prototype作用域。
  • 异步事件处理:使用@Async解耦耗时操作。
  • 避免自调用事务:确保@Transactional生效。

83. Spring集成JUnit 5的扩展点?

答案

  • @ExtendWith(SpringExtension.class):启用Spring测试上下文。
  • @TestConfiguration:定义测试专用配置:
    @TestConfiguration
    public class TestConfig {
      @Bean
      public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().build();
      }
    }
    

84. 如何定义自定义XML命名空间?

答案

  1. 实现NamespaceHandler
    public class MyNamespaceHandler extends NamespaceHandlerSupport {
      @Override
      public void init() {
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      }
    }
    
  2. 实现BeanDefinitionParser
    public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
      @Override
      public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 解析XML元素并创建Bean定义
      }
    }
    
  3. 注册到META-INF/spring.handlers
    http\://example.com/schema/mytag=com.example.MyNamespaceHandler
    

85. Spring事务管理器的选择依据?

答案

  • DataSourceTransactionManager:单机数据库事务(JDBC、MyBatis)。
  • JtaTransactionManager:分布式事务(需JTA实现,如Atomikos)。
  • HibernateTransactionManager:Hibernate专属事务管理。

86. 自定义BeanPostProcessor实现AOP的原理?

答案

  • 通过postProcessAfterInitialization方法包装Bean为代理对象:
    public Object postProcessAfterInitialization(Object bean, String beanName) {
      if (bean instanceof TargetInterface) {
        return Proxy.newProxyInstance(getClass().getClassLoader(),
          new Class<?>[] { TargetInterface.class },
          new InvocationHandler() { ... });
      }
      return bean;
    }
    

87. Spring事件发布机制的底层实现?

答案

  • 基于观察者模式,通过ApplicationEventMulticaster分发事件。
  • 流程:
    1. 发布者调用ApplicationEventPublisher.publishEvent()
    2. 多播器查找匹配的监听器。
    3. 异步或同步调用监听器方法。

88. Spring缓存抽象(Cache Abstraction)的扩展点?

答案

  • 实现CacheManager(如Redis):
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
      return RedisCacheManager.builder(factory).build();
    }
    
  • 实现Cache接口自定义缓存行为。

89. Spring AOP默认使用哪种动态代理?

答案

  • JDK动态代理:基于接口实现(默认)。
  • CGLIB代理:基于类代理(需proxyTargetClass=true):
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    

90. 如何配置Spring测试的分层上下文?

答案

  • 使用@ActiveProfiles隔离环境配置:
    @ActiveProfiles("test")
    @SpringBootTest
    public class TestClass { ... }
    
  • 使用@TestPropertySource覆盖属性:
    @TestPropertySource(properties = "app.name=test-app")
    

91. Spring中Bean的默认作用域是什么?如何修改?

答案

  • 默认作用域:singleton(全局单例)。
  • 修改方式:
    • @Scope注解:
      @Bean
      @Scope("prototype")
      public PrototypeBean prototypeBean() { ... }
      
    • XML配置:
      <bean id="bean" class="com.example.Bean" scope="prototype"/>
      

92. @Autowired@Resource的注入顺序优先级如何?

答案

  • @Autowired:按类型匹配,若存在多个候选Bean,结合@Qualifier按名称匹配。
  • @Resource:默认按名称匹配,若未找到,按类型匹配。
  • 优先级:@Resource的名称匹配优先级高于@Autowired的类型匹配。

93. Spring MVC的DispatcherServlet如何处理静态资源?

答案

  1. 配置静态资源映射:
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
      @Override
      public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
      }
    }
    
  2. 或XML配置:
    <mvc:resources mapping="/static/**" location="/static/"/>
    

94. 事务的Propagation.NESTED行为与REQUIRES_NEW有何不同?

答案

  • NESTED:在嵌套事务内提交/回滚,外层事务回滚可能导致内层回滚(取决于数据库支持)。
  • REQUIRES_NEW:始终独立事务,外层事务回滚不影响内层。
  • 示例:
    @Transactional(propagation = Propagation.NESTED)
    public void nestedTransactionalMethod() { ... }
    

95. JdbcTemplatequeryForObject方法在查询空结果时的行为?

答案

  • 抛出EmptyResultDataAccessException异常。
  • 处理方式:
    try {
      User user = jdbcTemplate.queryForObject("SELECT * FROM users WHERE id = ?", new Object[]{id}, userRowMapper);
    } catch (EmptyResultDataAccessException e) {
      // 处理空结果
    }
    

96. 如何配置Spring的国际化消息源?

答案

  1. 定义资源文件:
    # messages.properties
    greeting=Hello
    # messages_zh_CN.properties
    greeting=你好
    
  2. 配置MessageSource
    @Bean
    public MessageSource messageSource() {
      ResourceBundleMessageSource source = new ResourceBundleMessageSource();
      source.setBasename("messages");
      return source;
    }
    

97. @PostConstruct@PreDestroy注解的生命周期阶段?

答案

  • @PostConstruct:Bean初始化后执行(属性注入完成后)。
  • @PreDestroy:Bean销毁前执行(容器关闭时)。
  • 对应Bean生命周期阶段:
    实例化 → 属性注入 → @PostConstruct → 使用 → @PreDestroy → 销毁
    

98. Spring如何解决单例Bean的循环依赖?

答案

  • 通过三级缓存提前暴露对象引用(半成品Bean)。
  • 流程:
    1. BeanA实例化后存入三级缓存。
    2. BeanB注入BeanA时,从三级缓存获取工厂并生成代理。
    3. BeanA完成初始化后存入一级缓存,BeanB使用代理对象完成注入。

99. 注解驱动配置与XML配置的混合使用场景?

答案

  • 使用@ImportResource导入XML配置:
    @Configuration
    @ImportResource("classpath:legacy-context.xml")
    public class AppConfig { ... }
    
  • 或通过@ComponentScan扫描注解类:
    @Configuration
    @ComponentScan("com.example")
    public class AppConfig { ... }
    

100. @Cacheablesync属性作用是什么?

答案

  • 启用同步缓存,避免缓存击穿(需Spring 4.3+)。
  • 示例:
    @Cacheable(value = "users", sync = true)
    public User getUser(String id) { ... }
    

101. 如何自定义Spring的Bean作用域?

答案

  1. 实现Scope接口:
    public class ThreadLocalScope implements Scope {
      private final ThreadLocal<Map<String, Object>> threadScope = new ThreadLocal<>();
      // 实现get、remove、registerDestructionCallback等方法
    }
    
  2. 注册到容器:
    @Bean
    public static CustomScopeConfigurer scopeConfigurer() {
      CustomScopeConfigurer configurer = new CustomScopeConfigurer();
      configurer.addScope("thread", new ThreadLocalScope());
      return configurer;
    }
    

102. Spring事件驱动架构的典型应用场景?

答案

  • 解耦业务逻辑(如订单创建后发送通知)。
  • 示例:
    // 发布事件
    applicationEventPublisher.publishEvent(new OrderCreatedEvent(order));
    
    // 监听事件
    @Component
    public class OrderNotifier {
      @EventListener
      public void handleOrderCreated(OrderCreatedEvent event) {
        sendNotification(event.getOrder());
      }
    }
    

103. AOP中@Around通知如何控制目标方法执行?

答案

  • 通过ProceedingJoinPoint.proceed()决定是否执行目标方法:
    @Around("execution(* com.example.service.*.*(..))")
    public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
      System.out.println("Before method: " + joinPoint.getSignature());
      Object result = joinPoint.proceed(); // 执行目标方法
      System.out.println("After method: " + joinPoint.getSignature());
      return result;
    }
    

104. 动态注册Bean的两种方式及适用场景?

答案

  1. BeanDefinitionRegistryPostProcessor
    • 适用场景:启动时动态注册Bean。
    • 示例:
      public class CustomRegistrar implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
          GenericBeanDefinition definition = new GenericBeanDefinition();
          definition.setBeanClass(MyBean.class);
          registry.registerBeanDefinition("myBean", definition);
        }
      }
      
  2. DefaultListableBeanFactory.registerBeanDefinition
    • 适用场景:运行时动态注册Bean。
    • 示例:
      DefaultListableBeanFactory factory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
      factory.registerBeanDefinition("dynamicBean", new RootBeanDefinition(DynamicBean.class));
      

105. Spring测试中@DirtiesContext的作用?

答案

  • 标记测试方法会修改应用上下文,强制重新加载Bean。
  • 示例:
    @DirtiesContext
    @Test
    public void testModifyContext() { ... }
    

106. 如何集成Hibernate作为Spring的ORM框架?

答案

  1. 添加依赖:
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
    </dependency>
    
  2. 配置LocalSessionFactoryBean
    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
      LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
      sessionFactory.setDataSource(dataSource);
      sessionFactory.setPackagesToScan("com.example.entity");
      Properties hibernateProps = new Properties();
      hibernateProps.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
      sessionFactory.setHibernateProperties(hibernateProps);
      return sessionFactory;
    }
    
  3. 启用事务管理:
    @Bean
    public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) {
      return new HibernateTransactionManager(sessionFactory);
    }
    

107. 选择DataSourceTransactionManager还是JtaTransactionManager的依据?

答案

  • DataSourceTransactionManager:单机数据库事务(JDBC、MyBatis)。
  • JtaTransactionManager:分布式事务(需JTA实现,如Atomikos)。
  • 示例:
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
      return new DataSourceTransactionManager(dataSource);
    }
    

108. 自定义属性编辑器(PropertyEditor)的步骤?

答案

  1. 实现接口:
    public class CustomDateEditor extends PropertyEditorSupport {
      @Override
      public void setAsText(String text) {
        setValue(LocalDate.parse(text));
      }
    }
    
  2. 注册到CustomEditorConfigurer
    @Bean
    public CustomEditorConfigurer customEditorConfigurer() {
      CustomEditorConfigurer configurer = new CustomEditorConfigurer();
      configurer.setCustomEditors(Collections.singletonMap(LocalDate.class, new CustomDateEditor()));
      return configurer;
    }
    

109. @Scheduled如何配置固定速率任务?

答案

  • 使用fixedRate属性:
    @Scheduled(fixedRate = 5000)
    public void processTask() { ... }
    
  • 线程池隔离:
    @Bean
    public TaskScheduler taskScheduler() {
      ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
      scheduler.setPoolSize(5);
      return scheduler;
    }
    

110. 多数据源路由的两种实现方式?

答案

  1. AbstractRoutingDataSource
    • 抽象类,通过determineCurrentLookupKey()动态路由。
    • 示例:
      public class DynamicDataSource extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() {
          return DataSourceContextHolder.getDataSourceKey();
        }
      }
      
  2. @Primary注解
    • 标记主数据源,其他数据源通过@Qualifier指定:
      @Bean
      @Primary
      public DataSource primaryDataSource() { ... }
      
      @Bean
      public DataSource secondaryDataSource() { ... }
      

111. Spring IoC容器初始化的底层流程?

答案

  1. 资源加载:解析配置文件(XML、注解)。
  2. Bean定义解析:创建BeanDefinition对象。
  3. 依赖注入:实例化Bean并注入属性。
  4. 初始化回调:调用@PostConstructinit-method
  5. 事件发布:触发ContextRefreshedEvent事件。

112. Spring性能优化的关键策略?

答案

  • 延迟加载:使用@Lazy减少启动时间。
  • 缓存配置:启用@Cacheable减少重复计算。
  • 减少Bean作用域:避免prototype作用域。
  • 异步事件处理:使用@Async解耦耗时操作。
  • 避免自调用事务:确保@Transactional生效。

113. 集成测试与单元测试在Spring中的区别?

答案

  • 集成测试:加载完整应用上下文,验证组件间协作。
    • 示例:
      @SpringBootTest
      public class IntegrationTest { ... }
      
  • 单元测试:使用Mock对象(如@MockBean)隔离依赖。
    • 示例:
      @ExtendWith(MockitoExtension.class)
      public class UnitTest {
        @Mock
        private RemoteService remoteService;
      }
      

114. 如何定义自定义XML命名空间?

答案

  1. 实现NamespaceHandler
    public class MyNamespaceHandler extends NamespaceHandlerSupport {
      @Override
      public void init() {
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      }
    }
    
  2. 实现BeanDefinitionParser
    public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
      @Override
      public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 解析XML元素并创建Bean定义
      }
    }
    
  3. 注册到META-INF/spring.handlers
    http\://example.com/schema/mytag=com.example.MyNamespaceHandler
    

115. Spring缓存抽象的扩展点有哪些?

答案

  • 实现CacheManager(如Redis):
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
      return RedisCacheManager.builder(factory).build();
    }
    
  • 实现Cache接口自定义缓存行为。

116. JDK动态代理与CGLIB代理的选择策略?

答案

  • JDK动态代理:基于接口实现(默认)。
  • CGLIB代理:基于类代理(需proxyTargetClass=true):
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    

117. 如何实现事件监听器的异步处理?

答案

  1. 配置异步支持:
    @EnableAsync
    @Configuration
    public class AsyncConfig implements AsyncConfigurer {
      @Override
      public Executor getAsyncExecutor() {
        return Executors.newFixedThreadPool(10);
      }
    }
    
  2. 发布异步事件:
    applicationEventPublisher.publishEvent(new CustomEvent(this, "Data"));
    

118. 自定义Scope需实现哪些关键方法?

答案

  • get(String name, ObjectFactory<?> objectFactory):获取Bean实例。
  • remove(String name):移除Bean。
  • registerDestructionCallback(String name, Runnable callback):注册销毁回调。
  • resolveContextualObject(String key):解析上下文对象。

119. 测试上下文的分层配置策略?

答案

  • 使用@ActiveProfiles隔离环境配置:
    @ActiveProfiles("test")
    @SpringBootTest
    public class TestClass { ... }
    
  • 使用@TestPropertySource覆盖属性:
    @TestPropertySource(properties = "app.name=test-app")
    

120. Spring 5+对响应式编程的支持?

答案

  • WebFlux模块:基于Reactor的响应式Web框架。
  • ReactiveAdapterRegistry:支持响应式类型转换。
  • 示例:
    @Bean
    public RouterFunction<ServerResponse> route(UserHandler userHandler) {
      return RouterFunctions.route(GET("/users"), userHandler::getAllUsers);
    }
    

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值