GVKun编程网logo

IntelliJ Idea中没有为Kotlin @ConfigurationProperties类生成spring-configuration- metadata.json文件

10

针对IntelliJIdea中没有为Kotlin@ConfigurationProperties类生成spring-configuration-metadata.json文件这个问题,本篇文章进行了详

针对IntelliJ Idea中没有为Kotlin @ConfigurationProperties类生成spring-configuration- metadata.json文件这个问题,本篇文章进行了详细的解答,同时本文还将给你拓展@Configuration+@ConfigurationProperties+@EnableConfigurationProperties、@Configuration配置和@ConfigurationProperties加载外部配置注解的使用。、c# – container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致InvalidOperationException、com.intellij.lang.ant.config.impl.configuration.BuildFilePropertiesPanel的实例源码等相关知识,希望可以帮助到你。

本文目录一览:

IntelliJ Idea中没有为Kotlin @ConfigurationProperties类生成spring-configuration- metadata.json文件

IntelliJ Idea中没有为Kotlin @ConfigurationProperties类生成spring-configuration- metadata.json文件

我正在尝试为基于Spring Boot的项目生成spring-configuration-metadata.json文件。如果我使用Java
@ConfigurationProperties 类,则会正确并自动生成:

@ConfigurationProperties("myprops")public class MyProps {    private String hello;    public String getHello() {        return hello;    }    public void setHello(String hello) {        this.hello = hello;    }}

但是,如果我使用Kotlin类,则不会生成 spring-configuration-metadata.json 文件(我已经尝试了
gradle build 和Idea Rebuild Project )。

@ConfigurationProperties("myprops")class MyProps {    var hello: String? = null}

AFAIK Kotlin使用构造函数,getter和setter生成相同的类,并且应充当常规Java Bean。

有什么想法为什么 spring-boot-configuration-processor 不适用于Kotlin类?

答案1

小编典典

谢谢您指出正确的方向。所以解决方案是添加

dependencies {    ...    kapt "org.springframework.boot:spring-boot-configuration-processor"    optional "org.springframework.boot:spring-boot-configuration-processor"    ...}

生成 build.gradle 文件,在命令行中运行 gradle compileJava 并在IntelliJ Idea设置
Build,Execution,Deployment- > Compiler-> Annotation Processor-> Enable
annotation processing中打开注释处理
。其余配置保持不变

另请注意,没有此行

optional "org.springframework.boot:spring-boot-configuration-processor"

IntelliJ Idea将抱怨

无法解析配置属性

您的 application.properties*application.yml中的 消息 *

@Configuration+@ConfigurationProperties+@EnableConfigurationProperties

@Configuration+@ConfigurationProperties+@EnableConfigurationProperties

 @Configuration+@ConfigurationProperties+@EnableConfigurationProperties

 

 

最佳设计方案(现在又改板了):

Bean上面直接设置@ConfigurationProperties

//需要依赖spring-boot-configuration-processor

@ConfigurationProperties(prefix = "stu")

public class Stu {

    String name;

 

    public Stu(String name) {

        this.name = name;

    }

 

    public Stu() {

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public String toString() {

        return "Stu{" +

                "name=''" + name + ''\'''' +

                ''}'';

    }

}

方式一:configuration上面跟随@EnableConfigurationProperties【这种情况只有configuration里面一个Bean 】

@Configuration

@EnableConfigurationProperties

public class StuConfiguration {

    @Bean

    public Stu stu(){

        return  new Stu();

    }

}

方式二:configuration上面跟随@EnableConfigurationProperties【这种情况只有configuration里面一个Bean 】

package com.example.demo11.configuration;

import com.example.demo11.entity.Stu;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

//@EnableConfigurationProperties(Stu.class),如果携带class参数则有用注册Bean的能力,

//因为实现了ImportBeanDefinitionRegistrar接口,Import三插之一

//这里的Bean名称非常有意思【类型名称+全包名】

@EnableConfigurationProperties(Stu.class)

public class StuConfiguration {

    @Bean

    public Stu stu2(){

        return  new Stu();

    }

}

启动查看

@SpringBootApplication

public class Demo11Application {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(Demo11Application.class, args);

        Stu stu = context.getBean("stu-com.example.demo11.entity.Stu", Stu.class);

        System.out.println(context.getBeansOfType(Stu.class).size());

        System.out.println(stu.toString());

        context.close();

    }

 

}

@Configuration配置和@ConfigurationProperties加载外部配置注解的使用。

@Configuration配置和@ConfigurationProperties加载外部配置注解的使用。

那么在Spring boot项目中,应用上下文又是如何找到那么多配置并加载初始化好的呢?

@SpringBootApplication
spring boot项目推荐大家在主类中标注@SpringBootApplication这个注解,我们来看看它的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration //配置
@EnableAutoConfiguration //启用自动配置
//组件扫描
@ComponentScan(excludeFilters = @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class))
public @interface SpringBootApplication {
//需要排除的自动配置类
Class<?>[] exclude() default {};
//需要排除的自动配置类类名
String[] excludeName() default {};

 //扫描包路径

@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};

  //扫描包路径类

@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
@EnableAutoConfiguration
我们发现一个配置开关注解,名字叫@EnableAutoConfiguration,看看它的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

//是否启用自动配置的总开关名

String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
//需要排除的自动配置类
Class<?>[] exclude() default {};

//需要排除的自动配置类类名

String[] excludeName() default {};
}
EnableAutoConfigurationImportSelector
我们看到有一个@Import导入了选择器EnableAutoConfigurationImportSelector.class,看看它的源码:
public class EnableAutoConfigurationImportSelector

  implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
  BeanFactoryAware, EnvironmentAware, Ordered {

...

c# – container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致InvalidOperationException

c# – container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致InvalidOperationException

在我的集成测试中,我使用的是我正在测试的Web API项目中构建的相同的SimpleInjector.Container.

但是组合根类中的这一行:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

导致异常:

System.TypeInitializationException : The type initializer for 'MyProject.Api.Test.Integration.HttpClientFactory' threw an exception.
---- system.invalidOperationException : This method cannot be called during the application's pre-start initialization phase.
Result StackTrace:  
at MyProject.Api.Test.Integration.HttpClientFactory.Create()
   at MyProject.Api.Test.Integration.Controllers.ProductControllerIntegrationTest.<GetProductBarcode_Should_Return_Status_BadRequest_When_Barcode_Is_Empty>d__0.MoveNext() in d:\Projects\My\MyProject.Api.Test.Integration\Controllers\ProductControllerIntegrationTest.cs:line 26
----- Inner Stack Trace -----
   at System.Web.Compilation.BuildManager.EnsuretopLevelFilesCompiled()
   at System.Web.Compilation.BuildManager.GetReferencedAssemblies()
   at System.Web.Http.WebHost.WebHostAssembliesResolver.System.Web.Http.dispatcher.IAssembliesResolver.GetAssemblies()
   at System.Web.Http.dispatcher.DefaultHttpControllerTypeResolver.GetControllerTypes(IAssembliesResolver assembliesResolver)
   at System.Web.Http.WebHost.WebHostHttpControllerTypeResolver.GetControllerTypes(IAssembliesResolver assembliesResolver)
   at SimpleInjector.SimpleInjectorWebApiExtensions.GetControllerTypesFromConfiguration(HttpConfiguration configuration)
   at SimpleInjector.SimpleInjectorWebApiExtensions.RegisterWebApiControllers(Container container,HttpConfiguration configuration)
   at MyProject.Api.ContainerConfig.RegisterTypes(Container container) in d:\Projects\My\MyProject.Api\App_Start\ContainerConfig.cs:line 128
   at MyProject.Api.ContainerConfig.CreateWebApiContainer() in d:\Projects\My\MyProject.Api\App_Start\ContainerConfig.cs:line 63
   at MyProject.Api.Test.Integration.HttpClientFactory..cctor() in d:\Projects\My\MyProject.Api.Test.Integration\HttpClientFactory.cs:line 17

评论后,一切正常,网络应用程序本身和测试.

所以问题是:

>例外的原因是什么?
>(这种方法真的需要吗?)

这是HttpClientFactory的代码(一个辅助类,用于创建具有适当头的HttpClient,例如api密钥或授权):

internal static class HttpClientFactory
{
    private static readonly Container _container = ContainerConfig.CreateWebApiContainer();

    public static HttpClient Create()
    {
        var client = new HttpClient { BaseAddress = GetUrl() };
        //...
        return client;
    }
}

解决方法

如果我们仔细观察堆栈跟踪,我们可以准确地看到这里发生了什么. RegisterWebApiControllers扩展方法在从HttpConfiguration获取的IHttpControllerTypeResolver实例上调用GetControllerTypes方法,并传递也从配置中检索的IAssembliesResolver.调用GetControllerTypes方法(WebHostHttpControllerTypeResolver)调用DefaultHttpControllerTypeResolver的GetControllerTypes,最终将调用System.Web.Compilation.BuildManager类的GetReferencedAssemblies.

但是,System.Web.Compilation.BuildManager不能在ASP.NET管道的早期调用,也不能在ASP.NET的上下文之外调用.由于您正在进行测试,BuildManage将抛出您遇到的异常.

所以这里的解决方案(或’技巧’)将在单元测试时替换默认的IAssembliesResolver.我认为旋转变压器看起来像这样:

public class TestAssembliesResolver : IAssembliesResolver
{
    public ICollection<Assembly> GetAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies();
    }
}

[TestMethod]
public void TestMethod1()
{
    // Replace the original IAssembliesResolver.
    GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver),new TestAssembliesResolver());

    var container = SimpleInjectorWebApiInitializer.BuildContainer();

    container.Verify();
}

你不得不处理这个问题有点不幸,特别是因为Simple Injector的设计是可测试的.我们似乎忽略了这一点,将RegisterWebApiControllers扩展方法与Web API深深地集成在一起.我们必须退后一步,思考如何更轻松地验证单元测试中的Web API配置.

com.intellij.lang.ant.config.impl.configuration.BuildFilePropertiesPanel的实例源码

com.intellij.lang.ant.config.impl.configuration.BuildFilePropertiesPanel的实例源码

项目:intellij-ce-playground    文件:AntExplorer.java   
public void setBuildFileProperties() {
  final AntBuildFileBase buildFile = getCurrentBuildFile();
  if (buildFile != null && BuildFilePropertiesPanel.editBuildFile(buildFile,myProject)) {
    myConfig.updateBuildFile(buildFile);
    myBuilder.queueUpdate();
    myTree.repaint();
  }
}
项目:tools-idea    文件:AntExplorer.java   
public void setBuildFileProperties() {
  final AntBuildFileBase buildFile = getCurrentBuildFile();
  if (buildFile != null && BuildFilePropertiesPanel.editBuildFile(buildFile,myProject)) {
    myConfig.updateBuildFile(buildFile);
    myBuilder.queueUpdate();
    myTree.repaint();
  }
}
项目:consulo-apache-ant    文件:AntExplorer.java   
public void setBuildFileProperties() {
  final AntBuildFileBase buildFile = getCurrentBuildFile();
  if (buildFile != null && BuildFilePropertiesPanel.editBuildFile(buildFile,myProject)) {
    myConfig.updateBuildFile(buildFile);
    myBuilder.queueUpdate();
    myTree.repaint();
  }
}

今天关于IntelliJ Idea中没有为Kotlin @ConfigurationProperties类生成spring-configuration- metadata.json文件的分享就到这里,希望大家有所收获,若想了解更多关于@Configuration+@ConfigurationProperties+@EnableConfigurationProperties、@Configuration配置和@ConfigurationProperties加载外部配置注解的使用。、c# – container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致InvalidOperationException、com.intellij.lang.ant.config.impl.configuration.BuildFilePropertiesPanel的实例源码等相关知识,可以在本站进行查询。

本文标签: