1. Feign配置流程
1.1 Feign相关注解说明
1.1.1 @EnableFeignClients
注解
扫描声明为feign客户端的接口( 通过 @FeignClient
注解),配置组件扫描指令用于与 @Configuration
一起使用。
org.springframework.cloud.openfeign.EnableFeignClients
java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
/**
* basePackages属性的别名,允许更灵活的写法;
* 如 @ComponentScan("org.my.pkg"),而不是写为 @ComponentScan(basePackages="org.my.pkg")
*
* @return 返回basePackages的字符串数组。
*/
String[] value() default {};
/**
* 注解组件扫描的基础包。
* value属性是该属性的别名。
* 类型安全的变体是使用basePackageClasses()属性,直接指定Class,而不是使用基于字符串的包名。
* @return 返回basePackages字符串数组。
*/
String[] basePackages() default {};
/**
* basePackages()属性类型安全的变体,直接使用Class对象数组指定要扫描的注解组件所在的包。
* 该属性设置的每个Class所在的包都扫描。
* 推荐在每个需要扫描的包中创建一个特殊的没有任何操作的标记类或接口,仅仅用于设置需要扫描的包。
* @return 返回basePackageClasses的Class数组。
*/
Class<?>[] basePackageClasses() default {};
/**
* 为所有feign客户端指定的自定义的@Configuration。
* 可以覆盖@Bean定义中组成feign客户端的组件设置,如Decoder、Encoder、Contract等。
* @return 默认配置的Class数组。
*/
Class<?>[] defaultConfiguration() default {};
/**
* 使用@FeignClient注解的类的Class数组。如果非空,则禁用类路径扫描。
* @return list of FeignClient classes
*/
Class<?>[] clients() default {};
}
1.1.2 @FeignClient
注解
业务接口使用该注解标记之后,该业务接口的实现类对象基于feign客户端实现,是一个代理对象。
如果Spring Cloud的LoadBalancer可用,就使用Spring Cloud的LoadBalancer对后端的请求进行负载均衡。
org.springframework.cloud.openfeign.FeignClient
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {
/**
* 服务的名称,具有可选的协议前缀。name的同义词。
* 无论客户端是否指定了url,都必须配置name属性值。
* 同时该属性的值中可以包含SpEL表达式,如${propertyKey}。
* @return 返回带有可选协议前缀的服务name值。
*/
@AliasFor("name")
String value() default "";
/**
* 该属性的值作为bean的名称,而不是作为name属性值,但是不作为服务的ID。
* @return 返回bean的名称而不是name属性的值。
*/
String contextId() default "";
/**
* @return 返回带有可选协议前缀的服务id,value的同义词。
*/
@AliasFor("value")
String name() default "";
/**
* @return 返回feign客户端的@Qualifiers值。
*/
String[] qualifiers() default {};
/**
* @return 返回绝对的URL或可解析的hostname(协议是可选的)。
*/
String url() default "";
/**
* @return 404错误是否应该解析而不是抛异常FeignExceptions。默认false表示抛异常。
*/
boolean dismiss404() default false;
/**
* feign客户端的自定义配置类。
* 在该配置中可以覆盖构建feign客户端用到的@Bean定义,如Decoder、Encoder以及Contract。
* @return 返回feign客户端的配置类列表。
*/
Class<?>[] configuration() default {};
/**
* 指定feign客户端接口的服务降级类。该服务降级类必须实现@FeignClient标记的接口;
* 同时服务降级类必须是一个spring bean。
* @return 返回指定feign客户端接口的服务降级类。
*/
Class<?> fallback() default void.class;
/**
* 为指定的feign客户端接口定义服务降级工厂。
* 服务降级工厂生产的服务降级实例必须实现@FeignClient标记的接口。
* 同时服务降级工厂必须是一个spring bean。
* @return 返回指定feign客户端接口的服务降级工厂Class对象。
*/
Class<?> fallbackFactory() default void.class;
/**
* 返回所有方法级别映射的路径前缀。
*/
String path() default "";
/**
* 返回:是否将feign代理对象标记为首选bean,默认true。
*/
boolean primary() default true;
}
1.2. Feign涉及到的配置类
1.2.1 feign注解的处理
org.springframework.cloud.openfeign.FeignAutoConfiguration.DefaultFeignTargeterConfiguration
java
@Configuration(proxyBeanMethods = false)
@Conditional(FeignCircuitBreakerDisabledConditions.class)
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
}
在配置中,将targeter添加到上下文中。
org.springframework.cloud.openfeign.DefaultTargeter
java
class DefaultTargeter implements Targeter {
@Override
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context,
Target.HardCodedTarget<T> target) {
return feign.target(target);
}
}
默认的Targeter实现中,target方法的执行如下:
- 直接调用feign的target方法创建业务接口代理对象的实例。
1.3. feign注解的处理流程
1.3.1 主入口方法
org.example.openfeign.demo.BizApplication#main
java
public static void main(String[] args) {
SpringApplication.run(BizApplication.class, args);
}
1.3.2 SpringApplication的run方法
org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String...)
java
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
1.3.3 SpringApplication重载的run方法
静态帮助类,可用于从指定的资源使用默认的设置以及用户提供的参数运行一个SpringApplication。
传递的参数:
primarySource
:优先加载的资源;args
:应用参数,通常是从java的main方法传递进来的;
返回值:
- 返回运行中的ApplicationContext对象。
org.springframework.boot.SpringApplication#run(java.lang.Class<?>[], java.lang.String[])
java
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
1.3.4 SpringApplication重载的run方法
运行Spring应用,创建并刷新一个新的ApplicationContext对象。
传递的参数:
args
:应用参数,通常是从java的main方法传递进来的;
返回值:
- 返回运行中的ApplicationContext对象。
org.springframework.boot.SpringApplication#run(java.lang.String...)
java
public ConfigurableApplicationContext run(String... args) {
// 记录当前时间
long startTime = System.nanoTime();
// 创建Bootstrap上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 配置无头属性值
configureHeadlessProperty();
// 根据传递的参数获取Spring应用运行的监听器集合
SpringApplicationRunListeners listeners = getRunListeners(args);
// 开始监听
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 创建默认的应用参数对象,封装传递的应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建应用上下文
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文
refreshContext(context);
// 应用上下文刷新后处理
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 调用监听器的started方法,通知应用上下文已经启动了。
listeners.started(context, timeTakenToStartup);
// 调用runners
callRunners(context, applicationArguments);
} catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// runners执行结束后,标记上下文已经准备好。
listeners.ready(context, timeTakenToReady);
}
} catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回运行中的应用上下文
return context;
}
1.3.5 SpringApplication的刷新上下文
org.springframework.boot.SpringApplication#refreshContext
java
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);
}
// 调用refresh方法刷新指定的应用上下文
refresh(context);
}
1.3.6 SpringApplication的 refresh
方法
调用应用上下文的refresh方法刷新上下文。
org.springframework.boot.SpringApplication#refresh
java
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
1.3.7 ServletWebServerApplicationContext的refresh方法
上下文刷新的方法
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh
java
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
// 调用父类的方法执行上下文的刷新
super.refresh();
} catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
1.3.8 抽象应用上下文的刷新方法
执行抽象应用上下文中的刷新方法。
org.springframework.context.support.AbstractApplicationContext#refresh
java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 1. 准备刷新
prepareRefresh();
// 2. 通知子类刷新内部bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备当前上下文中用到的bean工厂。
prepareBeanFactory(beanFactory);
try {
// 4. 允许上下文子类中的bean工厂的后处理。
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 5. 调用注册到上下文中的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册拦截bean创建的bean处理器。
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 7. 初始化当前上下文中用到的消息源。
initMessageSource();
// 8. 初始化当前上下文中的事件多播。
initApplicationEventMulticaster();
// 9. 初始化特定子类上下文中的其他指定的bean。
onRefresh();
// 10. 检查监听器bean并注册。
registerListeners();
// 11. 初始化剩余的非懒初始化的单例bean。
finishBeanFactoryInitialization(beanFactory);
// 12. 最后,发布对应的事件。
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
1.3.9 抽象应用上下文的调用bean工厂后处理器方法
实例化并调所有注册的BeanFactoryPostProcessor bean,如果显式指定了顺序就按照指定的顺序调用。
必须在单例实例化之前调用。
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
java
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 使用后处理注册表代理调用bean工厂后处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1.3.10 抽象应用上下文的调用bean工厂后处理器的重载方法
抽象应用上下文中的调用bean工厂后处理器的方法。
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
java
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 如果有的话,先调用BeanDefinitionRegistryPostProcessors。
Set<String> processedBeans = new HashSet<>();
// 如果bean工厂是BeanDefinitionRegistry类型
if (beanFactory instanceof BeanDefinitionRegistry registry) {
// 新建普通后处理器集合
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 1. 首先,调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(
currentRegistryProcessors, registry, beanFactory.getApplicationStartup()
);
currentRegistryProcessors.clear();
// 2. 然后,调用实现了Ordered接口的BeanDefinitionRegistryPostProcessors。
postProcessorNames = beanFactory.getBeanNamesForType(
BeanDefinitionRegistryPostProcessor.class,
true,
false
);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(
beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)
);
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(
currentRegistryProcessors,
registry,
beanFactory.getApplicationStartup()
);
currentRegistryProcessors.clear();
// 3. 最后,调用调用其余的BeanDefinitionRegistryPostProcessors。
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(
BeanDefinitionRegistryPostProcessor.class,
true,
false
);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(
beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)
);
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(
currentRegistryProcessors, registry, beanFactory.getApplicationStartup()
);
currentRegistryProcessors.clear();
}
// 4. 现在,对所有已经处理过的所有处理器,调用它们的postProcessBeanFactory回调。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// 否则,调用使用上下文实例注册的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames = beanFactory.getBeanNamesForType(
BeanFactoryPostProcessor.class,
true,
false
);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
} else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(
beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)
);
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
} else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(
beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)
);
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(
beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)
);
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
1.3.11 后处理器注册表代理的调用bean定义注册中心处理器的方法
调用指定的BeanDefinitionRegistryPostProcessor beans。
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
java
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors,
BeanDefinitionRegistry registry,
ApplicationStartup applicationStartup) {
// 遍历后处理器集合
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start(
"spring.context.beandef-registry.post-process"
).tag("postProcessor", postProcessor::toString);
// 调用处理器的bean定义注册中心的后处理方法进行处理
postProcessor.postProcessBeanDefinitionRegistry(registry);
// 后处理结束
postProcessBeanDefRegistry.end();
}
}
1.3.12 bean定义注册表的后处理
从注册中心的配置类中导出更多的bean定义。
org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
java
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
// 如果已经处理过了,则抛异常
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
// 如果已经处理过了,则抛异常
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
// 将注册中心id添加到已处理集合中
this.registriesPostProcessed.add(registryId);
// 处理注册中心配置类的bean定义
processConfigBeanDefinitions(registry);
}
1.3.13 处理配置类的bean定义
基于 Configuration
类的注册中心构建并验证配置模型。
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
java
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 新建bean定义持有对象的列表集合
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 从注册中心获取bean定义的名称集合
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历名称集合
for (String beanName : candidateNames) {
// 从注册中心获取当前bean名称对应的bean定义
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 如果bean定义中CONFIGURATION_CLASS_ATTRIBUTE对应的属性不是null,则记录日志
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
} else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 否则,如果配置类通过了校验,则创建新的bean定义持有对象,添加到bean定义持有对象集合中。
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 如果没有找到 @Configuration 类,则方法立即返回。
if (configCandidates.isEmpty()) {
return;
}
// 对配置类持有对象中包含的bean定义的order值执行数值排序
configCandidates.sort((bd1, bd2) -> {
// 获取order值
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
// 获取order值
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
// 返回比较的结果
return Integer.compare(i1, i2);
});
// 检测通过嵌套的应用上下文提供的用户自定义bean名称生成策略。
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry _sbr) {
sbr = _sbr;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR
);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
// 如果环境为null,则创建标准环境对象并赋值
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory,
this.problemReporter,
this.environment,
this.resourceLoader,
this.componentScanBeanNameGenerator,
registry
);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry,
this.sourceExtractor,
this.resourceLoader,
this.environment,
this.importBeanNameGenerator,
parser.getImportRegistry()
);
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = Set.of(candidateNames);
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
bd,
this.metadataReaderFactory)
&& !alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
} while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
// Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
this.propertySourceDescriptors = parser.getPropertySourceDescriptors();
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
cachingMetadataReaderFactory.clearCache();
}
}
1.3.14 加载bean定义
读取 configurationModel
,使用基于其内容的注册中心执行bean定义的注册。
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
java
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// 遍历配置模型中的配置类
for (ConfigurationClass configClass : configurationModel) {
// 从配置类中加载bean定义
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
1.3.15 为配置类加载bean定义
读取指定的 ConfigurationClass
注册该bean,同时对其内部包含的 @Bean
注解的方法返回值进行bean定义的注册。
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
java
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 如果配置类应该跳过,则
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
// 如果beanName不为空并且注册中心包含该名称的bean定义,则从注册中心移除该bean的定义。
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
// 引入的注册中心移除引入的bean定义。
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
// 方法返回
return;
}
// 如果配置类是引入的
if (configClass.isImported()) {
// 对引入的配置类执行bean定义的注册
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 获取配置类中所有添加了 @Bean 注解的方法,遍历
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 从 @Bean 注解的方法加载bean的定义
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 从引入的配置类中引入的资源中加载bean定义
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 从引入的配置类的引入的bean定义注册中心加载bean的定义
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
1.3.16 从注册表加载bean定义
调用 regsiterBeanDefinitions
方法执行bean定义的注册。
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
java
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
// 遍历registrars集合,调用registrar的注册bean定义方法执行bean定义的注册
registrars.forEach((registrar, metadata) ->
// 调用registerBeanDefinitions方法执行bean定义的注册。
registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator)
);
}
1.3.17 注册bean定义
基于引入的@Configuration类注册bean的定义。
注意:由于与@Configuration类处理的声明周期限制,BeanDefinitionRegistryPostProcessor类型可能不会在这里注册。
默认实现将bean定义的注册代理给 registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry)
方法。
传递的参数:
-
importingClassMetadata
:引入类的注解元数据; -
registry
:当前bean定义注册中心; -
importBeanNameGenerator
:引入的bean的名称生成器,默认使用ConfigurationClassPostProcessor.IMPORT_BEAN_NAME_GENERATOR
,如果用户通过ConfigurationClassPostProcessor.setBeanNameGenerator
设置了命名规则,则使用用户指定的命名规则。对于用户指定的命名规则,同样用于所在的应用上下文的组件扫描,否则默认使用
AnnotationBeanNameGenerator.INSTANCE
执行组件扫描。
org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.beans.factory.support.BeanNameGenerator)
java
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
// 注册bean定义
registerBeanDefinitions(importingClassMetadata, registry);
}
1.3.18 注册bean定义
org.springframework.cloud.openfeign.FeignClientsRegistrar#registerBeanDefinitions
java
// 注册bean定义
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 注册默认的配置
registerDefaultConfiguration(metadata, registry);
// 注册feign客户端
registerFeignClients(metadata, registry);
}
1.3.18.1 注册默认配置
org.springframework.cloud.openfeign.FeignClientsRegistrar#registerDefaultConfiguration
java
// 注册默认的配置
private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 获取EnableFeignClients注解的属性集合
Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
// 如果存在,并且提供了defaultConfiguration配置
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
String name;
if (metadata.hasEnclosingClass()) {
name = "default." + metadata.getEnclosingClassName();
} else {
name = "default." + metadata.getClassName();
}
// 注册客户端配置
registerClientConfiguration(registry, name, "default", defaultAttrs.get("defaultConfiguration"));
}
}
1.3.18.2 注册客户端配置
org.springframework.cloud.openfeign.FeignClientsRegistrar#registerClientConfiguration
java
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object className,
Object configuration) {
// 获取FeignClientSpecification类型的bean定义建造器
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
// 添加构造器参数值
builder.addConstructorArgValue(name);
// 添加构造器参数值
builder.addConstructorArgValue(className);
// 添加构造器参数值
builder.addConstructorArgValue(configuration);
// 注册bean定义,名称为"<name>.FeignClientSpecification"
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
builder.getBeanDefinition());
}
1.3.19 @EnableFeignClients
注解的处理
org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients
java
// 注册feign客户端
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();
// 从元数据中获取EnableFeignClients注解的属性值集合
Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
// 获取EnableFeignClients注解中clients的属性值
final Class<?>[] clients = attrs == null ? null : (Class<?>[]) attrs.get("clients");
// 如果clients为null或长度为0
if (clients == null || clients.length == 0) {
// 获取类路径组件扫描器
ClassPathScanningCandidateComponentProvider scanner = getScanner();
// 设置资源加载器
scanner.setResourceLoader(this.resourceLoader);
// 添加包含过滤器:扫描添加了@FeignClient注解的类
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
// 获取根路径
Set<String> basePackages = getBasePackages(metadata);
// 遍历根路径
for (String basePackage : basePackages) {
// 通过扫描器扫描指定根路径下的添加了@FeignClient注解的接口,并添加到candidateComponents集合中
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
} else {
// 如果设置了EnableFeignClients注解的clients属性值,则遍历属性值的元素
for (Class<?> clazz : clients) {
// 将添加了@FeignClient注解的Class对象封装后添加到candidateComponents集合中。
candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
}
}
// 遍历candidateComponents
for (BeanDefinition candidateComponent : candidateComponents) {
// 如果是基于注解的bean定义
if (candidateComponent instanceof AnnotatedBeanDefinition beanDefinition) {
// verify annotated class is an interface
// 获取bean定义的元数据
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
// 从元数据中获取FeignClient的属性值集合
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(FeignClient.class.getCanonicalName());
// 获取客户端name属性值
String name = getClientName(attributes);
// 获取类名
String className = annotationMetadata.getClassName();
// 注册客户端配置
registerClientConfiguration(registry, name, className, attributes.get("configuration"));
// 注册feign客户端
registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
1.3.20 注册feign客户端
org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClient
java
// 注册feign客户端
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata,
Map<String, Object> attributes) {
// 从注解元数据中获取类名
String className = annotationMetadata.getClassName();
// 如果禁用属性的懒解析,则立即注册feign客户端的bean定义
if (String.valueOf(false).equals(
environment.getProperty("spring.cloud.openfeign.lazy-attributes-resolution", String.valueOf(false)))) {
eagerlyRegisterFeignClientBeanDefinition(className, attributes, registry);
} else {
// 延迟注册feign客户端bean定义
lazilyRegisterFeignClientBeanDefinition(className, attributes, registry);
}
}
1.3.21 @FeignClient
注解的处理
org.springframework.cloud.openfeign.FeignClientsRegistrar#eagerlyRegisterFeignClientBeanDefinition
java
private void eagerlyRegisterFeignClientBeanDefinition(String className, Map<String, Object> attributes,
BeanDefinitionRegistry registry) {
validate(attributes);
// 获取FeignClientFactoryBean类型的bean定义
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
// 设置url属性值为从客户端配置属性中获取到的url的值,如果注解中没有配置,则设置为null值;
definition.addPropertyValue("url", getUrl(null, attributes));
// 设置path属性值为从客户端配置属性中获取到的path的值,如果注解中没有配置,则设置为null值;
definition.addPropertyValue("path", getPath(null, attributes));
// 获取注解name属性值
String name = getName(attributes);
// 给bean定义设置name属性的值
definition.addPropertyValue("name", name);
// 获取注解中contextId属性的值,如果没有配置则设置为null。
String contextId = getContextId(null, attributes);
// 给bean定义设置contextId属性值
definition.addPropertyValue("contextId", contextId);
// 给bean定义设置type属性值为className,即业务接口的全限定类名
definition.addPropertyValue("type", className);
// 给bean定义设置dismiss404的值,即是否对404错误进行解码,还是直接抛异常。默认直接抛异常。
definition.addPropertyValue("dismiss404", Boolean.parseBoolean(String.valueOf(attributes.get("dismiss404"))));
// 从注解配置中获取属性fallback属性值
Object fallback = attributes.get("fallback");
// 如果获取到了
if (fallback != null) {
// 给bean定义设置fallback属性的值,如果是Class,直接设置,否则将类名解析为Class对象,如果无法解析则赋值为null值。
definition.addPropertyValue("fallback",
(fallback instanceof Class ? fallback : ClassUtils.resolveClassName(fallback.toString(), null)));
}
// 获取FeignClient属性fallbackFactory属性值
Object fallbackFactory = attributes.get("fallbackFactory");
// 如果获取到了
if (fallbackFactory != null) {
// 给bean定义设置fallbackFactory属性值,如果使用的是Class进行设置的则直接设置,否则通过类名进行解析,解析为Class对象;
// 如果无法解析,则直接设置为null值。
definition.addPropertyValue("fallbackFactory", fallbackFactory instanceof Class ? fallbackFactory
: ClassUtils.resolveClassName(fallbackFactory.toString(), null));
}
// 设置fallbackFactory属性的值为从注解配置的属性中获取的值
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
// 设置自动装配模式为根据类型自动装配
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
// 设置bean定义的refreshableClient为获取到的值:是否启用了客户端的自动刷新
definition.addPropertyValue("refreshableClient", isClientRefreshEnabled());
// 获取属性中配置的Qualifiers的数组
String[] qualifiers = getQualifiers(attributes);
// 如果是空的
if (ObjectUtils.isEmpty(qualifiers)) {
// 则创建一个元素的数组:contextId+"FeignClient"
qualifiers = new String[] { contextId + "FeignClient" };
}
// This is done so that there's a way to retrieve qualifiers while generating AOT
// code
// 给bean定义设置qualifiers属性的值
definition.addPropertyValue("qualifiers", qualifiers);
// 获取bean定义
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
// bean定义设置属性:对象类型为className表示的类型,即业务接口全限定类名
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);
// has a default, won't be null
// 从@FeignClient注解中获取primary属性的值
boolean primary = (Boolean) attributes.get("primary");
// 设置给bean定义
beanDefinition.setPrimary(primary);
// 创建bean定义持有对象
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, qualifiers);
// 通过工具类注册bean定义
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
// 注册可刷新的bean定义
registerRefreshableBeanDefinition(registry, contextId, Request.Options.class, OptionsFactoryBean.class);
registerRefreshableBeanDefinition(registry, contextId, RefreshableUrl.class, RefreshableUrlFactoryBean.class);
}
返回指定bean的实例,可以是共享的也可以是独立的。
传递的参数:
name
:bean的名称;requiredType
:bean的类型;args
:当创建bean实例需要参数的时候,此处显式指定(仅用于创建bean实例而不是获取现有的bean实例);typeCheckOnly
:是否获取bean实例仅仅是为了检查bean的类型而不是真正使用;- 返回值:bean的实例。
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
java
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 对bean的名称进行转换,一般如果是工厂bean,则name以&开头,转换后得到去掉&符号的真正bean名称
String beanName = transformedBeanName(name);
Object beanInstance;
// 根据bean的名称获取单例bean实例
Object sharedInstance = getSingleton(beanName);
// 如果获取到了并且args为null值,则
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 获取bean的实例:
// 如果name以&开头,且sharedInstance是工厂bean,则直接返回,表示要获取的就是这个工厂bean,因为name以&开头了;
// 如果name不是以&开头的,且sharedInstance不是FactoryBean类型,则直接返回sharedInstance;
// 如果name不是以&开头的,表示不是要获取工厂bean,此时需要通过工厂bean创建实例并返回。
// 即如果要获取的就是工厂bean,且sharedInstance就是工厂bean,则直接返回,如果要获取的不是工厂bean则通过工厂bean创建实例并返回。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 如果sharedInstance不存在或者args不是null
// 如果当前正要创建的bean是多实例类型,则抛异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 获取父bean工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果父bean工厂存在,并且父bean工厂中不包含bean名称对应的定义,则
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 获取bean的原始bean名称
String nameToLookup = originalBeanName(name);
// 如果父bean工厂是抽象bean工厂类型
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
// 通过抽象bean工厂获取bean实例:bean名称、要求的类型、传递的构建参数以及是否仅仅是为了检查bean的类型
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
// 如果父bean工厂不是抽象bean工厂类型,则根据bean名称和构建参数从父工厂中获取bean实例并返回
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// 如果父bean工厂不是抽象bean工厂类型,并且没有显式的传递构建bean实例的参数,但是要求的类型不是null
// 则从父bean工厂中根据指定的名称和指定的类型获取bean实例,并返回。
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
// 否则直接通过名称从父bean工厂中获取bean实例并返回。
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果父bean工厂不存在,且不仅仅是为了检查bean的类型,则标记bean为已创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// 起步阶段
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
try {
// 如果要求的类型不是null值,则起步阶段标记bean的类型
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 通过bean名称获取根bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查合并后的bean定义
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 获取bean定义依赖
String[] dependsOn = mbd.getDependsOn();
// 如果依赖的bean名称非空,则遍历该bean依赖的其他bean名称集合
if (dependsOn != null) {
for (String dep : dependsOn) {
// 循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖的bean
registerDependentBean(dep, beanName);
try {
// 获取bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建bean实例。
if (mbd.isSingleton()) {
// 通过bean名称获取bean,如果没有获取到,则调用createBean方法创建bean
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean实例添加到缓存中,并返回
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 显式的从缓存中移除单例:它有可能是在创建过程中饿汉式的放到缓存中的,这样可用于解决循环依赖
// 同时移除临时引用到当前bean的其他bean。
destroySingleton(beanName);
throw ex;
}
});
//
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 通过bean定义获取范围
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
// 从scopes集合中获取范围名称对应的Scope实例
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 从范围内获取bean的实例,如果没有,就调用createBean方法创建,添加到scope中,并返回。
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
// 调用方法创建bean
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
// 根据指定的bean实例scopedInstance获取对应的对象,如果name以&开头,则直接返回本身,否则
// 如果不是工厂bean,则直接返回;
// 如果是工厂bean,但是name不是以&开头的,则使用工厂bean获取对象并返回。
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
} catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
} finally {
// 标记bean创建完成
beanCreation.end();
}
}
// 对bean进行适配返回。
return adaptBeanInstance(name, beanInstance, requiredType);
}
2. 启动流程
2.1 主入口类
org.example.openfeign.demo.BizApplication
java
@SpringBootApplication
@EnableFeignClients
public class BizApplication {
public static void main(String[] args) {
SpringApplication.run(BizApplication.class, args);
}
}
2.2 静态帮助方法
静态的帮助方法,可以用于从指定的资源使用默认的设置运行一个 SpringApplication。
传递的参数:
- primarySource:需要加载的首要资源;
- args:通常是通过 java 的 main 方法传递进来的参数;
返回值:
- 返回运行中的
ApplicationContext
。
org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String...)
java
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
2.3 静态帮助方法
用于从指定的资源使用默认的设置以及用户提供的参数运行一个 SpringApplication。
传递的参数:
- primarySource:首要的需要加载的资源;
- args:应用参数,一般是 java 的 main 方法传递进来的参数。
返回值:
- 返回运行中的
ApplicationContext
。
org.springframework.boot.SpringApplication#run(java.lang.Class<?>[], java.lang.String[])
java
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
2.4 运行 spring 应用
该方法中的几个关键点:
- 准备环境;
- 打印banner;
- 准备上下文;
- 刷新上下文;
- 执行上下文刷新后的处理;
- 调用Runners。
通过创建并刷新一个新的 ApplicationContext
实例,运行 spring 应用。
传递的参数:
- args:应用参数,一般是 java 的 main 方法传递进来的参数;
返回值:
- 返回运行中的
SpringApplication
对象。
org.springframework.boot.SpringApplication#run(java.lang.String...)
java
public ConfigurableApplicationContext run(String... args) {
// 记录开始的时间纳秒值
long startTime = System.nanoTime();
// 创建DefaultBootstrapContext
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 配置无头属性
configureHeadlessProperty();
// 根据参数获取 Spring 的应用运行监听器集合
SpringApplicationRunListeners listeners = getRunListeners(args);
// 调用监听器的 start 方法开始监听
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 创建DefaultApplicationArguments对象,封装传递的参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建应用上下文对象
context = createApplicationContext();
// 给上下文设置ApplicationStartup对象
context.setApplicationStartup(this.applicationStartup);
// 准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 【刷新上下文】
refreshContext(context);
// 执行上下文刷新后的处理
afterRefresh(context, applicationArguments);
// 计算启动花费的时间
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
// 如果需要记录启动信息日志,则创建StartupInfoLogger,记录启动事件日志
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 调用started方法通知监听器上下文已经启动
listeners.started(context, timeTakenToStartup);
// 调用Runners
callRunners(context, applicationArguments);
} catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 如果上下文正在运行中,则记录从启动到现在过去的时间,称为就绪时长。
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// 调用ready方法通知监听器上下文已经就绪。
listeners.ready(context, timeTakenToReady);
}
} catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回运行中的上下文
return context;
}
2.5 刷新上下文
- 如果需要注册系统关闭的钩子回调,则注册;
- 调用
refresh
方法刷新指定的上下文对象。
org.springframework.boot.SpringApplication#refreshContext
java
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);
}
// 【执行上下文的刷新】
refresh(context);
}
2.6 刷新上下文
刷新底层的 ApplicationContext
对象。
传递的参数:
- applicationContext:需要执行刷新操作的应用上下文。
org.springframework.boot.SpringApplication#refresh
java
protected void refresh(ConfigurableApplicationContext applicationContext) {
// 调用刷新的方法执行上下文的刷新。
applicationContext.refresh();
}
2.7 刷新
调用父类的方法执行刷新。
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh
java
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
// 【调用父类的刷新方法】
super.refresh();
} catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
2.8 抽象应用上下文的刷新
抽象应用上下文中的刷新上下文的方法。
org.springframework.context.support.AbstractApplicationContext#refresh
java
@Override
public void refresh() throws BeansException, IllegalStateException {
// 加同步锁,防止并发执行
synchronized (this.startupShutdownMonitor) {
//
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 为上下文的刷新操作进行准备。
prepareRefresh();
// 告诉子类刷新内部的bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备当前上下文中使用的bean工厂。
prepareBeanFactory(beanFactory);
try {
// 允许上下文子类中的bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 调用注册到当前上下文中的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);
// 注册用于拦截bean创建操作的bean处理器。
registerBeanPostProcessors(beanFactory);
// 标记bean后处理完成
beanPostProcess.end();
// 初始化当前上下文的message资源。
initMessageSource();
// 初始化当前上下文用到的事件多播器
initApplicationEventMulticaster();
// 为上下文特定的子类初始化其他的特定bean。
onRefresh();
// 检查监听器bean并执行监听器bean的注册。
registerListeners();
// 【实例化所有剩余的、非懒初始化的单例bean。】
finishBeanFactoryInitialization(beanFactory);
// 最后一步:广播上下文刷新完成事件。
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// 重置通用的introspection缓存,因为有些单例bean的元数据可能永远也不需要了。
resetCommonCaches();
// 标记上下文刷新操作完成
contextRefresh.end();
}
}
}
2.9 完成bean工厂的初始化
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
java
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 为当前上下文初始化转换服务。
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
// 设置转换服务
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)
);
}
// 如果bean工厂没有内嵌的值解析器,则设置内嵌的值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 及早初始化加载期间织入bean,允许及早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止使用临时的类加载器进行类型匹配。
beanFactory.setTempClassLoader(null);
// 对所有bean定义的元数据冻结,缓存,防止后续修改。
beanFactory.freezeConfiguration();
// 【实例化所有剩下的非懒加载的单例bean】
beanFactory.preInstantiateSingletons();
}
2.10 实例化单例bean之前的操作
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
java
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 创建List集合。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 遍历bean名称
for (String beanName : beanNames) {
// 获取根bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 如果bean定义表示的不是抽象的,并且是单例,并且不是懒加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果bean定义表示的是工厂bean,则
if (isFactoryBean(beanName)) {
// 获取工厂bean实例,名称为"&<beanName>"。
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 如果是SmartFactoryBean并且需要立即初始化
if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
// 则通过getBean的方式初始化
getBean(beanName);
}
} else {
// 如果不是工厂bean,【根据名称获取bean】的方式对bean进行初始化。
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 遍历所有bean名称
for (String beanName : beanNames) {
// 获取单例bean实例
Object singletonInstance = getSingleton(beanName);
// 如果是SmartInitializingSingleton类型
if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
// 实例化后操作
smartSingleton.afterSingletonsInstantiated();
// 表示初始化结束
smartInitialize.end();
}
}
}
2.11 通过名称获取bean
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
2.12 执行bean的获取
返回指定bean的实例,该实例可能是共享的也可能是独立的。
传递的参数:
name
:需要获取的bean实例的名称;requiredType
:目标bean实例的类型;args
:当需要创建新的bean实例的时候显式指定的参数(仅对新建bean实例起作用);typeCheckOnly
:是否获取bean实例仅仅为了进行类型检查;
返回值:
- 返回bean的实例。
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
java
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 对名称进行转换:如果name以&开头,表示的是工厂bean
String beanName = transformedBeanName(name);
Object beanInstance;
// 首先从注册的单例bean实例缓存中获取
Object sharedInstance = getSingleton(beanName);
// 如果获取到了,且没有指定构建参数
if (sharedInstance != null && args == null) {
// 记录日志
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 获取真正的bean实例,因为sharedInstance可能为工厂bean,真正获取的可能是工厂bean生产出来的实例。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// beanName如果对应的是正在创建的多实例bean实例,则抛异常,循环依赖了。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 从当前工厂的父工厂中查找bean定义。
// 获取当前工厂的父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果父工厂存在,且当前工厂中不存在beanName对应的bean定义
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 获取name对应的bean的原始名称
String nameToLookup = originalBeanName(name);
// 如果父工厂是ABF类型,则返回从父工厂查找的结果
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 如果指定了构建参数,则使用构建参数和bean实例名称从父工厂获取。
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// 如果要求的类型不是null值,则使用bean的名称和要求的类型从父工厂获取并返回
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
// 否则直接使用名称从父工厂查找并返回。
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不仅仅是为了检查类型,则标记beanName的bean实例已经创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
// 如果要求的类型不是空的
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 获取合并后的bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查bean定义
checkMergedBeanDefinition(mbd, beanName, args);
// 获取bean定义中记录的依赖bean,即其他bean依赖当前要创建的bean实例
// 获取bean定义中,当前bean实例依赖的其他bean实例
String[] dependsOn = mbd.getDependsOn();
// 如果依赖非空
if (dependsOn != null) {
// 遍历依赖当前bean实例的bean名称集合
for (String dep : dependsOn) {
// 如果被当前bean依赖的dep反过来又依赖当前bean,则抛异常:循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册dep被beanName依赖,在dep销毁之前,先销毁beanName对应的bean
registerDependentBean(dep, beanName);
try {
// 获取dep,如果抛异常,则表示当前bean依赖了不存在的bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建bean实例
// 如果bean定义表示的是单例bean,则
if (mbd.isSingleton()) {
// 【获取bean实例,如果没有就使用lambda指定的ObjectFactory创建】
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 获取bean实例,因为sharedInstance可能是工厂bean,而真正使用的可能是工厂bean生产出来的bean实例。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// 如果bean定义表示的是多实例bean,则直接创建
Object prototypeInstance = null;
try {
// 创建前操作
beforePrototypeCreation(beanName);
// 创建bean实例
prototypeInstance = createBean(beanName, mbd, args);
} finally {
// 最终执行创建后操作
afterPrototypeCreation(beanName);
}
// 获取bean实例,因为sharedInstance可能是工厂bean,而真正使用的可能是工厂bean生产出来的bean实例。
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 如果是其他范围的如request范围,session范围的,则获取范围名称
String scopeName = mbd.getScope();
// 如果是空的,则抛异常
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
// 获取名称对应的范围
Scope scope = this.scopes.get(scopeName);
// 如果范围不存在,则抛异常
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 从范围中获取指定名称的bean实例,如果不存在,就使用指定的lambda实现的ObjectFactory创建
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
} catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
} finally {
// 最终标记bean实例已经被创建
beanCreation.end();
}
}
// 适配后返回bean实例。
return adaptBeanInstance(name, beanInstance, requiredType);
}
2.13 获取单例bean实例
获取单例bean的使用指定名称注册的原始单例对象或者代理对象。
如果没有注册的对象,则创建并注册一个新的。
传递的参数:
beanName
:bean的名称;singletonFactory
:对单例bean对象进行延迟创建的ObjectFactory;
返回值:
- 返回注册的单例bean的实例。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 对单例bean实例集合加锁
synchronized (this.singletonObjects) {
// 从单例bean实例集合中获取bean实例
Object singletonObject = this.singletonObjects.get(beanName);
// 如果没有获取到
if (singletonObject == null) {
// 如果单例bean实例正在销毁,则抛异常
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 单例bean实例创建前操作
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
// 如果需要抑制异常,则创建被抑制的异常集合
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 【通过单例工厂获取单例对象】
singletonObject = singletonFactory.getObject();
// 设置标志:新的单例bean实例。
newSingleton = true;
} catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 单例bean实例创建后处理
afterSingletonCreation(beanName);
}
// 如果是新创建的单例bean实例,则添加到单例bean实例集合中
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
// 返回单例bean实例。
return singletonObject;
}
}
2.14 创建bean实例
AbstractAutowireCapableBeanFactory
类的核心方法:
- 创建bean的实例;
- 为bean实例执行属性注入;
- 应用后处理器等。
lambda表达式实现的ObjectFactory调用的创建单例bean实例的方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
java
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 解析bean的Class对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 如果Class不是null值,并且bean定义中包含的Class名称存在
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 新建根bean定义,封装原来的bean定义对象
mbdToUse = new RootBeanDefinition(mbd);
// 设置bean的Class对象
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 处理方法的重写
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 给后处理器一个机会返回代理而不是目标bean的实例。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果获取到代理则立即返回。
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 【执行bean的创建】
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(),
beanName,
"Unexpected exception during bean creation", ex
);
}
}
2.15 执行bean的创建
真正执行指定bean的创建。
调用该方法的时候,已经执行过创建前处理了,即已经检查过 postProcessBeforeInstantiation
回调了。
与默认的实例化方式不同的是,此处使用工厂方法或构造器自动注入的方式对bean执行实例化。
传递的参数:
beanName
:bean的名称;mbd
:运行时合并后的bean定义对象;args
:为使用构造器或调用工厂方法创建对象而显式指定的参数。
返回值:
- 返回bean的新实例。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 如果工厂bean没有创建过该bean实例,则需要创建,
// 创建好之后,将bean名称和bean实例键值对添加到factoryBeanInstanceCache
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 通过封装对象获取bean对象(要获取的)
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.markAsPostProcessed();
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 【执行属性的注入】
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
throw bce;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
2.16 为bean实例执行属性注入
使用bean定义中的属性值集合,为BeanWrapper中封装的bean实例执行属性注入。
传递的参数:
beanName
:需要注入属性值的bean实例的名称;mbd
:需要注入属性值的bean实例的bean定义;bw
:bean实例封装对象。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 如果封装对象为null值,但是bean定义中包含属性值集合,则抛异常:无法为null值执行属性注入
// 否则方法返回。
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(),
beanName,
"Cannot apply property values to null instance"
);
} else {
return;
}
}
// 如果封装对象中封装的类型是记录类型的,且bean定义中包含属性值集合,则抛异常:不能为记录注入属性值。
// 否则方法返回,因为记录是不可修改的。
if (bw.getWrappedClass().isRecord()) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(),
beanName,
"Cannot apply property values to a record"
);
} else {
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 如果bean定义表示的不是框架或第三方注入的,而是当前应用注入的,并且包含实例化后处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 遍历实例化后处理器
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 如果处理失败,方法返回
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
// 获取属性值集合
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 获取自动注入模式。
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 如果是按类型注入或按名称注入,则
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// 创建属性值集合的封装对象,封装属性值集合
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 如果是按名称注入,则执行按名称自动注入的操作。
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 如果是按类型注入,则执行按照类型自动注入的操作。
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
// 将pvs赋值封装对象
pvs = newPvs;
}
// 如果包含实例化后处理器
if (hasInstantiationAwareBeanPostProcessors()) {
// 如果pvs是null值,即没有属性值集合,则获取属性值集合
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 遍历实例化后处理器集合
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 【对属性值集合进行后处理】
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
// 如果要使用的pvs为null值,则方法返回,无需注入
if (pvsToUse == null) {
return;
}
// 否则设置为后处理之后的属性值集合。
pvs = pvsToUse;
}
}
// 是否需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
// 如果需要依赖检查
if (needsDepCheck) {
// 则获取需要执行依赖检查的属性描述符
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
// 执行依赖检查
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 如果属性值集合不是null,则执行注入。
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
2.17 属性的后处理
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
java
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 获取注入元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 为bean实例【执行注入】
metadata.inject(bean, beanName, pvs);
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
// 返回属性值集合
return pvs;
}
2.18 给bean实例注入值
org.springframework.beans.factory.annotation.InjectionMetadata#inject
java
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 获取注入元素集合
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
// 如果需要注入的元素集合不是空的
if (!elementsToIterate.isEmpty()) {
// 遍历需要注入的元素
for (InjectedElement element : elementsToIterate) {
// 【执行注入】
element.inject(target, beanName, pvs);
}
}
}
2.19 为字段注入值
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
java
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 获取当前注入元素对应的字段反射对象
Field field = (Field) this.member;
Object value;
// 如果当前注入元素包含缓存的值
if (this.cached) {
try {
// 解析缓存的值
value = resolveCachedArgument(beanName, this.cachedFieldValue);
} catch (BeansException ex) {
// Unexpected target bean mismatch for cached argument -> re-resolve
this.cached = false;
logger.debug("Failed to resolve cached argument", ex);
value = resolveFieldValue(field, bean, beanName);
}
} else {
// 如果当前注入元素不包含缓存的值,则【解析字段的值】
value = resolveFieldValue(field, bean, beanName);
}
// 如果解析的值不是null值,则
if (value != null) {
// 破坏封装:将字段设置为可访问
ReflectionUtils.makeAccessible(field);
// 给字段赋值
field.set(bean, value);
}
}
2.20 解析字段的值
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
java
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
// 创建依赖描述符
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
// 给描述符设置容器类
desc.setContainingClass(bean.getClass());
// 创建自动注入bean的名称集合
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
Assert.state(beanFactory != null, "No BeanFactory available");
// 通过bean工厂获取类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
// 【bean工厂解析依赖】
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 对当前对象加锁
synchronized (this) {
// 如果当前需要自动注入的元素没有值缓存,则
if (!this.cached) {
// 如果上述依赖解析的结果不是null值,或者当前依赖是必须的
if (value != null || this.required) {
// 缓存的字段值
Object cachedFieldValue = desc;
// 注册依赖的bean
registerDependentBeans(beanName, autowiredBeanNames);
// 如果解析的依赖不是null值,并且自动注入bean名称仅有一个
if (value != null && autowiredBeanNames.size() == 1) {
// 获取自动注入的bean名称
String autowiredBeanName = autowiredBeanNames.iterator().next();
// 如果工厂中包含该bean并且类型匹配
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 给字段缓存值赋值快捷依赖描述符对象
cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
}
}
// 依赖解析完毕,设置值
this.cachedFieldValue = cachedFieldValue;
// 设置标志字段:已经缓存结果了。
this.cached = true;
} else {
// 如果没有解析到依赖值,则设置为null值。
this.cachedFieldValue = null;
// cached flag remains false
}
}
}
// 返回字段的值。
return value;
}
2.21 解析依赖
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
java
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 给依赖描述符初始化参数名称发现
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 如果依赖类型是可选的
if (Optional.class == descriptor.getDependencyType()) {
// 创建可选依赖并返回
return createOptionalDependency(descriptor, requestingBeanName);
} else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
// 如果依赖的类型是ObjectFactory类型或者依赖的类型是ObjectProvider类型,则创建对象并返回
return new DependencyObjectProvider(descriptor, requestingBeanName);
} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
// 如果依赖的类型是javax的,则创建依赖提供者并返回
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
} else {
// 否则获取自动注入候选项解析器,获取依赖对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor,
requestingBeanName
);
// 如果没有获取到,则执行依赖的解析
if (result == null) {
// 【执行依赖的解析】
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
// 返回依赖解析的结果
return result;
}
}
2.22 执行依赖的解析
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
java
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 获取注入点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 解析快捷对象
Object shortcut = descriptor.resolveShortcut(this);
// 如果有则立即返回
if (shortcut != null) {
return shortcut;
}
// 通过描述符获取依赖的Class对象
Class<?> type = descriptor.getDependencyType();
// 使用自动注入候选项解析器获取依赖描述符对应的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
// 如果获取到值
if (value != null) {
// 如果是字符串
if (value instanceof String strValue) {
// 对字符串进行解析,获取解析后的字符串
String resolvedValue = resolveEmbeddedValue(strValue);
// 获取依赖的bean定义
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 计算bean定义中字符串的值
value = evaluateBeanDefinitionString(resolvedValue, bd);
}
// 获取类型转换器
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 对依赖进行转换之后返回
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
} catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 查找自动注入的候选项
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 如果是空的,则
if (matchingBeans.isEmpty()) {
// 如果依赖是必须的,则抛异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
// 否则返回null值
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果找到了依赖项,而且不止一个
if (matchingBeans.size() > 1) {
// 判断需要使用的自动注入候选项名称
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
// 如果没有获取到
if (autowiredBeanName == null) {
// 如果依赖是必须的,或者要求的不是多个候选项,则返回解析的依赖项不止一个
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
} else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
// 否则返回null值。
return null;
}
}
// 通过名称从匹配的bean实例中获取依赖
instanceCandidate = matchingBeans.get(autowiredBeanName);
} else {
// We have exactly one match.
// 如果仅获取到一个依赖对象
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
// 获取名称
autowiredBeanName = entry.getKey();
// 设置依赖对象
instanceCandidate = entry.getValue();
}
// 如果获取到了,则将依赖对象的名称添加到自动注入bean名称集合中。
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 如果依赖对象是Class类型,则通过描述符解析依赖候选项
if (instanceCandidate instanceof Class) {
// 【通过描述符解析依赖候选项】
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
// 获取结果
Object result = instanceCandidate;
// 如果结果的类型是NullBean,表示没有获取到依赖性
if (result instanceof NullBean) {
// 如果依赖项是必须的,则抛异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
// 否则将结果设置为null
result = null;
}
// 如果得到的结果不是要求的类型,则抛异常
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
// 返回依赖的结果对象
return result;
} finally {
// 恢复注入点
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
2.23 解析候选项
使用依赖的匹配算法从指定的bean工厂中得到的指定bean的候选项。
默认实现调用 BeanFactory.getBan(String)
。自定义的子类中可以提供额外的参数或其他定制操作。
传递的参数:
beanName
:bean的名称;requiredType
:要求的bean实例的类型;beanFactory
:关联的bean工厂。
返回值:
- 返回bean的实例,永远不是null值。
org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate
java
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
// 【通过名称从bean工厂获取bean实例】
return beanFactory.getBean(beanName);
}
2.24获取指定名称的bean实例
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
java
@Override
public Object getBean(String name) throws BeansException {
// 【执行获取bean实例的操作】
return doGetBean(name, null, null, false);
}
2.25 执行bean实例的获取
返回指定bean的实例,可以是共享的也可以是独立的。
传递的参数:
name
:bean的名称;requiredType
:要求的bean的类型;args
:显式指定的,当需要创建bean实例时用到的参数(仅用于当需要创建bean实例而不是获取已有的bean实例时);typeCheckOnly
:是否获取bean实例仅仅是为了类型检查;
返回值:
- 返回bean的实例,可能是已有的,也可能是新创建的。
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
java
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
// 【从bean工厂获取指定名称的bean实例,如果没有,则使用lambda实现的ObjectFactory创建bean实例】
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
2.26 创建bean实例
AbstractAutowireCapableBeanFactory
类的核心方法:
- 创建bean实例;
- 注入bean实例属性值;
- 应用后处理器等。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
java
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 【执行bean实例的创建】
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
2.27 执行bean实例的创建
真正创建指定的bean实例。
在调用该方法时,已经执行了创建前处理,如检查 postProcessBeforeInstantiation
回调等。
与默认bean实例化方式不同的是,此处使用工厂方法或构造器注入的方式实例化bean实例。
传递的参数:
beanName
:bean的名称;mbd
:运行时合并后的bean定义;args
:为通过构造器注入的方式或调用工厂方法方式创建bean实例而显式设置的参数。
返回值:
- 返回bean的新实例。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.markAsPostProcessed();
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 【执行bean实例属性的注入】
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
throw bce;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
2.28 执行属性值注入
使用bean定义中的属性值集合为bean实例属性注入值。
传递的参数:
beanName
:bean的名称;mbd
:bean的定义;bw
:封装了bean实例的对象。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
if (bw.getWrappedClass().isRecord()) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");
} else {
// Skip property population phase for records since they are immutable.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
if (hasInstantiationAwareBeanPostProcessors()) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 【属性值集合的后处理】
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
pvs = pvsToUse;
}
}
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
2.29 属性值集合的后处理
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
java
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 【依赖注入】
metadata.inject(bean, beanName, pvs);
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
2.30 为字段注入值
org.springframework.beans.factory.annotation.InjectionMetadata#inject
java
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍历需要注入值的字段集合
for (InjectedElement element : elementsToIterate) {
// 【属性注入】
element.inject(target, beanName, pvs);
}
}
}
2.31 为指定字段注入值
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
java
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolveCachedArgument(beanName, this.cachedFieldValue);
} catch (BeansException ex) {
// Unexpected target bean mismatch for cached argument -> re-resolve
this.cached = false;
logger.debug("Failed to resolve cached argument", ex);
value = resolveFieldValue(field, bean, beanName);
}
} else {
// 【解析字段的值】
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
2.32 解析字段的值
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
java
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
// 【通过bean工厂解析依赖】
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
Object cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (value != null && autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
else {
this.cachedFieldValue = null;
// cached flag remains false
}
}
}
return value;
}
}
2.33 解析依赖
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
java
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 【执行依赖的解析】
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
2.34 执行依赖的解析
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
java
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String strValue) {
String resolvedValue = resolveEmbeddedValue(strValue);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(resolvedValue, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 【查找自动注入的候选项】
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
2.35 查找自动装配的候选条目
查找与指定类型匹配的实例。
在自动装配指定 bean 的时候调用。
传递的参数:
- beanName:查找该名称的 bean 用于自动组装;
- requiredType:用于自动组装的 bean 的 Class 对象(可能是数组元素类型或集合元素类型);
- descriptor:需要解析的依赖描述符;
返回值:
- 返回符合要求类型的候选条目名称和实例的 Map 集合,不是 null 值。
如果发生错误,则抛异常:BeansException
。
org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates
java
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
// 【添加候选项条目】
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
2.36 添加候选项条目
org.springframework.beans.factory.support.DefaultListableBeanFactory#addCandidateEntry
java
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDescriptor) {
// 【通过描述符解析候选项】
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
if (!(beanInstance instanceof NullBean)) {
candidates.put(candidateName, beanInstance);
}
}
else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor streamDescriptor &&
streamDescriptor.isOrdered())) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(candidateName, getType(candidateName));
}
}
2.37 使用bean工厂解析依赖候选项
org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate
java
/**
* Resolve the specified bean name, as a candidate result of the matching
* algorithm for this dependency, to a bean instance from the given factory.
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
* Subclasses may provide additional arguments or other customizations.
* @param beanName the bean name, as a candidate result for this dependency
* @param requiredType the expected type of the bean (as an assertion)
* @param beanFactory the associated factory
* @return the bean instance (never {@code null})
* @throws BeansException if the bean could not be obtained
* @since 4.3.2
* @see BeanFactory#getBean(String)
*/
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
// 【从bean工厂获取指定名称的bean实例】
return beanFactory.getBean(beanName);
}
2.38 从bean工厂获取指定名称的bean实例
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
java
@Override
public Object getBean(String name) throws BeansException {
// 【执行bean实例的获取】
return doGetBean(name, null, null, false);
}
2.39 执行获取 bean 的操作
返回指定 bean 的一个实例,该实例可以是共享的也可以是独立的。
传递的参数:
- name:要查找的 bean 的名称;
- requiredType:要查找的 bean 必须匹配的类型;
- args:当创建 bean 实例的时候需要的显式指定的参数(仅在需要创建 bean 而不是获取现有 bean 的时候有效);
- typeCheckOnly:获取的 bean 是否仅用于类型检查而不是真正使用;
返回值:
- 返回指定 bean 的实例。
如果无法创建 bean 的实例,则抛异常:BeansException
。
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
java
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 对名称进行转换:name中可能以&开头,如果以&开头,表示获取的是工厂bean。
String beanName = transformedBeanName(name);
Object beanInstance;
// 首先从缓存中根据原始名称进行获取
Object sharedInstance = getSingleton(beanName);
// 如果获取到了,且显式指定的构建bean实例的参数为null,则
if (sharedInstance != null && args == null) {
// 记录日志 ......
// 【获取bean的实例】
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 从bean工厂中获取bean实例,如果没有,则调用createBean方法创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 调用方法,创建bean。注意:这里的lambda是作为ObjectFactory的实现对象来使用的。
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 显式从单例bean实例缓存中移除:
// - 因为它可能是在早期作为处理循环依赖而引入的。
// - 同时移除任何对该临时bean实例应用的其他bean。
destroySingleton(beanName);
throw ex;
}
});
// 获取bean实例
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// 如果bean定义表示的是多实例bean,则创建新的实例
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
// 获取bean实例
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 从scope中获取指定名称的bean实例,如果没有,则使用lambda表示的ObjectFactory创建
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
// 调用createBean方法创建实例
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
// 获取bean实例
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
} catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
} finally {
beanCreation.end();
}
}
// 对bean实例进行适配后返回。
return adaptBeanInstance(name, beanInstance, requiredType);
}
2.40 为bean实例获取对象
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getObjectForBeanInstance
java
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 获取当前已经创建好的bean
String currentlyCreatedBean = this.currentlyCreatedBean.get();
// 如果不是null,则执行注册
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
// 【调用父类的方法获取bean的实例】
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
2.41 获取bean的实例
为指定的bean获取对象,要么通过bean实例本身,要么通过工厂bean的方法创建。
传递的参数:
beanInstance
:共享的bean实例;name
:包含了用于区分工厂bean前缀的bean名称(如果以&开头,表示是工厂bean);beanName
:完整的bean名称;mbd
:运行时合并后的bean定义。
返回值:
- 返回bean实例。
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
java
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
} else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 【从工厂bean获取bean的实例】
object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);
}
// 返回bean的实例
return object;
}
2.42 从工厂bean获取bean的实例
从给定的工厂bean获取bean的实例。
传递的参数:
factory
:工厂bean实例;shouldPostProcess
:是否需要对bean实例执行后处理;
返回值:
- 返回从工厂bean获取的bean的实例。
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
java
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 如果工厂是单例,并且单例对象集合中包含该单例
if (factory.isSingleton() && containsSingleton(beanName)) {
// 加锁
synchronized (getSingletonMutex()) {
// 从工厂bean创建的单例集合中获取该工厂bean创建的beanName实例
Object object = this.factoryBeanObjectCache.get(beanName);
// 如果没有获取到
if (object == null) {
// 【执行从工厂bean获取实例的方法获取bean实例】
object = doGetObjectFromFactoryBean(factory, beanName);
// 判断是否有其他操作将该bean实例放到缓存中了,比如循环引用触发的自定义的getBean方法就有这种可能。
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
// 如果有了,则直接获取出来使用
if (alreadyThere != null) {
object = alreadyThere;
} else {
// 如果没有,则如果需要执行后处理
if (shouldPostProcess) {
// 如果当前创建的beanName表示的实例是单例,则首先返回未经后处理的临时对象,而不存储。
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
beforeSingletonCreation(beanName);
try {
// 对从工厂bean获取的bean实例执行后处理
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
} finally {
afterSingletonCreation(beanName);
}
}
// 将beanName和bean实例键值对添加到工厂bean创建的对象缓存集合中。
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
// 直接返回该bean实例。
return object;
}
} else {
// 真正从工厂bean获取bean实例
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 如果需要执行后处理,则执行后处理
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
// 返回从工厂bean获取的bean实例
return object;
}
}
2.43 从工厂bean获取bean实例
传递的参数:
factory
:工厂bean实例;beanName
:bean的名称;
返回值:
- 返回从工厂bean获取到的bean实例。
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
java
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
// 【执行从工厂bean获取bean实例的方法】
// 调用FeignClientFactoryBean的getObject方法获取业务接口的基于feign客户端的代理对象。
object = factory.getObject();
} catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName,
"FactoryBean which is currently in creation returned null from getObject"
);
}
object = new NullBean();
}
return object;
}
2.44 工厂bean的getObject方法
调用getTarget方法获取并返回。
org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject
java
@Override
public Object getObject() {
// 业务接口如OrderService的基于feign客户端的代理实现。JDK动态代理来完成的。
return getTarget();
}
2.45 获取基于Feign的业务接口代理对象
获取目标对象的步骤:
-
获取 feign 客户端工厂;
-
通过 feign 客户端工厂创建
Feign.Builder
对象; -
如果 url 为空,并且 contextId 对应的配置中也不包含 url 配置,则
-
如果url不是空,且不是以http开头的,则在url之前插入http://;
-
得到标准的url;
-
从feign客户端工厂中获取Client类型的bean;
-
如果客户端不是null:
-
应用FeignBuilderCustomizer到feign的建造器;
-
从spring应用上下文获取Targeter类型的对象;
-
调用target方法创建服务接口的代理实现对象并返回。
org.springframework.cloud.openfeign.FeignClientFactoryBean#getTarget
java
@SuppressWarnings("unchecked")
<T> T getTarget() {
// 获取 feign 客户端工厂。
// 如果beanFactory不是null,就使用beanFactory获取FeignClientFactory对象,否则使用applicationContext获取FeignClientFactory对象。
FeignClientFactory feignClientFactory = beanFactory != null ? beanFactory.getBean(FeignClientFactory.class)
: applicationContext.getBean(FeignClientFactory.class);
// 通过FeignClientFactory创建Feign.Builder对象。
Feign.Builder builder = feign(feignClientFactory);
// 如果url为空,并且contextId对应的配置中也不包含url配置
if (!StringUtils.hasText(url) && !isUrlAvailableInConfig(contextId)) {
if (LOG.isInfoEnabled()) {
LOG.info("For '" + name + "' URL not provided. Will try picking an instance via load-balancing.");
}
// 如果名称不包含http前缀,就添加http前缀
if (!name.startsWith("http")) {
url = "http://" + name;
} else {
// 如果名称包含http前缀,则直接赋值
url = name;
}
// 在url上追加处理后的path字符串
url += cleanPath();
// param1:Feign客户端建造器;
// param2:feign客户端工程;
// param3:硬编码的目标对象,包含了类型、名称和url。
return (T) loadBalance(builder, feignClientFactory, new HardCodedTarget<>(type, name, url));
}
// 如果url不是空,且不是以http开头的,则在url之前插入http://
if (StringUtils.hasText(url) && !url.startsWith("http")) {
url = "http://" + url;
}
// 得到标准的url
String url = this.url + cleanPath();
// 从feign客户端工厂中获取Client类型的bean
Client client = getOptional(feignClientFactory, Client.class);
// 如果客户端不是null
if (client != null) {
// 如果客户端是FeignBlockingLoadBalancerClient类型
if (client instanceof FeignBlockingLoadBalancerClient) {
// 由于有url,因此不会执行负载均衡。
// 但是spring cloud loadbalancer在类路径上,因此需要拆包。
client = ((FeignBlockingLoadBalancerClient) client).getDelegate();
}
// 如果客户端是RetryableFeignBlockingLoadBalancerClient类型
if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
// 此时不执行负载均衡,因为有url。
// 但是spring cloud loadbalancer在类路径上,因此进行拆包。
client = ((RetryableFeignBlockingLoadBalancerClient) client).getDelegate();
}
// 将客户端设置给建造器,建造者基于该客户端创建服务接口的代理实现对象
builder.client(client);
}
// 应用FeignBuilderCustomizer到feign的建造器。
applyBuildCustomizers(feignClientFactory, builder);
// 从spring应用上下文获取Targeter类型的对象
Targeter targeter = get(feignClientFactory, Targeter.class);
// 调用target方法创建服务接口的代理实现对象并返回。
return targeter.target(this, builder, feignClientFactory, resolveTarget(feignClientFactory, contextId, url));
}
注意:此处使用的Target是HardCodedTarget,传递的参数是服务接口类型,客户端名称和类级别注解中指定的url。
2.45.1 cleanPath整理URL
- 如果path变量为null,则返回空字符串;
- 否则去掉首尾空格;
- 如果path此时还不为空字符串,则如果path不是以
/
开头,则在头部插入/
,如果path
是以/
结尾的,则去掉尾部的/
; - 返回整理后的path的字符串。
org.springframework.cloud.openfeign.FeignClientFactoryBean#cleanPath
java
private String cleanPath() {
// 如果path为null,则返回空字符串
if (path == null) {
return "";
}
// 否则path字符串去掉首尾空格
String path = this.path.trim();
// 如果此时path不为空字符串
if (StringUtils.hasLength(path)) {
// 如果path不是以/开头的,则添加/前缀
if (!path.startsWith("/")) {
path = "/" + path;
}
// 如果path以/结尾,则去掉尾部的/
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
}
// 返回path字符串
return path;
}
3. Feign客户端实现及负载均衡和重试
3.1 Retryer
Retryer
接口是重试器的顶级接口。
每次调用 Client.execute(Request, feign.Request.Options)
方法就克隆该接口实现类的对象一次。
- 这里的克隆,指的是使用当前对象的各个属性重新创建一个重试器对象。
实现类中可以保留重试的状态,以决定当前应该执行重试还是放弃重试。
对于默认实现:
- 在重试之前基础等待时长为100ms,即如果调用失败,则第一次重试的时候,等待100ms,后续重试之前等待的时长每次都是前一次的1.5倍;
- 最大重试之前等待的时长为1s;
- 最大重试次数5次。
对于没有任何操作的重试器接口实现:
- 不执行重试,直接抛异常,表示放弃重试;
- 同时,克隆的时候就是返回当前的对象,不创建新对象。因为没有任何操作的重试器实现,什么也不做,什么状态也不记录,幂等。
feign.Retryer
java
public interface Retryer extends Cloneable {
/**
* 如果允许重试,方法返回,可能在方法返回之前等待一定的时长。如果放弃重试,直接抛异常即可。
*/
void continueOrPropagate(RetryableException e);
// 克隆重试器对象的方法,每次调用feign客户端的execute方法就克隆重试器一次。
Retryer clone();
// 默认实现
class Default implements Retryer {
// 最大重试次数
private final int maxAttempts;
// 在重试之前等待的时间,该时间是基础时间
private final long period;
// 在重试之前等待时间的最大值。
private final long maxPeriod;
// 记录重试的次数
int attempt;
// 记录为了重试到当前时刻共等待了多长时间
long sleptForMillis;
/**
* 默认构造器创建Retryer实例:默认重试之前等待100ms,最大重试等待时长是1s,最多重试5次。
*/
public Default() {
// 调用重载的构造器,传递参数:
// 1. 重试时间间隔:100ms
// 2. 最大重试时间间隔:1s
// 3. 最大重试次数:5
this(100, SECONDS.toMillis(1), 5);
}
/**
* 构造器
* @param period 重试时间间隔
* @param maxPeriod 最大重试时间间隔
* @param maxAttempts 最大重试次数
*/
public Default(long period, long maxPeriod, int maxAttempts) {
this.period = period;
this.maxPeriod = maxPeriod;
this.maxAttempts = maxAttempts;
// attempt初始值为1。实际上只重试了4次就抛异常了,共调用5次,第一次是正常调用。
this.attempt = 1;
}
// ......
/**
* 继续重试还是将错误传播出去:
* 1. 如果重试次数小于最大重试次数,则重试,而不传播异常;
* 2. 如果重试次数大于等于最大重试次数,则将错误传播出去,即抛异常。
* @param e
*/
public void continueOrPropagate(RetryableException e) {
// 如果重试次数大于等于最大重试次数,则抛异常,表示放弃重试。
if (attempt++ >= maxAttempts) {
throw e;
}
long interval;
// 如果异常中包含retryAfter,则
if (e.retryAfter() != null) {
// 获取retryAfter中下次重试的时间,减去当前时间,计算还应该等待多长时间才可以重试。
interval = e.retryAfter().getTime() - currentTimeMillis();
// 如果计算出来的时间间隔大于最大的时间间隔,则赋值为最大的时间间隔。
if (interval > maxPeriod) {
interval = maxPeriod;
}
// 如果计算出来的值小于0,表示已经过了应该重试的时刻,方法立即返回,表示立即重试。
if (interval < 0) {
return;
}
} else {
// 如果异常中不包含指定的重试时刻,则获取本次重试之前应该等待的时长:时长1.5倍递增。
interval = nextMaxInterval();
}
try {
// 线程等待
Thread.sleep(interval);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
throw e;
}
// 总等待时长累加
sleptForMillis += interval;
}
/**
* 计算下次重试的时间间隔。
* 每重试一次,时间变为原来的1.5倍(1.5是退避因子),直到达到最大等待时间。
*
* @return 返回下一次重试前等待的时长,单位毫秒。
*/
long nextMaxInterval() {
// 1.5的指数增长
long interval = (long) (period * Math.pow(1.5, attempt - 1));
// 如果计算出的值大于最大等待时间,则返回最大等待时间,否则返回计算出的值。
return interval > maxPeriod ? maxPeriod : interval;
}
@Override
public Retryer clone() {
// 根据当前对象中的基础等待时间,最大等待时间以及最大重试次数创建新的重试器对象并返回
return new Default(period, maxPeriod, maxAttempts);
}
}
/**
* 从不重试的Retryer实现,直接将异常传递出去。
*/
Retryer NEVER_RETRY = new Retryer() {
/**
* 直接将异常抛出去,实现异常的传播,放弃重试。
* @param e
*/
@Override
public void continueOrPropagate(RetryableException e) {
throw e;
}
/**
* 反正该实现什么也不做,实际上是幂等的,直接返回当前实例即可。
* @return
*/
@Override
public Retryer clone() {
return this;
}
};
}
3.2 工厂bean生产bean实例
org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject
java
/**
* 实现的FactoryBean接口中的方法,获取FeignClient的bean:这里返回的是目标对象Target。
* 这是该类的主要方法,获取对象。
*
* @return 返回FeignClient对象
*/
@Override
public Object getObject() {
return getTarget();
}
3.3 获取代理对象
该方法的泛型指的是业务接口的类型,即基于feign客户端的业务接口代理对象的类型;
方法返回的是基于指定的数据和上下文信息创建的基于feign客户端的业务接口代理对象。
org.springframework.cloud.openfeign.FeignClientFactoryBean#getTarget
java
/**
* 获取对象。
*
* @param <T> 基于feign客户端代理对象的类型。
* @return 使用指定的数据和上下文信息创建的基于Feign客户端的业务接口代理对象。
*/
@SuppressWarnings("unchecked")
<T> T getTarget() {
// 获取 feign 客户端工厂。
// 如果beanFactory不是null,就使用beanFactory获取FeignClientFactory对象,
// 否则使用applicationContext获取FeignClientFactory对象。
FeignClientFactory feignClientFactory = beanFactory != null ? beanFactory.getBean(FeignClientFactory.class) : applicationContext.getBean(FeignClientFactory.class);
// 通过FeignClientFactory创建Feign.Builder对象。
Feign.Builder builder = feign(feignClientFactory);
// 如果url为空,并且contextId对应的配置中也不包含url配置
// 注意:这里的url实际上就是在@FeignClient中配置的url属性,该属性的值必须是绝对url或者是可解析的主机名称。
// 即:如果设置了url,则不再进行负载均衡。
if (!StringUtils.hasText(url) && !isUrlAvailableInConfig(contextId)) {
if (LOG.isInfoEnabled()) {
LOG.info("For '" + name + "' URL not provided. Will try picking an instance via load-balancing.");
}
// 如果名称不包含http前缀,就添加http前缀
if (!name.startsWith("http")) {
url = "http://" + name;
} else {
// 如果名称包含http前缀,则直接赋值
url = name;
}
// 在url上追加处理后的path字符串
url += cleanPath();
// param1:Feign客户端建造器;
// param2:feign客户端工程;
// param3:硬编码的目标对象,包含了类型、名称和url。
return (T) loadBalance(builder, feignClientFactory, new HardCodedTarget<>(type, name, url));
}
// 如果url不是空,且不是以http开头的,则在url之前插入http://
if (StringUtils.hasText(url) && !url.startsWith("http")) {
url = "http://" + url;
}
// 得到标准的url
String url = this.url + cleanPath();
// 从feign客户端工厂中获取Client类型的bean
Client client = getOptional(feignClientFactory, Client.class);
// 如果客户端不是null
if (client != null) {
// 如果客户端是FeignBlockingLoadBalancerClient类型
if (client instanceof FeignBlockingLoadBalancerClient) {
// 由于有url,因此不会执行负载均衡。
// 但是spring cloud loadbalancer在类路径上,因此需要拆包。
client = ((FeignBlockingLoadBalancerClient) client).getDelegate();
}
// 如果客户端是RetryableFeignBlockingLoadBalancerClient类型
if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
// 此时不执行负载均衡,因为有url。
// 但是spring cloud loadbalancer在类路径上,因此进行拆包。
client = ((RetryableFeignBlockingLoadBalancerClient) client).getDelegate();
}
// 将客户端设置给建造器,建造者基于该客户端创建服务接口的代理实现对象
builder.client(client);
}
// 应用FeignBuilderCustomizer到feign的建造器。
applyBuildCustomizers(feignClientFactory, builder);
// 从spring应用上下文获取Targeter类型的对象
Targeter targeter = get(feignClientFactory, Targeter.class);
// 调用target方法创建服务接口的代理实现对象并返回。
return targeter.target(this, builder, feignClientFactory, resolveTarget(feignClientFactory, contextId, url));
}
上述代码中,需要注意的是:
-
如果在
@FeignClient
注解中设置了url,则不再进行负载均衡。因为该url必须是绝对的url,或者是可解析的主机名称。即:通过url就指定了该服务调用的时候就调用url指定的服务实例,不调用其他服务实例。
3.3.1 没有设置URL需要负载均衡
如果没有设置URL,则:
- 拼接根URL,即接口级别的URL(对不同的方法拼接方法上配置的不同的path);
- 调用
loadBalance
方法执行负载均衡返回结果代理对象。
3.3.1.1 loadBalance方法
org.springframework.cloud.openfeign.FeignClientFactoryBean#loadBalance
java
protected <T> T loadBalance(Feign.Builder builder, FeignClientFactory context, HardCodedTarget<T> target) {
// 从上下文获取客户端
Client client = getOptional(context, Client.class);
// 如果客户端存在
if (client != null) {
// 给建造器设置客户端
builder.client(client);
// 应用建造的自定义
applyBuildCustomizers(context, builder);
// 从上下文获取Targeter
Targeter targeter = get(context, Targeter.class);
// 调用target方法生成业务接口基于feign客户端的代理对象
return targeter.target(this, builder, context, target);
}
throw new IllegalStateException(
"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?");
}
3.3.1.2 FeignBlockingLoadBalancerClient
此时,使用的是 FeignBlockingLoadBalancerClient
作为 Client。
在默认feign负载均衡器配置中,创建了 FeignBlockingLoadBalancerClient
对象,并添加到上下文中。
构造器参数:
- feign客户端的默认实现;
- 负载均衡器客户端;
- 负载均衡器客户端工厂;
- 转换器集合。
org.springframework.cloud.openfeign.loadbalancer.DefaultFeignLoadBalancerConfiguration#feignClient
java
@Bean
@ConditionalOnMissingBean
@Conditional(OnRetryNotEnabledCondition.class)
public Client feignClient(LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
return new FeignBlockingLoadBalancerClient(new Client.Default(null, null), loadBalancerClient,
loadBalancerClientFactory, transformers);
}
3.3.1.3 服务调用的时候的invoke方法-重试策略
feign.SynchronousMethodHandler#invoke
java
@Override
public Object invoke(Object[] argv) throws Throwable {
// 通过方法调用参数构建请求模板
RequestTemplate template = buildTemplateFromArgs.create(argv);
// 通过方法调用参数获取网络请求选项
Options options = findOptions(argv);
// 克隆重试器,实际上就是使用重试器的参数重新创建一个重试器对象
Retryer retryer = this.retryer.clone();
// while-true典型的重试逻辑
while (true) {
try {
// 发送请求解码响应并返回
return executeAndDecode(template, options);
} catch (RetryableException e) {
try {
// 如果发生异常,调用重试器方法,如果该方法不抛异常,则执行重试
// 如果抛异常,则不再重试。
// 默认该方法在返回之前等待的基础时长是100ms,后续的等待时长是前一次的1.5倍,最长等待1s;
// 默认最大重试次数为5次。
retryer.continueOrPropagate(e);
} catch (RetryableException th) {
Throwable cause = th.getCause();
if (propagationPolicy == UNWRAP && cause != null) {
throw cause;
} else {
throw th;
}
}
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
}
3.3.1.4 请求并解码响应
feign.SynchronousMethodHandler#executeAndDecode
java
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
// 通过模板创建请求对象
Request request = targetRequest(template);
if (logLevel != Logger.Level.NONE) {
logger.logRequest(metadata.configKey(), logLevel, request);
}
Response response;
long start = System.nanoTime();
try {
// 此时的Client是FeignBlockingLoadBalancerClient
response = client.execute(request, options);
// ensure the request is set. TODO: remove in Feign 12
response = response.toBuilder()
.request(request)
.requestTemplate(template)
.build();
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
}
throw errorExecuting(request, e);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
return responseHandler.handleResponse(
metadata.configKey(),
response,
metadata.returnType(),
elapsedTime
);
}
3.3.1.5 执行请求返回响应
org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient#execute
java
@Override
public Response execute(Request request, Request.Options options) throws IOException {
// 根据请求的url创建URI对象
final URI originalUri = URI.create(request.url());
// 获取URI对象的host值作为serviceId
String serviceId = originalUri.getHost();
Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
String hint = getHint(serviceId);
// 创建负载均衡请求对象
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
new RequestDataContext(buildRequestData(request), hint));
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(
loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
// 负载均衡选择服务实例
ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);
org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(
instance);
// 如果没有找到服务实例,则返回服务不可用错误
if (instance == null) {
String message = "Load balancer does not contain an instance for the service " + serviceId;
if (LOG.isWarnEnabled()) {
LOG.warn(message);
}
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.DISCARD, lbRequest, lbResponse)));
return Response.builder().request(request).status(HttpStatus.SERVICE_UNAVAILABLE.value())
.body(message, StandardCharsets.UTF_8).build();
}
// 否则使用挑选出来的服务实例对原始的URI进行重构,即将host替换为挑选出来的服务实例的host
String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();
// 使用重构后的URL字符串、挑选出来的服务实例以请求对象创建请求对象
Request newRequest = buildRequest(request, reconstructedUrl, instance);
// 调用带负载均衡生命周期处理的方法执行远程调用并解析结果返回
return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,
supportedLifecycleProcessors);
}
3.3.1.6 负载均衡选择服务实例
org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient#choose(java.lang.String, org.springframework.cloud.client.loadbalancer.Request)
java
@Override
public <T> ServiceInstance choose(String serviceId, Request<T> request) {
// 通过serviceId获取响应式的负载均衡器
ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);
// 如果没有获取到,则返回null值
if (loadBalancer == null) {
return null;
}
// 响应式调用方法,挑选服务实例。
Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose(request)).block();
// 如果负载均衡失败,则返回null值
if (loadBalancerResponse == null) {
return null;
}
// 获取服务实例返回
return loadBalancerResponse.getServer();
}
3.3.1.7 选择服务实例
org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer#choose
java
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
// 获取服务实例列表提供者
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
.getIfAvailable(NoopServiceInstanceListSupplier::new);
// 返回Mono响应式流
// 从服务实例列表提供者获取对应于request的服务实例列表
return supplier.get(request).next()
// 调用processInstanceResponse方法挑选服务实例
.map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));
}
3.3.1.8 获取可用的服务实例
org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier#get
java
default Flux<List<ServiceInstance>> get(Request request) {
return get();
}
3.3.1.9 获取可用的服务实例
org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier#get
java
@Override
public Flux<List<ServiceInstance>> get() {
// 返回服务发现客户端服务实例列表提供者持有的服务实例列表构成的响应式流
return serviceInstances;
}
3.3.1.10 执行负载均衡挑选服务实例
org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer#processInstanceResponse
java
private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,
List<ServiceInstance> serviceInstances) {
// 利用负载均衡算法挑选服务实例
Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances);
if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
// 记录用过的服务实例
((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
}
// 返回负载均衡响应对象
return serviceInstanceResponse;
}
3.3.1.11 默认使用轮询的方式执行负载均衡
org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer#getInstanceResponse
java
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
// 如果传进来的服务实例列表是空的,则返回空的响应
if (instances.isEmpty()) {
if (log.isWarnEnabled()) {
log.warn("No servers available for service: " + serviceId);
}
return new EmptyResponse();
}
// Do not move position when there is only 1 instance, especially some suppliers
// have already filtered instances
// 如果传递进来的服务实例列表只有一个元素,则返回包含该元素的响应结果。
if (instances.size() == 1) {
return new DefaultResponse(instances.get(0));
}
// 否则当前位置值+1之后,对Integer最大值取位与操作,(速度快)得到下一个服务实例的伪索引,该值可以是正数也可以是负数,无所谓。
int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
// 使用伪索引对实例个数取模,得到真索引(必定在0和实例个数之间的正数),使用真索引获取服务实例
ServiceInstance instance = instances.get(pos % instances.size());
// 新建响应对象封装挑选出来的实例返回。
return new DefaultResponse(instance);
}
3.3.2 设置了url不需要负载均衡
上述代码中从feign客户端工厂获取Targeter类型的bean,在Feign自动配置类中:
在FeignCircuitBreakerDisabledConditionis时候,向上下文中添加Targeter的bean,当上下文中没有Targeter类型的bean的时候才创建。
使用的是 DefaultTargeter
。
org.springframework.cloud.openfeign.FeignAutoConfiguration.DefaultFeignTargeterConfiguration#feignTargeter
java
@Configuration(proxyBeanMethods = false)
@Conditional(FeignCircuitBreakerDisabledConditions.class)
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
// 直接使用DefaultTargeter实例
return new DefaultTargeter();
}
}
DefaultTargeter的target方法:
- 直接调用feign建造器的target方法创建业务接口代理对象。
org.springframework.cloud.openfeign.DefaultTargeter#target
java
@Override
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context,
Target.HardCodedTarget<T> target) {
return feign.target(target);
}
Feign.Builder中的方法实现:
- 调用build方法创建Feign实例,调用Feign实例的newInstance方法创建业务接口的代理对象。
feign.Feign.Builder#target(feign.Target)
java
public <T> T target(Target<T> target) {
return build().newInstance(target);
}
而上述的build方法:
- 创建的是ReflectiveFeign对象。
feign.Feign.Builder#build
java
/**
* 建造feign对象
* @return
*/
public Feign build() {
// 调用父类的enrich方法。
super.enrich();
// 创建同步方法处理器工厂,传递的参数:
// 1. 客户端对象;
// 2. 重试器;
// 3. 请求拦截器集合;
// 4. 响应拦截器集合;
// 5. 日志记录器;
// 6. 日志记录级别;
// 7. 是否忽略 404的解码;
// 8. 是否在解码后关闭响应的底层输入流;
// 9. 异常传播策略;
// 10. 请求选项集合;
// 11. 解码器;
// 12. 错误解码器
MethodHandler.Factory<Object> synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors,
responseInterceptor, logger, logLevel, dismiss404, closeAfterDecode,
propagationPolicy, options, decoder, errorDecoder);
// 创建工具对象,根据名称解析处理器;
// 传递的参数:
// 1. 契约对象;
// 2. 编码器;
// 3. 查询映射编码器;
// 4. 同步的方法处理器工厂。
ParseHandlersByName<Object> handlersByName =
new ParseHandlersByName<>(contract, encoder, queryMapEncoder,
synchronousMethodHandlerFactory);
// 创建基于反射的 feign 实例,封装了根据名称解析处理器的工具对象,调用处理器工厂,以及默认的上下文 supplier 对象。
return new ReflectiveFeign<>(handlersByName, invocationHandlerFactory, () -> null);
}
ReflectiveFeign的newInstance方法
feign.ReflectiveFeign#newInstance(feign.Target)
java
/**
* 反射的方式生成代理对象,绑定到target。由于使用了反射,应缓存尽缓存。
*/
public <T> T newInstance(Target<T> target) {
// 上面的方法调用该方法的时候,传递的supplier是() -> null,因此第二个参数是null值。
return newInstance(target, defaultContextSupplier.newContext());
}
重载的newInstance方法:
创建业务接口基于feign客户端的代理对象。
比如,对于 org.example.openfeign.demo.service.remote.OrderService
接口,生成该接口的代理对象。
在实现类中使用代理的方式,将方法委托给feign发起远程调用。
注意:
由于是通过反射的方式生成的代理对象,绑定到target。因此,应缓存仅缓存。
传递的参数:
target
:封装了业务接口、对应的根URL,以及bean名称的封装对象;requestContext
:请求上下文,默认情况下传递的是null值。- T:业务接口代理对象的类型;
返回值:
- 返回JDK动态代理生成的业务接口的代理对象。
方法执行流程:
-
验证target:
-
如果target的泛型不是接口,则抛异常:必须是接口;
-
遍历接口中的方法,如果返回值类型不是future类型,则继续,即可以是同步返回值,没问题;
-
如果返回值类型是future类型,则如果返回值类型不是CompletableFuture类型,则抛异常:
方法返回值不是CompletableFuture
类型; -
如果返回值类型是CompletableFuture类型,但不是参数化类型,则抛异常:
方法返回值不是参数化类型
,即没有指定结果类型泛型; -
如果返回值类型是CompletableFuture类型,且是参数化类型,但却是通配符类型,则抛异常:
通配符类型不支持作为CompletableFuture的类型参数
。
-
-
通过target和请求上下文(默认为null)获取业务接口中方法对象到方法Handler对象映射的Map集合;
- 即:每个方法都有一个MethodHandler对象;
-
通过工厂创建InvocationHandler对象(典型的JDK动态代理);
-
通过JDK动态代理,生成业务接口的基于feign客户端的代理对象;
-
遍历所有的方法Handler,如果是DefaultMethodHandler,则绑定到代理对象;
-
返回创建的代理对象。
feign.ReflectiveFeign#newInstance(feign.Target, C)
java
@SuppressWarnings("unchecked")
public <T> T newInstance(Target<T> target, C requestContext) {
TargetSpecificationVerifier.verify(target);
// 方法和方法handler的map集合
Map<Method, MethodHandler> methodToHandler = targetToHandlersByName.apply(target, requestContext);
// 创建InvocationHandler对象
InvocationHandler handler = factory.create(target, methodToHandler);
// 反射的方式生成代理对象
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class<?>[]{target.type()}, handler);
// 如果MethodHandler是DefaultMethodHandler,则绑定到proxy
for (MethodHandler methodHandler : methodToHandler.values()) {
if (methodHandler instanceof DefaultMethodHandler) {
((DefaultMethodHandler) methodHandler).bindTo(proxy);
}
}
// 返回创建的代理对象。
return proxy;
}
上述代码中,使用factory创建InvocationHandler对象,这里的factory默认使用的是父类中的invocationHandlerFactory:
feign.BaseBuilder#invocationHandlerFactory
java
/**
* 调用处理器工厂,使用默认的实现
*/
protected InvocationHandlerFactory invocationHandlerFactory = new InvocationHandlerFactory.Default();
则创建InvocationHandler的过程:
- 创建ReflectiveFeign.FeignInvocationHandler对象。
- 即每次需要生产InvocationHandler对象,就调用该方法,创建FeignInvocationHandler对象。
feign.InvocationHandlerFactory.Default#create
java
/**
* 根据 target 和方法到方法处理器的映射集合,创建 InvocationHandler 对象
* @param target target,用于创建 Request 的对象;
* @param dispatch 用于对方法调用进行分发的 map 集合。
* @return 返回 InvocationHandler 对象,此处是 ReflectiveFeign.FeignInvocationHandler 对象
*/
@Override
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
}
3.3.2.1 服务调用的invoke方法
既然是一个InvocationHandler,则必有invoke方法:
该方法处理具体的方法调用。
执行逻辑:
- 处理
equals
、hashCode
、toString
方法的调用; - 通过当前调用的方法的
Method
对象,到dispatch
集合中取出对应的MethodHandler
对象,调用MethodHandler
的invoke
方法处理方法调用。
feign.ReflectiveFeign.FeignInvocationHandler#invoke
java
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("equals".equals(method.getName())) {
try {
Object otherHandler =
args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return equals(otherHandler);
} catch (IllegalArgumentException e) {
return false;
}
} else if ("hashCode".equals(method.getName())) {
return hashCode();
} else if ("toString".equals(method.getName())) {
return toString();
}
// 通过dispatch获取方法的handler,并调用handler的invoke方法获取结果返回。
return dispatch.get(method).invoke(args);
}
3.3.2.2 SynchronousMethodHandler中的invoke方法-重试策略
MethodHandler默认使用的是SynchronousMethodHandler:
feign.SynchronousMethodHandler#invoke
java
@Override
public Object invoke(Object[] argv) throws Throwable {
// 通过方法调用时传递的参数,构建网络请求模板
RequestTemplate template = buildTemplateFromArgs.create(argv);
// 通过方法调用时传递的参数,获取网络请求选项
Options options = findOptions(argv);
// 克隆(实际上是新建)重试器
Retryer retryer = this.retryer.clone();
// while-true典型的重试方式
while (true) {
try {
// 执行远程调用并解码响应后返回结果
return executeAndDecode(template, options);
} catch (RetryableException e) {
try {
// 如果发生了异常,则调用重试器的方法,如果该方法不抛异常,表示需要重试。
// 如果需要重试,则方法会执行线程等待,等待结束后,方法返回,while-true循环重试。
// 默认基础等待时间为100ms,后续重试等待时长是前一次的1.5倍,最大重试等待时长默认为1s。
// 默认最多重试5次。
retryer.continueOrPropagate(e);
} catch (RetryableException th) {
Throwable cause = th.getCause();
if (propagationPolicy == UNWRAP && cause != null) {
throw cause;
} else {
throw th;
}
}
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
}
3.3.2.3 远程调用解析响应的实现
执行流程:
- 通过请求模板,创建请求对象;
- 通过客户端发起网络请求获取响应;
- 通过响应Handler对响应进行解码后返回。
最关键的是调用客户端的execute方法。
feign.SynchronousMethodHandler#executeAndDecode
java
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
// 传递模板,创建请求对象
Request request = targetRequest(template);
if (logLevel != Logger.Level.NONE) {
logger.logRequest(metadata.configKey(), logLevel, request);
}
Response response;
long start = System.nanoTime();
try {
// 客户端执行请求获取响应
response = client.execute(request, options);
// TODO:在Feign12中移除
// 确保在响应对象中封装了请求对象,实际是再操作一次。
response = response.toBuilder()
.request(request)
.requestTemplate(template)
.build();
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
}
throw errorExecuting(request, e);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
// 交给响应处理器,对结果进行处理,返回处理后的结果
// 参数1:配置key
// 参数2:响应对象;
// 参数3:返回类型;
// 参数4:远程调用使用的时间
return responseHandler.handleResponse(
metadata.configKey(), response, metadata.returnType(), elapsedTime);
}
上述代码中关键步骤是使用client发起网络请求。
client默认是:
feign.Feign.Builder#client
java
/**
* 客户端:创建默认的实现类对象,传递 SSL 上下文工厂为 null,主机名校验器为 null。
*/
private Client client = new Client.Default(null, null);
创建feign.Feign.Builder对象,默认使用的是Client.Default对象。
builder的build方法创建了ReflectiveFeign对象,在创建过程中,首先创建了 SynchronousMethodHandler.Factory
,构造器传值 client
默认就是 Client.Default
对象。
而 SynchronousMethodHandler.Factory
的create方法用于创建 SynchronousMethodHandler
,因此在 SynchronousMethodHandler
的 executeAndDecode
方法中使用的就是 Client.Default
对象的execute方法:
3.3.2.4 执行网络请求并获取响应
执行流程:
- 转换并发送请求;
- 对响应进行处理,返回处理的结果。
feign.Client.Default#execute
java
@Override
public Response execute(Request request, Options options) throws IOException {
// 负责发送请求
HttpURLConnection connection = convertAndSend(request, options);
// 对响应进行处理
return convertResponse(connection, request);
}
3.3.2.5 转换并发送请求
执行步骤:
- 创建URL对象;
- 调用url的openConnection方法获取HttpURLConnection对象;
- 如果是https请求,则类型强转,并给连接设置SSL上下文工厂和主机名校验器;
- 设置请求方式、请求报文头、请求报文体、请求超时时间、读取超时时间、是否跟随3XX重定向,以及是否禁用请求缓冲区等;
- 处理编码;
- 对请求报文头字段进行处理;
- 获取输出流,并根据编码情况对输出流进行装饰;
- 使用输出流发送请求报文体;
- 关闭输出流;
- 返回连接对象。
feign.Client.Default#convertAndSend
java
HttpURLConnection convertAndSend(Request request, Options options) throws IOException {
// 创建URL对象
final URL url = new URL(request.url());
// 调用url的openConnection()方法获取HttpURLConnection对象
final HttpURLConnection connection = this.getConnection(url);
// 如果是https请求
if (connection instanceof HttpsURLConnection) {
// 类型强转
HttpsURLConnection sslCon = (HttpsURLConnection) connection;
// 如果SSL上下文工厂存在,则给连接设置SSL上下文工厂
if (sslContextFactory != null) {
sslCon.setSSLSocketFactory(sslContextFactory);
}
// 如果主机名校验器存在,则给连接设置主机名校验器
if (hostnameVerifier != null) {
sslCon.setHostnameVerifier(hostnameVerifier);
}
}
// 设置连接超时时间
connection.setConnectTimeout(options.connectTimeoutMillis());
// 设置读超时时间
connection.setReadTimeout(options.readTimeoutMillis());
// 设置是否允许用户与交互
connection.setAllowUserInteraction(false);
// 设置是否跟随3XX重定向
connection.setInstanceFollowRedirects(options.isFollowRedirects());
// 设置HTTP请求方法:GET、POST等
connection.setRequestMethod(request.httpMethod().name());
// 获取请求头中的Content-Encoding字段值
Collection<String> contentEncodingValues = request.headers().get(CONTENT_ENCODING);
// 判断是否是gzip编码
boolean gzipEncodedRequest = this.isGzip(contentEncodingValues);
// 判断是否是deflate编码
boolean deflateEncodedRequest = this.isDeflate(contentEncodingValues);
boolean hasAcceptHeader = false;
Integer contentLength = null;
// 遍历请求头所有字段名称
for (String field : request.headers().keySet()) {
// 如果字段名称是Accept,则将标志hasAcceptHeader设置为true
if (field.equalsIgnoreCase("Accept")) {
hasAcceptHeader = true;
}
// 获取请求字段的值
for (String value : request.headers().get(field)) {
// 如果字段名称是Content-Length,则将内容长度值赋给contentLength
if (field.equals(CONTENT_LENGTH)) {
// 如果请求体没有被gzip或deflate编码,则将内容长度值赋给contentLength
if (!gzipEncodedRequest && !deflateEncodedRequest) {
contentLength = Integer.valueOf(value);
connection.addRequestProperty(field, value);
}
} else {
// 否则直接将字段名称和字段的值作为请求属性赋值给connection
connection.addRequestProperty(field, value);
}
}
}
// 如果请求报文头没有Accept字段,则将Accept作为字段名称,"*/*"作为字段值,添加为connection的请求属性。
// 因为有些服务器无法处理默认的accept字符串。
if (!hasAcceptHeader) {
connection.addRequestProperty("Accept", "*/*");
}
boolean hasEmptyBody = false;
// 获取请求报文体字节数组
byte[] body = request.body();
// 如果数组为null,并且请求方法要求有请求体
if (body == null && request.httpMethod().isWithBody()) {
// 则创建空的字节数组
body = new byte[0];
// 将空请求报文体标志设置为true
hasEmptyBody = true;
}
// 如果请求报文体字节数组不是null
if (body != null) {
/*
* 如果是空的报文体,则忽略disableRequestBuffering标记,确保内部重试逻辑对此类请求也适用。
*/
// 如果禁用请求缓冲标志为true,并且不是空的请求报文体
if (disableRequestBuffering && !hasEmptyBody) {
// 如果内容长度不是null,则设置固定长度流模式
if (contentLength != null) {
connection.setFixedLengthStreamingMode(contentLength);
} else {
// 否则设置分块流模式,块大小为8k字节
connection.setChunkedStreamingMode(8196);
}
}
// 设置是否允许输出流
connection.setDoOutput(true);
// 获取输出流
OutputStream out = connection.getOutputStream();
// 如果是gzip编码
if (gzipEncodedRequest) {
// 对输出流使用gzip装饰
out = new GZIPOutputStream(out);
} else if (deflateEncodedRequest) {
// 如果是deflate编码,则对输出流使用deflate装饰
out = new DeflaterOutputStream(out);
}
try {
// 写出请求报文体
out.write(body);
} finally {
try {
// 最终关闭输出流
out.close();
} catch (IOException suppressed) { // NOPMD
}
}
}
// 返回处理之后的连接对象
return connection;
}
3.3.2.6 转换响应
获取结果并对结果进行处理。
处理步骤:
-
获取响应状态码:如HTTP / 1.0 200 OK,抽取出200;
-
获取响应消息,如HTTP / 1.0 200 OK,抽取出OK;
-
创建TreeMap用户封装响应报文头;
-
遍历响应报文头字段集合;
将响应报文头的字段名称作为key,值作为value添加到headers MAP集合中;
-
获取内容长度,如果长度为-1,则设置length为null;
-
如果响应码大于等于400,则获取响应报文头中的错误流;
-
如果没有错误,则根据编码和压缩信息,对从连接获取的输入流进行装饰等;
-
使用Response的建造器创建响应对象:
- 状态:200、400、500等;
- 信息:OK、Bad Request等;
- 响应报文头字段信息集合:Content-Type、Content-Length等;
- 请求对象;
- 响应报文体;
- 创建响应对象并返回。
feign.Client.Default#convertResponse
java
Response convertResponse(HttpURLConnection connection, Request request) throws IOException {
// 获取响应码,如HTTP/ 1.0 200 OK,抽取出200
int status = connection.getResponseCode();
// 获取响应消息,如HTTP/ 1.0 200 OK,抽取出其中的OK
String reason = connection.getResponseMessage();
if (status < 0) {
throw new IOException(format("Invalid status(%s) executing %s %s", status,
connection.getRequestMethod(), connection.getURL()));
}
// 创建TreeMap用于封装响应报文头
Map<String, Collection<String>> headers = new TreeMap<>(CASE_INSENSITIVE_ORDER);
// 对响应报文头字段进行遍历
for (Map.Entry<String, List<String>> field : connection.getHeaderFields().entrySet()) {
// response message
// 将响应报文头的字段名称作为key,值作为value添加到headers MAP集合中
if (field.getKey() != null) {
headers.put(field.getKey(), field.getValue());
}
}
// 获取内容长度
Integer length = connection.getContentLength();
// 如果是-1,则设置为null
if (length == -1) {
length = null;
}
InputStream stream;
// 如果响应码大于等于400,则获取响应报文头中的错误流
if (status >= 400) {
stream = connection.getErrorStream();
} else {
// 获取输入流,并使用对应的编码进行装饰
if (this.isGzip(headers.get(CONTENT_ENCODING))) {
stream = new GZIPInputStream(connection.getInputStream());
} else if (this.isDeflate(headers.get(CONTENT_ENCODING))) {
stream = new InflaterInputStream(connection.getInputStream());
} else {
// 如果没有编码,则直接返回获取的输入流
stream = connection.getInputStream();
}
}
// 使用Response的建造器创建响应对象
return Response.builder()
.status(status) // 状态:200、400、500等
.reason(reason) // 信息:OK、Bad Request等
.headers(headers) // 响应报文头字段信息集合:Content-Type、Content-Length等
.request(request) // 请求对象
.body(stream, length) // 响应报文体
.build(); // 创建响应对象并返回。
}