Kotlin内部类作为Spring Bean [英] Kotlin inner class as 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.
推荐答案
这似乎是根本原因已被解释为:
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屋!