Kotlin内部类作为Spring Bean [英] Kotlin inner class as Spring Bean

查看:106
本文介绍了Kotlin内部类作为Spring Bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Spring Boot中使用Kotlin,但遇到了有关bean创建的一些错误.

I used Kotlin with Spring boot and i met some errors about bean creation.

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

error message was Index 0 out of bounds for length 0 in spring framework class

我不明白为什么导致有关此Java代码(弹簧)的异常

i dont understand why caused exception about this java code(spring)

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

有可能吗?

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

anyway, i want to know how create spring bean as kotlin inner class with property values(@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]

谢谢.对不起,我的英语.

Thank you. sorry for my english.

推荐答案

这似乎是根本原因已被解释为:

方法参数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的种类值.

When checking for required constructor parameters in DependencyDescriptor the statement above filters out Parameter 0 which is a reference to the outer class and has kind value of INSTANCE.

然后尝试基于初始输入索引访问参数,但该流已被过滤为空.

It then attempts to access the parameter based on the initial input index, but the stream has been filtered down to empty.

修改

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

Nested classes are however supported and work as expected. A nested class is a class defined inside a class having no modifier in kotlin and static modifier in java. An inner class on the other hand is a class defined inside a class having inner modifier in kotlin and no modifier in java.

这篇关于Kotlin内部类作为Spring Bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆