【问题标题】:How to inject a properties in a class with implements ImportBeanDefinitionRegistrar?如何使用实现 ImportBeanDefinitionRegistrar 在类中注入属性?
【发布时间】:2019-02-12 08:20:43
【问题描述】:

我想使用这些属性将一些 swagger docket 设置为 spring,但是当我实现 ImportBeanDefinitionRegistrar 并出现错误时我无法获取这些属性

引起:java.lang.NoSuchMethodException: com.github.sofior.swagger.SwaggerAutoConfiguration.()

@Configuration
@EnableSwagger2
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements ImportBeanDefinitionRegistrar {

    private final SwaggerProperties properties;

    public SwaggerAutoConfiguration(SwaggerProperties properties) {
        this.properties = properties;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        System.out.println(properties);
        properties.getDockets().forEach((docketName, docketProperties) -> {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Docket.class);
            builder.addConstructorArgValue(docketProperties.getType());
            builder.addConstructorArgValue(docketProperties.getType());
            registry.registerBeanDefinition(docketName, builder.getRawBeanDefinition());
        });
    }

}

【问题讨论】:

  • 如果你想要一个解决方法来解决这个问题,我想我可以在下面的答案中给出一个

标签: spring spring-boot spring-boot-starter


【解决方案1】:

基本上,您需要将属性注入到您的类构造函数中。 所以配置应该是自动装配的以便它们工作。

@Autowired
public SwaggerAutoConfiguration(SwaggerProperties properties) {
    this.properties = properties;
}

这应该可以解决您的“属性”为空的问题。

【讨论】:

    【解决方案2】:

    我认为这是不可能的,因为春天有两个阶段

    1.bean注册

    2.bean初始化和实例化

    SwaggerProperties 只能在阶段 2 完成实例化后使用,但 registerBeanDefinitions 是阶段 1

    【讨论】:

    • 那么这里有其他方法吗?获取属性并注册bean。非常感谢
    • 看我的另一个答案
    【解决方案3】:

    这个问题的解决方法是在 registerBeanDefinitions 期间读取一个新的属性

    启用CustomSwagger

    import org.springframework.context.annotation.Import;
    import java.lang.annotation.Documented;
    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)
    @Documented
    @Import(SwaggerAutoConfiguration.class)
    public @interface EnableCustomSwagger {
        String path() default "";
    }
    

    SwaggerAutoConfiguration

    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.annotation.AnnotationAttributes;
    import org.springframework.core.io.DefaultResourceLoader;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.ResourceLoader;
    import org.springframework.core.type.AnnotationMetadata;
    
    
    public class SwaggerAutoConfiguration implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            String clsName = EnableCustomSwagger.class.getName();
            AnnotationAttributes attrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(clsName, false));
            if (!attrs.getString("path").equals("")) {
                String path = attrs.getString("path");
                ResourceLoader loader = new DefaultResourceLoader();
                Resource resource = loader.getResource(path);
                // you can get the value from your property files
            }
    
            //how can I get properties here,the properties is null
    
    //        properties.getDockets().forEach((docketName, docketProperties) -> {
    //            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Docket.class);
    //            builder.addConstructorArgValue(docketProperties.getType());
    //            builder.addConstructorArgValue(docketProperties.getType());
    //            registry.registerBeanDefinition(docketName, builder.getRawBeanDefinition());
    //        });
        }
    
    }
    

    应用

    @SpringBootApplication
    @EnableCustomSwagger(path="classpath:docklet.properties")
    public class Application {
    }
    

    【讨论】:

    • 你有没有得到这个工作?属性仍将为空。我想做同样的事情,在属性文件中设置 bean,然后动态地创建和注册这些 bean。
    【解决方案4】:

    春天 2.x

    import org.springframework.boot.context.properties.bind.Binder;
    public class MultipleDataSourceComponentRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
    ...
    

    private Environment environment; @Override public void setEnvironment(Environment environment) { this.environment = environment; }

     @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        ConfigurationProperties annotationCp = MultipleDataSourceSetProperties.class.getAnnotation(ConfigurationProperties.class);
        MultipleDataSourceSetProperties properties = Binder.get(environment).bind(annotationCp.prefix(), MultipleDataSourceSetProperties.class).get();
    
    }
    

    ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-09
      • 2011-09-07
      相关资源
      最近更新 更多