【问题标题】:Kotlin inner class as Spring BeanKotlin 内部类作为 Spring Bean
【发布时间】:2019-05-25 15:30:02
【问题描述】:

我在 Spring boot 中使用 Kotlin,但在创建 bean 时遇到了一些错误。

错误消息是 Spring 框架类中的 Index 0 out of bounds for length 0

我不明白为什么会导致这个 java 代码异常(spring)

for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
  Class<?> paramType = paramTypes[paramIndex];
  String paramName = (paramNames != null ? paramNames[paramIndex] : ""); // Here!           
  ...
}

这可能吗?

无论如何,我想知道如何将 spring bean 创建为具有属性值的 kotlin 内部类(@ConfigurationProperties)。

我的代码


// application.yml
naver:
  clientId: ...
  clientSecret: ...
  grantType: authorization_code
  redirectUri: ...
  accessTokenUrl: ...
  profileUrl: ...

// some codes
abstract class OAuth2Provider {
  lateinit var clientId: String
  lateinit var clientSecret: String
  lateinit var grantType: String
  lateinit var redirectUri: String
  lateinit var accessTokenUri: String
  lateinit var profileUri: String

  fun callback(code: String) = getProfiles(getAuthenticationResult(code))
  abstract fun getAuthenticationResult(code: String): AuthenticationResult
  abstract fun getProfiles(result: AuthenticationResult): Map<String, String>
}

@Component
class Providers(
  val restTemplate: RestTemplate
) {

  private fun createOauth2LoginParams(grantType: String, clientId: String, code: String): MultiValueMap<String, String> {
    val map = LinkedMultiValueMap<String, String>()
    map.add("grant_type", grantType)
    map.add("client_id", clientId)
    map.add("code", code)
    return map
  }

  private fun createOauth2HttpEntity(map: MultiValueMap<String, String>): HttpEntity<MultiValueMap<String, String>> {
    val headers = HttpHeaders()
    headers.contentType = APPLICATION_FORM_URLENCODED
    return HttpEntity(map, headers)
  }

  private fun createAuthenticationResult(url: String, entity: HttpEntity<MultiValueMap<String, String>>): AuthenticationResult {
    return restTemplate.postForObject(url, entity, AuthenticationResult::class.java)!!
  }

  private fun createProfileResponseEntity(url: String, result: AuthenticationResult): ResponseEntity<Map<*, *>> {
    val headers = HttpHeaders()
    headers.add("Authorization", result.tokenType + " " + result.accessToken)
    headers.contentType = MediaType.APPLICATION_FORM_URLENCODED

    val entity = HttpEntity<MultiValueMap<String, String>>(headers)
    return restTemplate.exchange(url, HttpMethod.GET, entity, Map::class.java)
  }

  @ConfigurationProperties("naver")
  @Component
  inner class Naver : OAuth2Provider() {

    override fun getAuthenticationResult(code: String): AuthenticationResult {
      val map = createOauth2LoginParams(grantType, clientId, code)
      map.add("client_secret", clientSecret);

      val entity = createOauth2HttpEntity(map)
      return createAuthenticationResult(accessTokenUri, entity)
    }

    override fun getProfiles(result: AuthenticationResult): Map<String, String> {
      val resultEntity = createProfileResponseEntity(profileUri, result)
      val body = resultEntity.body!!

      val uniqueId = body.get("id").toString()
      val imageUrl = body.get("profile_image").toString()

      val profiles = HashMap<String, String>()
      profiles["uniqueId"] = uniqueId
      profiles["imageUrl"] = imageUrl
      return profiles
    }
  }

}

错误

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.mubeeplayer.api.oauth2.Providers$Naver': Unexpected exception during bean creation; nested exception is java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:705) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1187) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]

谢谢。对不起我的英语。

【问题讨论】:

    标签: spring kotlin inner-classes spring-bean


    【解决方案1】:

    这似乎是spring framework issue

    根本原因已解释为:

    MethodParameter L:781

    if (function != null) { 
        List<KParameter> parameters = function.getParameters(); 
        KParameter parameter = parameters
            .stream()
            .filter(p -> KParameter.Kind.VALUE.equals(p.getKind()))
            .collect(Collectors.toList()) 
            .get(index); 
            return (parameter.getType().isMarkedNullable() || parameter.isOptional()); 
    }
    

    当检查DependencyDescriptor 中所需的构造函数参数时,上面的语句会过滤掉参数0,它是对外部类的引用,并且类型值为INSTANCE。

    然后它尝试根据初始输入索引访问参数,但流已被过滤为空。

    编辑

    但是,支持嵌套类并按预期工作。 nested 类是在 kotlin 中没有修饰符且在 java 中没有 static 修饰符的类中定义的类。另一方面,inner 类是在 kotlin 中具有 inner 修饰符而在 java 中没有修饰符的类中定义的类。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2018-10-01
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    相关资源
    最近更新 更多