全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📝 1 篇文章 48 道配套习题

高阶扩展与自定义注解专题

专题说明

本专题深入讲解SpringBoot高阶扩展技术,从自定义注解开发到注解与AOP结合,再到Actuator端点扩展和BeanPostProcessor扩展,全面掌握SpringBoot高级定制与扩展能力。

学习目标

  1. 掌握自定义注解开发规范
  2. 理解注解与AOP切面结合实现
  3. 学会自定义Actuator端点扩展
  4. 掌握BeanPostProcessor扩展机制
  5. 理解条件注解原理与自定义
  6. 掌握自定义Starter开发流程

学习内容

  • 自定义注解开发(元注解、属性定义)
  • 注解与AOP结合(切入点表达式、切面实现)
  • 自定义健康指示器(HealthIndicator)
  • Actuator端点扩展(@Endpoint、WebEndpointResponse)
  • BeanPostProcessor扩展
  • 条件注解原理(@Conditional系列)

学习建议

建议先掌握自定义注解的元注解使用和属性定义,再学习注解与AOP切面的结合实现,然后深入Actuator端点扩展和BeanPostProcessor机制。注意理解args表达式绑定参数的方式,以及WebEndpointResponse返回状态码的正确用法。

📝 发现内容有误?点击此处直接编辑

📝 配套习题(48 题)

1
单选题

在Spring Boot Actuator中,自定义健康检查指示器需要实现哪个接口?该接口的核心方法是什么?

A

实现HealthCheck接口,提供check()方法

B

实现HealthIndicator接口,提供health()方法返回Health对象

C

实现StatusIndicator接口,提供getStatus()方法

D

继承AbstractHealthIndicator类,重写doHealthCheck()方法

2
单选题

在Spring Boot应用中配置了多个自定义健康指示器,当访问/actuator/health端点时,系统如何聚合各个健康指示器的状态?哪种状态会作为最终的整体健康状态?

A

所有指示器状态都为UP时才返回UP,否则返回DOWN

B

使用最严重状态作为最终状态:DOWN > OUT_OF_SERVICE > UP

C

只考虑第一个注册的健康指示器状态

D

根据配置的健康指示器顺序依次检查,第一个DOWN就返回

3
单选题

自定义健康指示器在执行健康检查时可能涉及外部服务调用,如果检查逻辑耗时较长会影响/actuator/health端点响应时间。以下哪种方案可以有效解决这个问题?

A

使用@Async注解让健康检查异步执行,不影响主线程

B

使用ReactiveHealthIndicator返回Mono实现异步健康检查

C

在健康检查方法中设置超时,超时后返回DOWN状态

D

配置management.endpoint.health.cache.time-to-live缓存健康结果

4
多选题

在Spring Boot应用中,以下哪些是自定义健康指示器的典型应用场景?

A

检查外部API服务是否可达,如支付接口、短信服务

B

检查Redis、MongoDB等中间件的连接状态

C

检查应用内部业务状态,如订单队列积压情况

D

检查服务器磁盘空间是否充足

E

检查关键配置是否正确加载,如加密密钥是否配置

F

检查数据库连接池状态,如连接数是否接近上限

5
多选题

在Spring Boot Actuator中,可以通过配置管理健康检查的行为。以下哪些配置是正确的?

A

management.endpoint.health.show-details=always 配置显示所有健康检查详情

B

management.endpoint.health.group.readiness.include=db,redis 创建readiness健康组

C

management.health.defaults.enabled=false 禁用所有默认健康检查

D

management.health.custom.enabled=true 启用自定义健康指示器(custom为指示器名称)

E

management.endpoint.health.status.order=DOWN,OUT_OF_SERVICE,UP,UNKNOWN 配置状态排序

F

management.endpoint.health.probes.enabled=true 启用Kubernetes存活和就绪探针

6
判断题

自定义健康指示器的Bean名称会影响其在/actuator/health响应中的显示名称。如果自定义指示器类名为MyServiceHealthIndicator,则其显示名称默认为myService(去掉HealthIndicator后缀并首字母小写)。

A

B

7
判断题

可以通过配置management.health.{indicator-name}.enabled=false来禁用特定的健康指示器,其中indicator-name是健康指示器在响应中显示的名称(如db、redis、diskSpace)。

A

B

8
单选题

Spring的@Import注解有三种使用方式来注册组件,以下哪个选项正确描述了这三种方式?

A

直接导入类、导入ImportSelector实现类、导入ImportBeanDefinitionRegistrar实现类

B

直接导入@Configuration类、导入@Component类、导入@Bean方法

C

导入普通类、导入配置类、导入工厂类

D

导入Bean、导入Configuration、导入ComponentScan

9
单选题

Spring Boot中的@Enable*注解(如@EnableCaching、@EnableScheduling)是如何实现的?以下哪种描述是正确的?

A

@Enable*注解直接通过@ComponentScan扫描相关组件

B

@Enable*注解内部使用@Import导入相关配置类或ImportSelector

C

@Enable*注解内部使用@Bean方法注册相关组件

D

@Enable*注解是Spring Boot特有的,Spring框架不支持

10
单选题

ImportSelector接口可以根据注解元数据动态选择要导入的类。以下代码片段展示了如何根据@EnableMyFeature注解的属性值决定导入哪些配置类:

Java
public class MyFeatureSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        // 如何获取@EnableMyFeature注解的属性?
    }
}
A

使用metadata.getAnnotationAttributes("EnableMyFeature")获取注解属性Map

B

使用metadata.getAllAnnotationAttributes()获取所有注解属性

C

使用AnnotationConfigApplicationContext获取注解信息

D

ImportSelector无法获取注解属性,只能硬编码导入类名

11
多选题

ImportBeanDefinitionRegistrar相比ImportSelector提供了更强大的Bean注册能力。以下哪些是ImportBeanDefinitionRegistrar可以实现的功能?

A

自定义Bean的名称,而不是使用默认的类名首字母小写

B

为注册的Bean设置属性值,如scope、lazy-init等

C

根据注解元数据动态决定是否注册某些Bean

D

注册FactoryBean而不是普通Bean

E

为Bean设置primary属性,影响自动装配优先级

F

执行其他BeanDefinitionRegistry操作,如删除已注册的Bean

12
多选题

Spring提供了DeferredImportSelector接口,它是ImportSelector的子接口。以下关于DeferredImportSelector的描述哪些是正确的?

A

DeferredImportSelector的selectImports方法会在所有@Configuration类处理完成后才执行

B

DeferredImportSelector可以保证导入的配置类在所有用户配置之后加载

C

EnableAutoConfiguration使用DeferredImportSelector实现自动配置在用户配置之后加载

D

DeferredImportSelector必须实现selectImports方法,否则会抛异常

E

DeferredImportSelector执行时会传入ImportSelector.Group的Group.Entry信息

F

使用DeferredImportSelector可以避免自动配置覆盖用户自定义配置

13
多选题

在Spring中,@Import导入的配置类与当前配置类的加载顺序会影响Bean的依赖关系。以下哪些关于@Import加载顺序的描述是正确的?

A

通过@Import直接导入的类会在当前配置类处理之前先被处理

B

通过ImportSelector导入的类会在当前配置类处理时立即处理

C

ImportBeanDefinitionRegistrar注册的BeanDefinition会在当前配置类的Bean注册之前处理

D

多个@Import导入的类按照声明顺序依次处理

E

@Import导入的@Configuration类中的@Bean方法按正常规则处理

F

如果导入的配置类存在循环依赖,Spring会抛异常

14
填空题

Spring的@Import注解支持三种导入方式:

  1. 直接导入类:如@Import(MyService.class),效果等同于将_________注册为Bean
  2. 导入ImportSelector:实现______________接口的selectImports方法返回要导入的类名数组
  3. 导入ImportBeanDefinitionRegistrar:实现________________________接口,手动注册BeanDefinition获得完全控制
15
单选题

在Spring中创建自定义注解并通过AOP实现其功能时,以下哪个步骤是必须的?

A

自定义注解必须使用@Target(ElementType.METHOD)指定作用于方法

B

自定义注解必须继承Spring的注解接口

C

切面类必须使用@Around注解才能处理自定义注解

D

自定义注解必须配置@Retention(RetentionPolicy.RUNTIME)才能被AOP识别

16
单选题

在Spring AOP中,以下哪种切入点表达式可以正确匹配标注了@MyLog注解的方法?

A

@Pointcut("execution(* @MyLog .(..))")

B

@Pointcut("@annotation(com.example.MyLog)")

C

@Pointcut("annotation(com.example.MyLog)")

D

@Pointcut("@target(com.example.MyLog)")

17
单选题

假设需要创建一个@RateLimit注解实现接口限流功能,以下哪种实现方案最合适?

A

继承TransactionProxyFactoryBean并重写invoke方法

B

使用Spring AOP的@Around注解结合RateLimiter实现限流逻辑

C

实现BeanPostProcessor在Bean初始化时动态生成代理

D

使用Java动态Proxy.newProxyInstance创建代理

18
多选题

在Spring AOP切面中,可以通过哪些方式获取被拦截方法的参数信息?

A

通过ProceedingJoinPoint.getArgs()获取方法参数数组

B

通过MethodSignature.getMethod()获取Method对象后使用getParameterTypes()

C

在切入点表达式中使用args(..)绑定参数

D

通过JoinPoint.getTarget()获取目标对象后反射调用

E

使用@annotation注解属性注入的方式传递参数值

F

通过ProceedingJoinPoint.proceed(args)修改方法参数后继续执行

19
多选题

自定义注解可以与Spring现有注解组合使用以增强功能。以下哪些组合使用方式是有效的?

A

自定义@MyTransactional注解,内部使用@Transactional,实现自定义事务语义

B

自定义@MyCacheable注解,在切面中先处理自定义逻辑再调用CacheManager

C

自定义@MyLog注解与@Transactional组合使用,切面记录事务方法执行日志

D

自定义@MyAsync注解替代@EnableAsync,实现自定义异步执行逻辑

E

使用@AliasFor将自定义注解属性与Spring注解属性建立映射关系

F

自定义注解继承@Transactional注解,自动获得事务功能

20
多选题

在Spring AOP中处理自定义注解时,以下哪些关于注解继承和传递的描述是正确的?

A

如果方法上的注解需要从父类继承,自定义注解应配置@Inherited

B

@annotation切入点表达式无法匹配父类方法上的注解

C

@within切入点表达式可以匹配类上的注解,包括从父类继承的类注解

D

使用@target切入点表达式可以匹配目标对象类上的注解

E

在接口方法上标注自定义注解,实现类方法上的切面无法捕获该注解

F

Spring 4.0+支持@annotation匹配接口继承的方法注解

21
填空题

创建一个可被Spring AOP识别的自定义注解,必须配置以下两个元注解:

  1. ________________________ - 表示注解在运行时保留,AOP可通过反射获取
  2. _______ - 指定注解可以作用的程序元素类型,如ElementType.METHOD表示作用于方法
22
单选题

BeanPostProcessor接口有两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。它们的执行时机在Bean生命周期中的位置是什么?

A

在Bean实例化之后、属性注入之前执行

B

在Bean属性注入之后、初始化方法(@PostConstruct、InitializingBean)之前和之后执行

C

在Bean初始化方法执行之后、Bean销毁之前执行

D

在BeanFactory创建之后、Bean实例化之前执行

23
单选题

Spring提供了BeanFactoryPostProcessor和BeanPostProcessor两个扩展接口。以下关于它们区别的描述哪个是正确的?

A

BeanFactoryPostProcessor处理BeanFactory,BeanPostProcessor处理Bean实例

B

BeanFactoryPostProcessor在Bean实例化后执行,BeanPostProcessor在Bean销毁前执行

C

两者执行时机相同,只是处理的类型不同

D

BeanFactoryPostProcessor可以修改BeanDefinition,BeanPostProcessor只能修改Bean实例

24
单选题

在实现BeanPostProcessor时,需要注意一个重要问题:BeanPostProcessor不应该依赖其他普通Bean。以下哪种解释是正确的?

A

BeanPostProcessor是特殊组件,不允许使用@Autowired注入其他Bean

B

BeanPostProcessor执行时其他Bean尚未实例化,依赖注入会失败

C

BeanPostProcessor依赖其他Bean会导致循环依赖问题

D

BeanPostProcessor在ApplicationContext初始化时执行,此时Bean容器尚未就绪

25
多选题

BeanPostProcessor在Spring框架中有广泛的应用。以下哪些是BeanPostProcessor的典型应用场景?

A

AutowiredAnnotationBeanPostProcessor处理@Autowired注解进行依赖注入

B

AbstractAutoProxyCreator为标注@Transactional等方法创建AOP代理

C

CommonAnnotationBeanPostProcessor处理@PostConstruct和@PreDestroy注解

D

ApplicationContextAwareProcessor处理Aware接口回调

E

InstantiationAwareBeanPostProcessor在Bean实例化前执行,可替代实例化逻辑

F

SmartInitializingSingleton在所有单例Bean初始化完成后执行回调

26
多选题

Spring容器中的BeanPostProcessor执行顺序会影响Bean的处理结果。以下哪些关于BeanPostProcessor执行顺序的描述是正确的?

A

BeanPostProcessor通过实现PriorityOrdered或Ordered接口可以控制执行顺序

B

未实现Ordered接口的BeanPostProcessor按注册顺序执行

C

实现PriorityOrdered的BeanPostProcessor优先于实现Ordered的执行

D

同为PriorityOrdered或Ordered的按getOrder()返回值从小到大执行

E

ApplicationContext会自动注册ApplicationContextAwareProcessor作为第一个BeanPostProcessor

F

@Autowired注入BeanPostProcessor的顺序就是执行顺序

27
多选题

MergedBeanDefinitionPostProcessor是BeanPostProcessor的子接口,它在Bean生命周期中扮演特殊角色。以下哪些关于它的描述是正确的?

A

postProcessMergedDefinition方法在Bean实例化后、属性注入前执行

B

它用于收集BeanDefinition中的元数据(如注解信息)供后续处理使用

C

AutowiredAnnotationBeanPostProcessor实现了此接口,收集@Autowired注解元数据

D

CommonAnnotationBeanPostProcessor实现此接口,收集@PostConstruct注解元数据

E

通过实现此接口可以在Bean实例化前修改BeanDefinition的merged状态

F

merged BeanDefinition包含了来自父BeanDefinition的继承信息

28
填空题

BeanPostProcessor接口定义了两个核心方法,在Bean初始化前后执行:

  1. ________________________ - 在Bean属性注入后、初始化方法(@PostConstruct等)执行前调用
  2. ________________________ - 在初始化方法执行后调用,常用于创建AOP代理
29
单选题

EnvironmentPostProcessor是Spring Boot提供的扩展接口,用于在应用启动早期修改Environment配置。它的执行时机在哪个阶段?

A

在ApplicationContext创建之后、Bean实例化之前执行

B

在SpringApplication.run()启动后、ApplicationContext创建之前执行

C

在BeanFactoryPostProcessor执行期间执行

D

在所有自动配置类加载之后执行

30
单选题

自定义EnvironmentPostProcessor需要通过什么方式注册才能被Spring Boot识别和加载?

A

使用@Component注解标注,让Spring自动扫描注册

B

使用@Import注解导入EnvironmentPostProcessor类

C

在META-INF/spring.factories文件中配置org.springframework.boot.env.EnvironmentPostProcessor键

D

在application.yml中配置spring.environment.post-processors属性

31
单选题

在EnvironmentPostProcessor中添加自定义PropertySource时,如何确保自定义配置的优先级高于application.yml中的配置?

A

使用environment.getPropertySources().addLast()添加到最后,覆盖前面的配置

B

使用environment.getPropertySources().addFirst()添加到最前面,优先级最高

C

使用environment.getPropertySources().addAfter("applicationConfig")添加到application.yml后面

D

直接修改existing PropertySource的值,无需添加新的PropertySource

32
多选题

EnvironmentPostProcessor在Spring Boot中有很多实际应用场景,以下哪些是典型的应用场景?

A

从配置中心(如Nacos、Apollo)加载动态配置并添加到Environment

B

根据环境变量或主机名动态设置激活的profile

C

加载加密的配置文件并解密后添加到Environment

D

在开发环境自动添加调试相关的默认配置

E

为特定租户添加租户特定的配置(多租户场景)

F

统计Environment中所有PropertySource的配置项数量

33
多选题

在使用EnvironmentPostProcessor时,需要注意一些重要的限制和最佳实践。以下哪些描述是正确的?

A

EnvironmentPostProcessor执行时ApplicationContext尚未创建,不能使用@Autowired注入Bean

B

EnvironmentPostProcessor应该实现Ordered接口控制执行顺序,避免配置覆盖冲突

C

EnvironmentPostProcessor中可以使用Environment.getProperty()获取已有的配置值

D

EnvironmentPostProcessor不应该抛出异常,否则会阻止应用启动

E

EnvironmentPostProcessor可以通过lazy初始化延迟加载,减少启动时间

F

EnvironmentPostProcessor可以修改Environment的activeProfiles,动态添加或移除Profile

34
多选题

Spring Boot提供了多个启动阶段的扩展接口。以下关于EnvironmentPostProcessor与SpringApplicationRunListener的对比描述哪些是正确的?

A

SpringApplicationRunListener的environmentPrepared事件触发时机与EnvironmentPostProcessor相同

B

EnvironmentPostProcessor是接口,SpringApplicationRunListener通过事件监听方式扩展

C

EnvironmentPostProcessor只关注Environment处理,SpringApplicationRunListener可以监听整个启动流程

D

EnvironmentPostProcessor通过spring.factories加载,SpringApplicationRunListener也通过spring.factories加载

E

SpringApplicationRunListener可以返回自定义的Environment,EnvironmentPostProcessor只能修改现有Environment

F

两者执行顺序相同,EnvironmentPostProcessor实际上由SpringApplicationRunListener触发

35
判断题

EnvironmentPostProcessor添加的PropertySource优先级高于通过@PropertySource注解添加的配置源,因为EnvironmentPostProcessor执行时机早于@PropertySource处理。

A

B

36
单选题

Spring Boot的FailureAnalyzer接口用于什么目的?它的主要作用是什么?

A

在应用启动失败时分析失败原因并提供更友好的错误信息

B

在Bean创建失败时记录失败日志

C

在测试失败时分析测试错误原因

D

在应用运行时监控异常并自动恢复

37
单选题

如何实现自定义FailureAnalyzer来分析特定的异常类型?以下哪种实现方式是正确的?

A

实现FailureAnalyzer接口,使用@ExceptionHandler注解处理异常

B

继承AbstractFailureAnalyzer类,重写analyze方法分析特定异常类型T

C

实现BeanPostProcessor接口,在postProcessAfterInitialization中捕获异常

D

使用@ControllerAdvice全局异常处理器处理启动异常

38
单选题

自定义的FailureAnalyzer需要通过什么方式注册才能被Spring Boot在启动失败时调用?

A

使用@Component注解标注,让Spring自动扫描注册

B

使用@Import注解导入FailureAnalyzer类

C

在META-INF/spring.factories文件中配置org.springframework.boot.diagnostics.FailureAnalyzer键

D

在application.yml中配置spring.failure-analyzers属性

39
多选题

自定义FailureAnalyzer可以针对哪些场景提供更好的错误分析和提示?

A

自定义配置校验失败时,提示具体缺少哪些必填配置项

B

外部服务(如数据库、Redis)连接失败时,提示连接信息和排查建议

C

自定义注解处理失败时,提示注解使用方式和正确配置

D

Bean创建时的循环依赖异常分析

E

配置文件格式错误(如YAML语法错误)时,提示具体错误位置

F

应用正常运行时的业务异常分析

40
多选题

FailureAnalyzer返回的FailureAnalysis对象包含哪些信息?这些信息如何展示给用户?

A

description - 对失败的详细描述,说明发生了什么问题

B

action - 建议用户采取的操作,帮助解决问题

C

cause - 原始异常,用于调试和日志记录

D

输出格式包含分隔线、Description和Action三部分

E

FailureAnalysis的输出会替代原始异常堆栈

F

可以通过配置保留原始异常堆栈与FailureAnalysis一起显示

41
判断题

FailureAnalyzer在Spring Boot应用启动成功后不会被调用,只有在启动失败时才会执行异常分析和错误提示。

A

B

42
单选题

在Spring Boot Actuator中,如何创建自定义的端点?最简单的方式是使用哪个注解?

A

使用@Endpoint注解标注类,配合@ReadOperation/@WriteOperation/@DeleteOperation标注方法

B

使用@RestController注解创建Controller,路径前缀为/actuator

C

实现Endpoint接口,重写invoke方法

D

继承AbstractEndpoint类,实现自定义端点逻辑

43
单选题

在自定义Actuator端点中,如何返回特定的HTTP状态码?以下哪种方式是正确的?

A

在@ReadOperation方法中抛出异常,Spring会自动设置状态码

B

返回WebEndpointResponse对象,设置status和body

C

使用@ResponseStatus注解标注方法指定状态码

D

使用 ResponseEntity作为返回类型,手动设置状态码

44
单选题

自定义的Actuator端点默认不会自动暴露,需要通过配置来启用。以下哪种配置方式是正确的?

A

management.endpoints.web.exposure.include=mycustom 包含特定端点

B

management.endpoints.web.exposure.include=* 暴露所有端点(包括自定义)

C

management.endpoint.mycustom.enabled=true 只启用端点但不暴露

D

以上配置方式都需要配合Spring Security进行权限控制

45
多选题

在自定义Actuator端点中,@Selector注解用于定义路径参数。以下哪些关于@Selector的描述是正确的?

A

@Selector用于标注方法参数,表示该参数从URL路径中获取

B

单个@Selector参数的路径格式为:/actuator/{endpointId}/{selector}

C

多个@Selector参数可以使用@Selector(arg0="path1", arg1="path2")方式

D

@Selector参数可以是String类型,自动从路径解析

E

@Selector支持的路径格式类似于Spring MVC的@PathVariable

F

@Selector参数必须与URL路径的最后一部分匹配

46
多选题

在自定义Actuator端点的方法中,除了@Selector路径参数,还可以注入哪些类型的参数?

A

通过方法参数名自动匹配查询参数(如?name=value)

B

使用@Selector标注路径参数

C

注入Principal获取当前认证用户信息

D

注入SecurityContext获取安全上下文

E

使用@Nullable标注可选参数,允许参数不存在

F

注入HttpServletRequest获取完整的请求信息

47
判断题

自定义Actuator端点的id必须使用小写字母,不能包含特殊字符或空格,否则端点无法正确注册和访问。

A

B

48
判断题

自定义Actuator端点默认是启用(enabled=true)但不暴露的,需要在配置中添加到management.endpoints.web.exposure.include才能通过HTTP访问。

A

B

← 上一个专题 项目搭建与环境初始化专题

📝 发现内容有误?点击此处直接编辑

想查看更多习题和详细解析?
小程序提供完整的题库和详细解析

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库