当前位置: 首页 > news >正文

Spring面试题及详细答案 125道(16-25) -- 核心概念与基础2

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。

前后端面试题-专栏总目录

在这里插入图片描述

文章目录

  • 一、本文面试题目录
      • 16. 什么是Spring的自动装配?有哪些自动装配模式?
      • 17. 如何禁用Spring的自动装配?
      • 18. Spring中的@Qualifier注解的作用是什么?
      • 19. 什么是Spring的事件机制?请举例说明。
      • 20. Spring中的BeanPostProcessor有什么作用?如何使用?
      • 21. Spring中的FactoryBean和BeanFactory有什么区别?请举例说明FactoryBean的应用场景。
      • 22. 什么是Spring的占位符配置(如${})?如何解析?
      • 23. Spring中如何处理循环依赖?三级缓存的作用是什么?
      • 24. @Value注解的作用是什么?如何使用它注入配置文件中的值?
      • 25. Spring中的@Profile注解有什么作用?如何通过它实现环境隔离?
  • 二、125道Spring面试题目录列表

一、本文面试题目录

16. 什么是Spring的自动装配?有哪些自动装配模式?

  • 定义:Spring的自动装配是指容器在创建Bean时,根据特定规则自动识别并注入该Bean所依赖的其他Bean,无需开发者在配置中显式声明依赖关系,从而减少配置工作量。
  • 自动装配模式
    • no(默认):不启用自动装配,需手动通过<property>@Autowired等方式配置依赖。
    • byName:根据属性名自动匹配容器中同名的Bean(如属性名为userDao,则匹配id="userDao"的Bean)。
      <bean id="userService" class="com.example.UserService" autowire="byName"/>
      <bean id="userDao" class="com.example.UserDao"/> <!-- 与属性名匹配 -->
      
    • byType:根据属性类型自动匹配容器中同类型的Bean,若存在多个同类型Bean会抛出异常。
      <bean id="userService" class="com.example.UserService" autowire="byType"/>
      <bean class="com.example.UserDao"/> <!-- 与属性类型匹配 -->
      
    • constructor:类似byType,但用于构造器参数,根据参数类型匹配依赖的Bean。
    • autodetect(已过时):优先尝试constructor,失败则使用byType

17. 如何禁用Spring的自动装配?

  • XML配置:在<bean>标签中显式设置autowire="no"(默认值),或全局禁用自动装配:
    <!-- 单个Bean禁用 -->
    <bean id="userService" class="com.example.UserService" autowire="no"/><!-- 全局禁用(仅适用于Spring旧版本) -->
    <beans default-autowire="no">...</beans>
    
  • 注解配置
    • 不使用@Autowired@Resource等自动装配注解,手动通过@Bean方法参数注入依赖。
    • 对类添加@Autowired(required = false)并结合@Qualifier强制指定依赖(本质是控制装配而非禁用)。
  • Java配置类:通过@Bean方法显式声明依赖,不依赖容器自动注入:
    @Configuration
    public class AppConfig {@Beanpublic UserService userService() {UserService service = new UserService();service.setUserDao(userDao()); // 手动注入return service;}@Beanpublic UserDao userDao() {return new UserDao();}
    }
    

18. Spring中的@Qualifier注解的作用是什么?

  • 作用:当容器中存在多个同类型的Bean时,@Qualifier用于指定具体要注入的Bean名称,解决@Autowired按类型自动装配的歧义问题。
  • 使用场景:配合@Autowired使用,明确依赖的Bean标识。
    @Service
    public class UserService {// 容器中存在多个UserDao类型的Bean(如userDaoImpl1、userDaoImpl2)@Autowired@Qualifier("userDaoImpl1") // 指定注入id为userDaoImpl1的Beanprivate UserDao userDao;
    }
    
  • XML配置对应方式:通过<qualifier>标签指定:
    <bean id="userService" class="com.example.UserService"><property name="userDao"><qualifier value="userDaoImpl1"/></property>
    </bean>
    

19. 什么是Spring的事件机制?请举例说明。

  • 定义:Spring的事件机制基于观察者模式,允许Bean通过发布事件(Event)和监听事件(Listener)实现松耦合通信。核心组件包括:
    • ApplicationEvent:事件基类,自定义事件需继承此类。
    • ApplicationListener:事件监听器接口,或使用@EventListener注解。
    • ApplicationEventPublisher:事件发布器,由容器自动注入。
  • 示例
    1. 定义自定义事件
      public class OrderCreatedEvent extends ApplicationEvent {private String orderId;public OrderCreatedEvent(Object source, String orderId) {super(source);this.orderId = orderId;}public String getOrderId() {return orderId;}
      }
      
    2. 创建事件监听器
      @Component
      public class OrderListener {// 方式1:实现ApplicationListener接口@Componentpublic static class OrderCreatedListener implements ApplicationListener<OrderCreatedEvent> {@Overridepublic void onApplicationEvent(OrderCreatedEvent event) {System.out.println("监听订单创建:" + event.getOrderId());}}// 方式2:使用@EventListener注解(推荐)@EventListenerpublic void handleOrderEvent(OrderCreatedEvent event) {System.out.println("处理订单:" + event.getOrderId());}
      }
      
    3. 发布事件
      @Service
      public class OrderService {@Autowiredprivate ApplicationEventPublisher publisher;public void createOrder(String orderId) {// 业务逻辑...publisher.publishEvent(new OrderCreatedEvent(this, orderId));}
      }
      

20. Spring中的BeanPostProcessor有什么作用?如何使用?

  • 作用BeanPostProcessor是Spring的后置处理器接口,用于在Bean初始化前后对其进行增强或修改,是AOP实现的基础机制之一。
  • 核心方法
    • postProcessBeforeInitialization:在Bean初始化方法(如@PostConstructafterPropertiesSet)执行前调用。
    • postProcessAfterInitialization:在Bean初始化方法执行后调用。
  • 使用示例:对Bean进行属性加密处理
    @Component
    public class EncryptBeanPostProcessor implements BeanPostProcessor {// 初始化前处理@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof User) {User user = (User) bean;user.setPassword(encrypt(user.getPassword())); // 加密密码}return bean;}// 初始化后处理(可返回代理对象实现AOP)@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}private String encrypt(String password) {// 加密逻辑...return password + "_encrypted";}
    }
    
  • 注意BeanPostProcessor会作用于容器中所有Bean,可通过beanName或类型判断进行针对性处理。

21. Spring中的FactoryBean和BeanFactory有什么区别?请举例说明FactoryBean的应用场景。

  • 区别

    特性FactoryBeanBeanFactory
    本质是一个Bean,用于创建复杂对象是IoC容器接口,管理所有Bean
    作用自定义Bean的创建逻辑负责Bean的注册、实例化、依赖注入
    接口方法getObject()返回实际对象getBean()获取容器中的Bean
  • FactoryBean示例:创建数据库连接池(复杂对象)

    public class DataSourceFactoryBean implements FactoryBean<DataSource> {private String url;private String username;private String password;// 设置配置参数public void setUrl(String url) { this.url = url; }public void setUsername(String username) { this.username = username; }public void setPassword(String password) { this.password = password; }// 自定义对象创建逻辑@Overridepublic DataSource getObject() throws Exception {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}@Overridepublic Class<?> getObjectType() {return DataSource.class;}
    }
    
  • 配置与使用

    <bean id="dataSource" class="com.example.DataSourceFactoryBean"><property name="url" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="123456"/>
    </bean>
    
    // 获取的是FactoryBean创建的DataSource对象,而非FactoryBean本身
    DataSource dataSource = context.getBean("dataSource", DataSource.class);
    
  • 应用场景

    • 创建复杂对象(如连接池、线程池、MyBatis的SqlSessionFactory)。
    • 隐藏对象创建细节,简化配置。
    • 动态生成代理对象(如AOP代理)。

22. 什么是Spring的占位符配置(如${})?如何解析?

  • 定义:占位符配置(${key})允许在Spring配置中使用外部化参数(如配置文件、环境变量),实现配置与代码分离,便于多环境部署。
  • 解析方式
    1. 基于XML配置:通过PropertyPlaceholderConfigurercontext:property-placeholder标签:
      <!-- 引入配置文件 -->
      <context:property-placeholder location="classpath:db.properties"/><!-- 使用占位符 -->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${db.url}"/><property name="username" value="${db.username}"/>
      </bean>
      
    2. 基于注解配置:结合@PropertySource@Value
      @Configuration
      @PropertySource("classpath:db.properties") // 加载配置文件
      public class DataSourceConfig {@Value("${db.url}")private String url;@Value("${db.username}")private String username;@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(url);dataSource.setUsername(username);return dataSource;}
      }
      
    3. Spring Boot自动解析:默认加载application.propertiesapplication.yml,直接使用@Value("${key}")注入。
  • 注意:若占位符未找到对应值,可通过default-value设置默认值:${db.url:jdbc:mysql://localhost:3306/test}

23. Spring中如何处理循环依赖?三级缓存的作用是什么?

  • 循环依赖:指两个或多个Bean相互依赖(如A依赖B,B依赖A)。Spring通过三级缓存解决单例Bean的循环依赖,原型Bean无法解决(会抛出异常)。
  • 三级缓存
    1. 一级缓存(singletonObjects):存储完全初始化完成的单例Bean。
    2. 二级缓存(earlySingletonObjects):存储提前暴露的未完全初始化的Bean实例(原始对象或代理对象)。
    3. 三级缓存(singletonFactories):存储Bean的工厂对象(ObjectFactory),用于延迟创建代理对象。
  • 处理流程
    1. 创建A时,先将A的工厂对象放入三级缓存,再注入依赖B。
    2. 创建B时,注入依赖A,此时从三级缓存获取A的工厂,生成A的早期实例(放入二级缓存),并注入B。
    3. B初始化完成后,注入A,A继续完成初始化,最终放入一级缓存。
  • 代码验证
    @Service
    public class A {@Autowiredprivate B b; // A依赖B
    }@Service
    public class B {@Autowiredprivate A a; // B依赖A
    }
    
    上述代码可正常运行,Spring通过三级缓存解决了循环依赖。
  • 注意:构造器注入的循环依赖无法解决(因构造器执行前无法暴露实例),需改为setter注入。

24. @Value注解的作用是什么?如何使用它注入配置文件中的值?

  • 作用@Value注解用于将外部值(配置文件、系统变量、SpEL表达式等)注入到Bean的字段或方法参数中。
  • 使用方式
    1. 注入配置文件值
      # application.properties
      app.name=MyApp
      app.version=1.0.0
      
      @Component
      public class AppConfig {@Value("${app.name}")private String appName;@Value("${app.version:2.0.0}") // 设默认值private String appVersion;
      }
      
    2. 注入系统变量或环境变量
      @Value("${user.home}") // 系统变量
      private String userHome;@Value("${JAVA_HOME}") // 环境变量
      private String javaHome;
      
    3. 注入SpEL表达式结果
      @Value("#{T(java.lang.Math).random() * 100}") // 随机数
      private double randomValue;@Value("#{systemProperties['os.name']}") // 系统属性
      private String osName;
      
    4. 注入Bean的属性
      @Component
      public class User {private String username = "admin";// getter
      }@Component
      public class UserService {@Value("#{user.username}") // 注入其他Bean的属性private String username;
      }
      

25. Spring中的@Profile注解有什么作用?如何通过它实现环境隔离?

  • 作用@Profile注解用于标识Bean在特定环境(如开发、测试、生产)下才会被注册到容器中,实现不同环境的配置隔离。
  • 使用方式
    1. 标记Bean或配置类
      // 开发环境的数据源
      @Configuration
      @Profile("dev")
      public class DevDataSourceConfig {@Beanpublic DataSource dataSource() {return new HikariDataSource(...); // 开发环境配置}
      }// 生产环境的数据源
      @Configuration
      @Profile("prod")
      public class ProdDataSourceConfig {@Beanpublic DataSource dataSource() {return new HikariDataSource(...); // 生产环境配置}
      }
      
    2. 激活环境
      • XML配置<context:property-placeholder profile="dev"/>
      • Java启动参数-Dspring.profiles.active=dev
      • 代码激活
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.getEnvironment().setActiveProfiles("dev"); // 激活dev环境
        context.register(AppConfig.class);
        context.refresh();
        
    3. 默认环境:使用@Profile("default")标识默认激活的Bean,当未指定环境时生效。
  • 优势:避免在不同环境切换时修改配置文件,通过激活不同Profile即可加载对应环境的Bean。

二、125道Spring面试题目录列表

文章序号Spring面试题125道
1Spring面试题及详细答案125道(01-15)
2Spring面试题及详细答案125道(16-25)
3Spring面试题及详细答案125道(26-45)
4Spring面试题及详细答案125道(46-65)
5Spring面试题及详细答案125道(66-75)
6Spring面试题及详细答案125道(76-90)
7Spring面试题及详细答案125道(91-110)
8Spring面试题及详细答案125道(111-125)
http://www.dtcms.com/a/349264.html

相关文章:

  • 工程师的自我修养
  • Linux --网络基础概念
  • 08-系统能力调用与权限管理
  • Python爬虫-解决在抓包的过程中,找不到接口地址的问题
  • ViLU: Learning Vision-Language Uncertainties for Failure Prediction
  • C++ 容器——vector
  • PyTorch入门实战:MNIST数据集加载与可视化详解
  • 一、基因组选择(GS)与基因组预测(GP)
  • 【K8s】整体认识K8s之namespace
  • OpenIM应用机器人自动应答
  • 基于陌讯视觉算法的扶梯大件行李识别技术实战:误检率↓79%的工业级解决方案
  • 大模型中的意图识别
  • DMA-API(alloc和free)调用流程分析(十)
  • 胸部X光片数据集:健康及肺炎2类,14k+图像
  • 【网络运维】Shell脚本编程:函数
  • 大件垃圾识别精准度↑90%!陌讯多尺度融合模型在智慧环卫的落地实践
  • 鸿蒙ArkTS 基础篇-03-对象
  • 【黑色星期五输出当年有几个】2022-10-23
  • 单词搜索+回溯法
  • Windows客户端部署和管理
  • Week 13: 深度学习补遗:RNN的训练
  • 青少年软件编程(python五级)等级考试试卷-客观题(2023年12月)
  • 2024年09月 Python(一级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • 使用 LangGraph + Zep 打造一款有记忆的心理健康关怀机器人
  • 【LLIE专题】一种用于低光图像增强的空间自适应光照引导 Transformer(SAIGFormer)框架
  • 超级助理:百度智能云发布的AI助理应用
  • JUC之并发容器
  • 2025最新酷狗kgm格式转mp3,kgma格式转mp3,kgg格式转mp3
  • 《程序员修炼之道》第五六章读书笔记
  • 【云馨AI-大模型】AI热潮持续升温:2025年8月第三周全球动态