@ -1,3 +1,19 @@
@@ -1,3 +1,19 @@
/ *
* Copyright 2022 - 2022 the original author or authors .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* https : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
package org.springframework.cloud.openfeign.aot ;
import java.util.Map ;
@ -37,33 +53,31 @@ import org.springframework.util.ClassUtils;
@@ -37,33 +53,31 @@ import org.springframework.util.ClassUtils;
/ * *
* @author Olga Maciaszek - Sharma
* /
public class FeignClientBeanFactoryInitializationAotProcessor implements BeanRegistrationExcludeFilter , BeanFactoryInitializationAotProcessor {
public class FeignClientBeanFactoryInitializationAotProcessor
implements BeanRegistrationExcludeFilter , BeanFactoryInitializationAotProcessor {
private final GenericApplicationContext context ;
private final Map < String , BeanDefinition > feignClientBeanDefinitions ;
public FeignClientBeanFactoryInitializationAotProcessor ( GenericApplicationContext context , FeignClientFactory feignClientFactory ) {
public FeignClientBeanFactoryInitializationAotProcessor ( GenericApplicationContext context ,
FeignClientFactory feignClientFactory ) {
this . context = context ;
this . feignClientBeanDefinitions = getFeignClientBeanDefinitions ( feignClientFactory ) ;
}
@Override
public boolean isExcludedFromAotProcessing ( RegisteredBean registeredBean ) {
return registeredBean . getBeanClass ( )
. equals ( FeignClientFactoryBean . class ) | | feignClientBeanDefinitions
. containsKey ( registeredBean . getBeanClass ( ) . getName ( ) ) ;
return registeredBean . getBeanClass ( ) . equals ( FeignClientFactoryBean . class )
| | feignClientBeanDefinitions . containsKey ( registeredBean . getBeanClass ( ) . getName ( ) ) ;
}
private Map < String , BeanDefinition > getFeignClientBeanDefinitions ( FeignClientFactory feignClientFactory ) {
Map < String , FeignClientSpecification > configurations = feignClientFactory . getConfigurations ( ) ;
return configurations . values ( ) . stream ( )
. map ( FeignClientSpecification : : getClassName )
. filter ( Objects : : nonNull )
. filter ( className - > ! className . equals ( "default" ) )
. map ( className - > Map . entry ( className , context . getBeanDefinition ( className ) ) )
. collect ( Collectors . toMap ( Map . Entry : : getKey , Map . Entry : : getValue ) ) ;
return configurations . values ( ) . stream ( ) . map ( FeignClientSpecification : : getClassName ) . filter ( Objects : : nonNull )
. filter ( className - > ! className . equals ( "default" ) )
. map ( className - > Map . entry ( className , context . getBeanDefinition ( className ) ) )
. collect ( Collectors . toMap ( Map . Entry : : getKey , Map . Entry : : getValue ) ) ;
}
@Override
@ -75,7 +89,7 @@ public class FeignClientBeanFactoryInitializationAotProcessor implements BeanReg
@@ -75,7 +89,7 @@ public class FeignClientBeanFactoryInitializationAotProcessor implements BeanReg
return new AotContribution ( feignClientBeanDefinitions ) ;
}
private static class AotContribution implements BeanFactoryInitializationAotContribution {
private static final class AotContribution implements BeanFactoryInitializationAotContribution {
private final Map < String , BeanDefinition > feignClientBeanDefinitions ;
@ -84,22 +98,23 @@ public class FeignClientBeanFactoryInitializationAotProcessor implements BeanReg
@@ -84,22 +98,23 @@ public class FeignClientBeanFactoryInitializationAotProcessor implements BeanReg
}
@Override
public void applyTo ( GenerationContext generationContext , BeanFactoryInitializationCode beanFactoryInitializationCode ) {
Set < String > feignClientRegistrationMethods = feignClientBeanDefinitions . values ( )
. stream ( )
. map ( beanDefinition - > {
Assert . notNull ( beanDefinition , "beanDefinition cannot be null" ) ;
Assert . isInstanceOf ( GenericBeanDefinition . class , beanDefinition ) ;
GenericBeanDefinition registeredBeanDefinition = ( GenericBeanDefinition ) beanDefinition ;
MutablePropertyValues feignClientProperties = registeredBeanDefinition . getPropertyValues ( ) ;
return beanFactoryInitializationCode . getMethods ( )
. add ( buildMethodName ( ( String ) feignClientProperties . get ( "type" ) ) ,
method - > generateFeignClientRegistrationMethod ( method , feignClientProperties , registeredBeanDefinition ) )
. getName ( ) ;
} ) . collect ( Collectors . toSet ( ) ) ;
public void applyTo ( GenerationContext generationContext ,
BeanFactoryInitializationCode beanFactoryInitializationCode ) {
Set < String > feignClientRegistrationMethods = feignClientBeanDefinitions . values ( ) . stream ( )
. map ( beanDefinition - > {
Assert . notNull ( beanDefinition , "beanDefinition cannot be null" ) ;
Assert . isInstanceOf ( GenericBeanDefinition . class , beanDefinition ) ;
GenericBeanDefinition registeredBeanDefinition = ( GenericBeanDefinition ) beanDefinition ;
MutablePropertyValues feignClientProperties = registeredBeanDefinition . getPropertyValues ( ) ;
return beanFactoryInitializationCode . getMethods ( )
. add ( buildMethodName ( ( String ) feignClientProperties . get ( "type" ) ) ,
method - > generateFeignClientRegistrationMethod ( method , feignClientProperties ,
registeredBeanDefinition ) )
. getName ( ) ;
} ) . collect ( Collectors . toSet ( ) ) ;
MethodReference initializerMethod = beanFactoryInitializationCode . getMethods ( )
. add ( "initialize" , method - > generateInitializerMethod ( method , feignClientRegistrationMethods ) )
. toMethodReference ( ) ;
. add ( "initialize" , method - > generateInitializerMethod ( method , feignClientRegistrationMethods ) )
. toMethodReference ( ) ;
beanFactoryInitializationCode . addInitializer ( initializerMethod ) ;
}
@ -110,37 +125,48 @@ public class FeignClientBeanFactoryInitializationAotProcessor implements BeanReg
@@ -110,37 +125,48 @@ public class FeignClientBeanFactoryInitializationAotProcessor implements BeanReg
private void generateInitializerMethod ( MethodSpec . Builder method , Set < String > feignClientRegistrationMethods ) {
method . addModifiers ( Modifier . PUBLIC ) ;
method . addParameter ( DefaultListableBeanFactory . class , "registry" ) ;
feignClientRegistrationMethods . forEach ( feignClientRegistrationMethod - > method . addStatement ( "$N(registry)" , feignClientRegistrationMethod ) ) ;
feignClientRegistrationMethods . forEach ( feignClientRegistrationMethod - > method . addStatement ( "$N(registry)" ,
feignClientRegistrationMethod ) ) ;
}
private void generateFeignClientRegistrationMethod ( MethodSpec . Builder method , MutablePropertyValues feignClientPropertyValues , GenericBeanDefinition registeredBeanDefinition ) {
private void generateFeignClientRegistrationMethod ( MethodSpec . Builder method ,
MutablePropertyValues feignClientPropertyValues , GenericBeanDefinition registeredBeanDefinition ) {
Object feignQualifiers = feignClientPropertyValues . get ( "qualifiers" ) ;
Assert . notNull ( feignQualifiers , "Feign qualifiers cannot be null" ) ;
String qualifiers = "{\"" + String . join ( "\",\"" , ( String [ ] ) feignQualifiers ) + "\"}" ;
method
. addJavadoc ( "register Feign Client: $L" , feignClientPropertyValues . get ( "type" ) )
. addModifiers ( Modifier . PUBLIC , Modifier . STATIC )
. addParameter ( BeanDefinitionRegistry . class , "registry" )
. addStatement ( "Class clazz = $T.resolveClassName(\"$L\", null)" , ClassUtils . class , feignClientPropertyValues . get ( "type" ) )
. addStatement ( "$T definition = $T.genericBeanDefinition($T.class)" , BeanDefinitionBuilder . class ,
BeanDefinitionBuilder . class , FeignClientFactoryBean . class )
. addStatement ( "definition.addPropertyValue(\"name\",\"$L\")" , feignClientPropertyValues . get ( "name" ) )
. addStatement ( "definition.addPropertyValue(\"contextId\", \"$L\")" , feignClientPropertyValues . get ( "contextId" ) )
. addStatement ( "definition.addPropertyValue(\"type\", clazz)" )
. addStatement ( "definition.addPropertyValue(\"url\", \"$L\")" , feignClientPropertyValues . get ( "url" ) )
. addStatement ( "definition.addPropertyValue(\"path\", \"$L\")" , feignClientPropertyValues . get ( "path" ) )
. addStatement ( "definition.addPropertyValue(\"dismiss404\", $L)" , feignClientPropertyValues . get ( "dismiss404" ) )
. addStatement ( "definition.addPropertyValue(\"fallback\", $T.class)" , feignClientPropertyValues . get ( "fallback" ) )
. addStatement ( "definition.addPropertyValue(\"fallbackFactory\", $T.class)" , feignClientPropertyValues . get ( "fallbackFactory" ) )
. addStatement ( "definition.setAutowireMode($L)" , registeredBeanDefinition . getAutowireMode ( ) )
. addStatement ( "definition.setLazyInit($L)" , registeredBeanDefinition . getLazyInit ( ) ! = null ? registeredBeanDefinition . getLazyInit ( ) : false )
. addStatement ( "$T beanDefinition = definition.getBeanDefinition()" , AbstractBeanDefinition . class )
. addStatement ( "beanDefinition.setAttribute(\"$L\", clazz)" , FactoryBean . OBJECT_TYPE_ATTRIBUTE )
. addStatement ( "beanDefinition.setPrimary($L)" , registeredBeanDefinition . isPrimary ( ) )
. addStatement ( "$T holder = new $T(beanDefinition, \"$L\", new String[]$L)" , BeanDefinitionHolder . class ,
BeanDefinitionHolder . class , feignClientPropertyValues . get ( "type" ) , qualifiers )
. addStatement ( "$T.registerBeanDefinition(holder, registry) " , BeanDefinitionReaderUtils . class ) ;
method . addJavadoc ( "register Feign Client: $L" , feignClientPropertyValues . get ( "type" ) )
. addModifiers ( Modifier . PUBLIC , Modifier . STATIC )
. addParameter ( BeanDefinitionRegistry . class , "registry" )
. addStatement ( "Class clazz = $T.resolveClassName(\"$L\", null)" , ClassUtils . class ,
feignClientPropertyValues . get ( "type" ) )
. addStatement ( "$T definition = $T.genericBeanDefinition($T.class)" , BeanDefinitionBuilder . class ,
BeanDefinitionBuilder . class , FeignClientFactoryBean . class )
. addStatement ( "definition.addPropertyValue(\"name\",\"$L\")" , feignClientPropertyValues . get ( "name" ) )
. addStatement ( "definition.addPropertyValue(\"contextId\", \"$L\")" ,
feignClientPropertyValues . get ( "contextId" ) )
. addStatement ( "definition.addPropertyValue(\"type\", clazz)" )
. addStatement ( "definition.addPropertyValue(\"url\", \"$L\")" , feignClientPropertyValues . get ( "url" ) )
. addStatement ( "definition.addPropertyValue(\"path\", \"$L\")" ,
feignClientPropertyValues . get ( "path" ) )
. addStatement ( "definition.addPropertyValue(\"dismiss404\", $L)" ,
feignClientPropertyValues . get ( "dismiss404" ) )
. addStatement ( "definition.addPropertyValue(\"fallback\", $T.class)" ,
feignClientPropertyValues . get ( "fallback" ) )
. addStatement ( "definition.addPropertyValue(\"fallbackFactory\", $T.class)" ,
feignClientPropertyValues . get ( "fallbackFactory" ) )
. addStatement ( "definition.setAutowireMode($L)" , registeredBeanDefinition . getAutowireMode ( ) )
. addStatement ( "definition.setLazyInit($L)" ,
registeredBeanDefinition . getLazyInit ( ) ! = null ? registeredBeanDefinition . getLazyInit ( )
: false )
. addStatement ( "$T beanDefinition = definition.getBeanDefinition()" , AbstractBeanDefinition . class )
. addStatement ( "beanDefinition.setAttribute(\"$L\", clazz)" , FactoryBean . OBJECT_TYPE_ATTRIBUTE )
. addStatement ( "beanDefinition.setPrimary($L)" , registeredBeanDefinition . isPrimary ( ) )
. addStatement ( "$T holder = new $T(beanDefinition, \"$L\", new String[]$L)" ,
BeanDefinitionHolder . class , BeanDefinitionHolder . class ,
feignClientPropertyValues . get ( "type" ) , qualifiers )
. addStatement ( "$T.registerBeanDefinition(holder, registry) " , BeanDefinitionReaderUtils . class ) ;
}
}
}