自定义@EnableX注解如何与导入的配置类共享其属性?
如何让自定义@EnableX注解与导入的配置类共享属性
下面提供两种Spring原生支持的实现方式,完全可以实现你想要的属性传递效果:
方式一:让配置类实现ImportAware接口
通过ImportAware接口,配置类可以直接获取到导入它的@EnableInteger注解的元数据,从而读取到注解属性值。
修改后的代码示例
- 保持
@EnableInteger注解定义不变:
import org.springframework.context.annotation.Import; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(GenericTest.SomeConfig.class) public @interface EnableInteger { boolean odd() default false; }
- 修改配置类
SomeConfig,实现ImportAware接口:
@Configuration static class SomeConfig implements ImportAware { private boolean generateOdd; @Override public void setImportMetadata(AnnotationMetadata importMetadata) { // 解析@EnableInteger注解的属性 Map<String, Object> annotationAttrs = importMetadata.getAnnotationAttributes(EnableInteger.class.getName()); if (annotationAttrs != null) { this.generateOdd = (boolean) annotationAttrs.get("odd"); } } @Bean Integer someInteger() { // 根据注解属性生成对应整数 return generateOdd ? 41 : 42; } }
- 测试类用法不变:
@ExtendWith(SpringExtension.class) @EnableInteger(odd = true) public class GenericTest { @Autowired @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") Integer someInteger; @Test void test() { // 验证注入的是奇数 assert someInteger % 2 == 1; } }
方式二:使用ImportBeanDefinitionRegistrar注册Bean
如果不想让配置类依赖Spring接口,可以自定义ImportBeanDefinitionRegistrar,直接根据注解属性动态注册Bean。
修改后的代码示例
- 修改
@EnableInteger注解,改为导入自定义的注册器:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(IntegerBeanRegistrar.class) public @interface EnableInteger { boolean odd() default false; }
- 实现自定义注册器
IntegerBeanRegistrar:
import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; import org.springframework.beans.factory.support.BeanDefinitionRegistry; public class IntegerBeanRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 获取@EnableInteger的odd属性值 Map<String, Object> annotationAttrs = importingClassMetadata.getAnnotationAttributes(EnableInteger.class.getName()); boolean isOdd = annotationAttrs != null ? (boolean) annotationAttrs.get("odd") : false; // 创建Bean定义,指定要生成的整数 GenericBeanDefinition beanDef = new GenericBeanDefinition(); beanDef.setBeanClass(Integer.class); beanDef.setFactoryMethodName("valueOf"); beanDef.getConstructorArgumentValues().addGenericArgumentValue(isOdd ? 41 : 42); // 注册名为someInteger的Bean registry.registerBeanDefinition("someInteger", beanDef); } }
- 测试类无需修改,注入的
someInteger会根据@EnableInteger(odd = true)生成对应奇数。
这两种方式都是Spring官方注解(比如@EnableAsync、@EnableCaching)常用的实现逻辑,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

