如何使用实现ImportBeanDefinitionRegistrar在类中注入属性?

时间:2018-09-07 03:14:54

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

我想使用这些属性来设置一些摇摇欲坠的弹簧,但是当我实现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());
        });
    }

}

4 个答案:

答案 0 :(得分:0)

基本上,您需要将属性注入到类构造函数中。 因此,应使用自动接线配置才能使用它们。

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

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

答案 1 :(得分:0)

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

1. bean注册

2. bean初始化和实例化

SwaggerProperties仅在完成实例化的阶段2之后可以使用,但是 registerBeanDefinitions 是阶段1

答案 2 :(得分:0)

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

EnableCustomSwagger

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 {
}

答案 3 :(得分:0)

spring 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();

}

...