单元测试类如下:

@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class Test{
    @Resource
    private AdSupportAccount adSupportAccount;
    @Test
    publict void test(){
        adSupportAccount.list(accountInfoQuery);
    }
}

Feign声明如下:

@FeignClient(value = "account-provider", url = "${account}")
public interface AdSupportAccount {

    /**
     * 分页查询account 列表
     *
     * @param accountInfoQuery
     * @return
     */
    @PostMapping("accountInfo/list")
    KkbResponse<Map<String, Object>> list(@RequestBody AccountInfoQuery accountInfoQuery);
}

debug可以看到AdSupportAccount实例其实被代理类FeignINvocationHandler持有。

下面截取部分Spring boot启动过程中的堆栈信息:

registerBeanDefinition:929, DefaultListableBeanFactory (org.springframework.beans.factory.support)
registerBeanDefinition:164, BeanDefinitionReaderUtils (org.springframework.beans.factory.support)
registerFeignClient:258, FeignClientsRegistrar (org.springframework.cloud.openfeign)
registerFeignClients:219, FeignClientsRegistrar (org.springframework.cloud.openfeign)
registerBeanDefinitions:144, FeignClientsRegistrar (org.springframework.cloud.openfeign)
registerBeanDefinitions:86, ImportBeanDefinitionRegistrar (org.springframework.context.annotation)
lambda$loadBeanDefinitionsFromRegistrars$1:384, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
accept:-1, 1868288866 (org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$$Lambda$276)
forEach:684, LinkedHashMap (java.util)
loadBeanDefinitionsFromRegistrars:383, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
loadBeanDefinitionsForConfigurationClass:148, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
loadBeanDefinitions:120, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
processConfigBeanDefinitions:332, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:237, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:280, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:96, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:707, AbstractApplicationContext (org.springframework.context.support)
refresh:533, AbstractApplicationContext (org.springframework.context.support)
refresh:755, SpringApplication (org.springframework.boot)
refresh:747, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)
loadContext:120, SpringBootContextLoader (org.springframework.boot.test.context)
loadContextInternal:99, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
loadContext:124, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
getApplicationContext:123, DefaultTestContext (org.springframework.test.context.support)
setUpRequestContextIfNecessary:190, ServletTestExecutionListener (org.springframework.test.context.web)
prepareTestInstance:132, ServletTestExecutionListener (org.springframework.test.context.web)
prepareTestInstance:244, TestContextManager (org.springframework.test.context)
createTest:227, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
runReflectiveCall:289, SpringJUnit4ClassRunner$1 (org.springframework.test.context.junit4)
run:12, ReflectiveCallable (org.junit.internal.runners.model)
methodBlock:291, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
runChild:246, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
runChild:97, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
run:331, ParentRunner$4 (org.junit.runners)
schedule:79, ParentRunner$1 (org.junit.runners)
runChildren:329, ParentRunner (org.junit.runners)
access$100:66, ParentRunner (org.junit.runners)
evaluate:293, ParentRunner$2 (org.junit.runners)
evaluate:61, RunBeforeTestClassCallbacks (org.springframework.test.context.junit4.statements)
evaluate:70, RunAfterTestClassCallbacks (org.springframework.test.context.junit4.statements)
evaluate:306, ParentRunner$3 (org.junit.runners)
run:413, ParentRunner (org.junit.runners)
run:190, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
run:137, JUnitCore (org.junit.runner)
startRunnerWithArgs:69, JUnit4IdeaTestRunner (com.intellij.junit4)
startRunnerWithArgs:33, IdeaTestRunner$Repeater (com.intellij.rt.junit)
prepareStreamsAndStart:235, JUnitStarter (com.intellij.rt.junit)
main:54, JUnitStarter (com.intellij.rt.junit)

其中

invokeBeanFactoryPostProcessors:707, AbstractApplicationContext (org.springframework.context.support)

表示spring boot 在启动过程中执行AbstractApplicationContext.invokeBeanFactoryPostProcessors();

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

最终会执行到FeignClientsRegistrar.registerBeanDefinitions();

public void registerBeanDefinitions(AnnotationMetadata metadata,
            BeanDefinitionRegistry registry) {
        registerDefaultConfiguration(metadata, registry);(1)
        registerFeignClients(metadata, registry);(2)
    }

其中(2)最终会调用到 registerFeignClient(BeanDefinitionRegistry registry,AnnotationMetadata annotationMetadata, Map<String, Object> attributes);
这个方法会有一个代码片段如下所示:

BeanDefinitionBuilder definition = BeanDefinitionBuilder
                .genericBeanDefinition(FeignClientFactoryBean.class);(1)

        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);(2)

(1)中创建了一个FeignClientFactoryBean类型的BeanDefinitionBuilder实例;

(2)最终把FeignClientFactoryBean类型的BeanDefinition,put进DefaultListableBeanFactory的beanDefinitionMap属性中,下面挑出几行栈调用和具体debug信息粘贴出来,方便大家验证核对:

loadBeanDefinitionsForConfigurationClass:148, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
image.png

registerBeanDefinitions:86, ImportBeanDefinitionRegistrar (org.springframework.context.annotation)

image.png

registerBeanDefinitions:144, FeignClientsRegistrar (org.springframework.cloud.openfeign)

image.png

registerFeignClients:219, FeignClientsRegistrar (org.springframework.cloud.openfeign)

image.png

registerFeignClient:258, FeignClientsRegistrar (org.springframework.cloud.openfeign)

image.png

registerBeanDefinition:164, BeanDefinitionReaderUtils (org.springframework.beans.factory.support)

image.png

registerBeanDefinition:975, DefaultListableBeanFactory 

                    this.beanDefinitionMap.put(beanName, beanDefinition);

image.png

由此,我们可以看出这个FeignClientsRegistrar这个类扮演了十分重要的角色,它作为和FeignClient声明类和FeignClientFactoryBean类的桥梁。而这个FeignClientFactoryBean,后面会展开描述;

那么,问题又来了,FeignClientsRegistrar这个类是怎么冒出的?下面揭晓:

@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {}

看到了吗?@Import(FeignClientsRegistrar.class);@EnableFeignClients这个注解应用在我们的Spring boot 项目的启动类上:

image.png

现在可以得出结论:当我们debug获取adSupportAccount实例的时候,最终会通过

getObject:251, FeignClientFactoryBean (org.springframework.cloud.openfeign)(1)

(1)获取到;下面是按照时间轴贴出来调用的堆栈信息:

getObject:251, FeignClientFactoryBean (org.springframework.cloud.openfeign)
doGetObjectFromFactoryBean:169, FactoryBeanRegistrySupport (org.springframework.beans.factory.support)
getObjectFromFactoryBean:101, FactoryBeanRegistrySupport (org.springframework.beans.factory.support)
getObjectForBeanInstance:1828, AbstractBeanFactory (org.springframework.beans.factory.support)
getObjectForBeanInstance:1270, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doGetBean:261, AbstractBeanFactory (org.springframework.beans.factory.support) [6]
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
resolveCandidate:276, DependencyDescriptor (org.springframework.beans.factory.config)
addCandidateEntry:1532, DefaultListableBeanFactory (org.springframework.beans.factory.support)
findAutowireCandidates:1489, DefaultListableBeanFactory (org.springframework.beans.factory.support)
doResolveDependency:1270, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveDependency:1227, DefaultListableBeanFactory (org.springframework.beans.factory.support)
autowireResource:521, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResource:497, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResourceToInject:650, CommonAnnotationBeanPostProcessor$ResourceElement (org.springframework.context.annotation)
inject:228, InjectionMetadata$InjectedElement (org.springframework.beans.factory.annotation)
inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
postProcessProperties:318, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
populateBean:1425, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 294505405 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$240)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support) [5]
getBean:207, AbstractBeanFactory (org.springframework.beans.factory.support)
resolveBeanByName:453, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
autowireResource:527, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResource:497, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResourceToInject:650, CommonAnnotationBeanPostProcessor$ResourceElement (org.springframework.context.annotation)
inject:228, InjectionMetadata$InjectedElement (org.springframework.beans.factory.annotation)
inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
postProcessProperties:318, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
populateBean:1425, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 294505405 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$240)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support) [4]
getBean:207, AbstractBeanFactory (org.springframework.beans.factory.support)
resolveBeanByName:453, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
autowireResource:527, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResource:497, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResourceToInject:650, CommonAnnotationBeanPostProcessor$ResourceElement (org.springframework.context.annotation)
inject:228, InjectionMetadata$InjectedElement (org.springframework.beans.factory.annotation)
inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
postProcessProperties:318, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
populateBean:1425, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 294505405 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$240)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support) [3]
getBean:207, AbstractBeanFactory (org.springframework.beans.factory.support)
resolveBeanByName:453, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
autowireResource:527, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResource:497, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResourceToInject:650, CommonAnnotationBeanPostProcessor$ResourceElement (org.springframework.context.annotation)
inject:228, InjectionMetadata$InjectedElement (org.springframework.beans.factory.annotation)
inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
postProcessProperties:318, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
populateBean:1425, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 294505405 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$240)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support) [2]
getBean:207, AbstractBeanFactory (org.springframework.beans.factory.support)
resolveBeanByName:453, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
autowireResource:527, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResource:497, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
getResourceToInject:650, CommonAnnotationBeanPostProcessor$ResourceElement (org.springframework.context.annotation)
inject:228, InjectionMetadata$InjectedElement (org.springframework.beans.factory.annotation)
inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
postProcessProperties:318, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
populateBean:1425, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 294505405 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$240)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support) [1]
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support)
refresh:551, AbstractApplicationContext (org.springframework.context.support)
refresh:755, SpringApplication (org.springframework.boot)
refresh:747, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)
loadContext:120, SpringBootContextLoader (org.springframework.boot.test.context)
loadContextInternal:99, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
loadContext:124, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
getApplicationContext:123, DefaultTestContext (org.springframework.test.context.support)
setUpRequestContextIfNecessary:190, ServletTestExecutionListener (org.springframework.test.context.web)
prepareTestInstance:132, ServletTestExecutionListener (org.springframework.test.context.web)
prepareTestInstance:244, TestContextManager (org.springframework.test.context)
createTest:227, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
runReflectiveCall:289, SpringJUnit4ClassRunner$1 (org.springframework.test.context.junit4)
run:12, ReflectiveCallable (org.junit.internal.runners.model)
methodBlock:291, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
runChild:246, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
runChild:97, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
run:331, ParentRunner$4 (org.junit.runners)
schedule:79, ParentRunner$1 (org.junit.runners)
runChildren:329, ParentRunner (org.junit.runners)
access$100:66, ParentRunner (org.junit.runners)
evaluate:293, ParentRunner$2 (org.junit.runners)
evaluate:61, RunBeforeTestClassCallbacks (org.springframework.test.context.junit4.statements)
evaluate:70, RunAfterTestClassCallbacks (org.springframework.test.context.junit4.statements)
evaluate:306, ParentRunner$3 (org.junit.runners)
run:413, ParentRunner (org.junit.runners)
run:190, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
run:137, JUnitCore (org.junit.runner)
startRunnerWithArgs:69, JUnit4IdeaTestRunner (com.intellij.junit4)
startRunnerWithArgs:33, IdeaTestRunner$Repeater (com.intellij.rt.junit)
prepareStreamsAndStart:235, JUnitStarter (com.intellij.rt.junit)
main:54, JUnitStarter (com.intellij.rt.junit)

可以看到我们声明的AdSupportAccount实例对象:
image.png
其实是FeignInvocationHandler.ReflectiveFeign;这样一来就首尾呼应了!


子瞻
1 声望9 粉丝