0%

分支流程 SpringApplication#prepareEnvironment

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// org.springframework.boot.SpringApplication#prepareEnvironment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    listeners.environmentPrepared(bootstrapContext, environment);
    DefaultPropertiesPropertySource.moveToEnd(environment);
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
            "Environment prefix cannot be set via properties.");
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
        environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

流程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// org.springframework.boot.SpringApplication#prepareEnvironment
// 构建 Environment
--> 创建`Environment`。
    --|> `org.springframework.boot.SpringApplication#getOrCreateEnvironment`
    --> WebApplicationType.SERVLET 类型调用`org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory#createEnvironment`。
        --> new ApplicationServletEnvironment()
        --|> org.springframework.boot.web.servlet.context.ApplicationServletEnvironment
---> 配置`Environment`。
    --|> `org.springframework.boot.SpringApplication#configureEnvironment`
    --> 创建`ApplicationConversionService`并填充到`environment`,即填充到`AbstractEnvironment#propertyResolver`。
        --|> org.springframework.boot.convert.ApplicationConversionService#ApplicationConversionService()
        --|> 默认`ApplicationConversionService`内包含`org.springframework.core.convert.converter.Converter``org.springframework.format.Formatter`,不包含`java.beans.PropertyEditor`,
        --> 配置转换器org.springframework.boot.convert.ApplicationConversionService#configure
            --> org.springframework.core.convert.support.DefaultConversionService#addDefaultConverters
                --|> 注册`*Converter`,包括
                    --> ScalarConverters
                    --> CollectionConverters
                    --> xxxConverters
            --> org.springframework.format.support.DefaultFormattingConversionService#addDefaultFormatters
                --|> 注册`*Formatter`。
            --> org.springframework.boot.convert.ApplicationConversionService#addApplicationFormatters
                --|> 注册 Spring Boot 相关的`*Formatter`。
            --> org.springframework.boot.convert.ApplicationConversionService#addApplicationConverters
                --|> 注册 Spring Boot 相关的`*Converter`。
            --> 后续逻辑会将其填充到 BeanFactory 
                --> org.springframework.boot.SpringApplication#postProcessApplicationContext
                    --> context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
    --> 配置`PropertySource`并填充到`environment`。
    --> 配置`Profile`并填充到`environment`。空逻辑跳过
--> 封装和添加`ConfigurationPropertySourcesPropertySource`。
    --|> `org.springframework.boot.context.properties.source.ConfigurationPropertySources#attach`
    --|> 将当前的`MutablePropertySources`封装为`SpringConfigurationPropertySources`,并再次封装为支持参数解析的`ConfigurationPropertySourcesPropertySource`,名称为`ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties"`,添加到`MutablePropertySources`中并且优先级最高
--> 发布`ApplicationEnvironmentPreparedEvent`。
    --|> `listeners.environmentPrepared(bootstrapContext, environment);`
    --> 生效的`listener`如下
    --|> EnvironmentPostProcessorApplicationListener
        --> 加载`org.springframework.boot.env.EnvironmentPostProcessor`
            --|> `org.springframework.boot.env.EnvironmentPostProcessorApplicationListener#getEnvironmentPostProcessors`。
            --|> `EnvironmentPostProcessorApplicationListener`使用无参构建方法创建
                --> 构造方法为`this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());`。
            --> 创建`EnvironmentPostProcessorsFactory`,`EnvironmentPostProcessorsFactory::fromSpringFactories`。
                --> 加载`EnvironmentPostProcessor`,默认有7个
                --|> `SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));`
                --> 创建`ReflectionEnvironmentPostProcessorsFactory`。
                --|> 作用是反射创建实例配置参数`DeferredLogFactory`、`ConfigurableBootstrapContext`
            --> 使用该`EnvironmentPostProcessorsFactory`(`ReflectionEnvironmentPostProcessorsFactory`)实例化`EnvironmentPostProcessor`。
                --|> 均使用`DeferredLog`作为`logger`。
        --> 调用接口方法`org.springframework.boot.env.EnvironmentPostProcessor#postProcessEnvironment`。
            --|> 上一步骤默认创建7个分别如下
            --|> RandomValuePropertySourceEnvironmentPostProcessor
                --|> 添加`RandomValuePropertySource``MutablePropertySources`,相当于也同步添加到了`ConfigurationPropertySourcesPropertySource`
            --|> SystemEnvironmentPropertySourceEnvironmentPostProcessor
                --|> An EnvironmentPostProcessor that replaces the systemEnvironment SystemEnvironmentPropertySource with an SystemEnvironmentPropertySourceEnvironmentPostProcessor.OriginAwareSystemEnvironmentPropertySource that can track the SystemEnvironmentOrigin for every system environment property.
                --|> 用1个`SystemEnvironmentPropertySourceEnvironmentPostProcessor.OriginAwareSystemEnvironmentPropertySource`替换`SystemEnvironmentPropertySource`。
            --|> SpringApplicationJsonEnvironmentPostProcessor
                --|> An EnvironmentPostProcessor that parses JSON from spring. application. json or equivalently SPRING_APPLICATION_JSON and adds it as a map property source to the Environment. The new properties are added with higher priority than the system properties.
                --|> 一个 EnvironmentPostProcessor它解析来自 spring.application.json 或等效的 SPRING_APPLICATION_JSON  JSON并将其作为映射属性源添加到环境中新添加的属性优先级高于系统属性
            --|> CloudFoundryVcapEnvironmentPostProcessor
            --|> ConfigDataEnvironmentPostProcessor
                --|> EnvironmentPostProcessor that loads and applies ConfigData to Spring's Environment.
                --|> 用于加载并应用 ConfigData  Spring  Environment 
            --|> DebugAgentEnvironmentPostProcessor
            --|> IntegrationPropertiesEnvironmentPostProcessor
    --|> AnsiOutputApplicationListener配置日志 ANSI 特性
    --|> LoggingApplicationListener
        --|> An ApplicationListener that configures the LoggingSystem. If the environment contains a logging. config property it will be used to bootstrap the logging system, otherwise a default configuration is used.
        --|> 用于配置日志系统如果环境中包含 logging.config 属性它将被用来初始化日志系统否则将使用默认配置
            --> org.springframework.boot.context.logging.LoggingApplicationListener#initialize
    --|> BackgroundPreinitializer
        --|> ApplicationListener to trigger early initialization in a background thread of time-consuming tasks.
        --> 不了解为何将其作为耗时操作org.springframework.boot.autoconfigure.BackgroundPreinitializer#performPreinitialization
    --|> DelegatingApplicationListener默认未起作用
    --|> FileEncodingApplicationListener默认未起作用
--> org.springframework.boot.SpringApplication#bindToSpringApplication
    --|> `spring.main`相关的配置绑定到`SpringApplication`

ConfigDataEnvironmentPostProcessor 详解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor#postProcessEnvironment(org.springframework.core.env.ConfigurableEnvironment, org.springframework.boot.SpringApplication)
--> org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor#postProcessEnvironment(org.springframework.core.env.ConfigurableEnvironment, org.springframework.core.io.ResourceLoader, java.util.Collection<java.lang.String>)
    --> new DefaultResourceLoader();
        --|> org.springframework.core.io.DefaultResourceLoader#DefaultResourceLoader()
    --> org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor#getConfigDataEnvironment
        --> new ConfigDataEnvironment(
            --|> org.springframework.boot.context.config.ConfigDataEnvironment#ConfigDataEnvironment
            --|> 默认搜索路径`locations``"optional:classpath:/;optional:classpath:/config/"``"optional:file:./;optional:file:./config/;optional:file:./config/*/"`。通过使用
            --> 构建`Binder`,`org.springframework.boot.context.properties.bind.Binder#get(org.springframework.core.env.Environment)`。
                --> `ConfigurationPropertySources.get(environment);`
                --> new PropertySourcesPlaceholdersResolver(environment)
                    --> new PropertyPlaceholderHelper
                --> `new Binder(sources, placeholdersResolver, null, null, defaultBindHandler);`,`defaultBindHandler`同样为 null
                    --|> org.springframework.boot.context.properties.bind.Binder#Binder(java.lang.Iterable<org.springframework.boot.context.properties.source.ConfigurationPropertySource>, org.springframework.boot.context.properties.bind.PlaceholdersResolver, org.springframework.core.convert.ConversionService, java.util.function.Consumer<org.springframework.beans.PropertyEditorRegistry>, org.springframework.boot.context.properties.bind.BindHandler)
                        --> org.springframework.boot.context.properties.bind.Binder#Binder(java.lang.Iterable<org.springframework.boot.context.properties.source.ConfigurationPropertySource>, org.springframework.boot.context.properties.bind.PlaceholdersResolver, org.springframework.core.convert.ConversionService, java.util.function.Consumer<org.springframework.beans.PropertyEditorRegistry>, org.springframework.boot.context.properties.bind.BindHandler, org.springframework.boot.context.properties.bind.BindConstructorProvider)
                            --> org.springframework.boot.context.properties.bind.Binder#Binder(java.lang.Iterable<org.springframework.boot.context.properties.source.ConfigurationPropertySource>, org.springframework.boot.context.properties.bind.PlaceholdersResolver, org.springframework.core.convert.ConversionService, java.util.function.Consumer<org.springframework.beans.PropertyEditorRegistry>, org.springframework.boot.context.properties.bind.BindHandler, org.springframework.boot.context.properties.bind.BindConstructorProvider)
                                --> org.springframework.boot.context.properties.bind.BindConverter#get
                                    --> 当前`conversionServices``propertyEditorInitializer`均为空因此`BindConverter`获取默认转换器包含`Converter``PropertyEditor`两大类
                                        --|> org.springframework.boot.context.properties.bind.BindConverter#getSharedInstance
                                        --> new BindConverter(null, null);
                                            --|> org.springframework.boot.context.properties.bind.BindConverter#BindConverter
                                            --> new TypeConverterConversionService(propertyEditorInitializer)
                                                --> new TypeConverterConverter(initializer)
                                                    --|> org.springframework.boot.context.properties.bind.BindConverter.TypeConverterConverter#TypeConverterConverter
                                                    --> createTypeConverter()
                                                        --|> org.springframework.boot.context.properties.bind.BindConverter.TypeConverterConverter#createTypeConverter
                                                        --> new SimpleTypeConverter()
                                                            --> new TypeConverterDelegate(this);
                                                                --|> org.springframework.beans.TypeConverterDelegate#TypeConverterDelegate(org.springframework.beans.PropertyEditorRegistrySupport)
                                                            --> registerDefaultEditors()
                                            --> ApplicationConversionService.getSharedInstance()
                                                --|> org.springframework.boot.convert.ApplicationConversionService#getSharedInstance
                                                --> new ApplicationConversionService(null, true);
                                                    --|> org.springframework.boot.convert.ApplicationConversionService#ApplicationConversionService(org.springframework.util.StringValueResolver, boolean)
                                                    --> org.springframework.boot.convert.ApplicationConversionService#configure
                                                        --|> 批量注册`Converter``Formatter`。
                                
                                --> 使用`BindConstructorProvider.DEFAULT`。
                                --> 两种 Binder `ValueObjectBinder``JavaBeanBinder`。
            --> logger `DeferredLogs`。
            --> createConfigDataLocationResolvers(
                --|> org.springframework.boot.context.config.ConfigDataEnvironment#createConfigDataLocationResolvers
                    --> new ConfigDataLocationResolvers(
                        --|> org.springframework.boot.context.config.ConfigDataLocationResolvers
                            --> 获取`ConfigDataLocationResolver.class`实现类,`SpringFactoriesLoader.loadFactoryNames(ConfigDataLocationResolver.class`。
                            --> org.springframework.boot.context.config.ConfigDataLocationResolvers#ConfigDataLocationResolvers(org.springframework.boot.logging.DeferredLogFactory, org.springframework.boot.ConfigurableBootstrapContext, org.springframework.boot.context.properties.bind.Binder, org.springframework.core.io.ResourceLoader, java.util.List<java.lang.String>)
                                --> 填充`DeferredLogFactory.class`等信息
                                --> 实例化`ConfigDataLocationResolver.class`实现类默认2个有序排列为`ConfigTreeConfigDataLocationResolver``StandardConfigDataLocationResolver`。
                                    --> ConfigTreeConfigDataLocationResolver
                                    --> StandardConfigDataLocationResolver
                                        --> SpringFactoriesLoader.loadFactories(PropertySourceLoader.class
                                            --|> 获取并实例化`PropertySourceLoader.class`实现类
                                            --|> 默认支持如下2种
                                            --|> PropertiesPropertySourceLoader 支持查找`properties``xml`。
                                            --|> YamlPropertySourceLoader 支持查找`yml``yaml` 
            --> 入参`this.environmentUpdateListener`为空使用默认空实现`ConfigDataEnvironmentUpdateListener.NONE`,无逻辑
                --|> 该类监听器响应2种事件分别为
                --|> `onPropertySourceAdded`,属性源添加事件
                --|> `onSetProfiles`,profile 设置事件
            --> new ConfigDataLoaders(
                --> SpringFactoriesLoader.loadFactoryNames(ConfigDataLoader.class, classLoader))
                    --|> 获取并实例化`ConfigDataLoader.class`实现类
                        --|> 默认支持如下2种
                        --|> ConfigTreeConfigDataLoader
                        --|> StandardConfigDataLoader
            --> `createContributors(binder);`
                --|> org.springframework.boot.context.config.ConfigDataEnvironment#createContributors(org.springframework.boot.context.properties.bind.Binder)
                --> for-each 遍历 propertySources封装为`ConfigDataEnvironmentContributor`
                    --|> 此处忽略名称为`defaultProperties` propertySource后续封装应当是为了适配优先级
                    --> ConfigDataEnvironmentContributor.ofExisting(propertySource)
                        --|> 类型为`org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind#EXISTING`。
                --> 添加若干个初始`ImportContributor`。
                    --|> 类型为`org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind#INITIAL_IMPORT`。
                    --|> 对应配置参数如下
                    --> spring.config.import
                    --> spring.config.additional-location
                    --> spring.config.location
                        --|> 默认搜索路径如下
                        --> "optional:classpath:/;optional:classpath:/config/"
                        --> "optional:file:./;optional:file:./config/;optional:file:./config/*/"
                --> 如果存在则将名称为`defaultProperties` propertySource 封装为`ConfigDataEnvironmentContributor`。
        --> org.springframework.boot.context.config.ConfigDataEnvironment#processAndApply
            --> `new ConfigDataImporter(`
                --|> Imports ConfigData by resolving and loading locations. resources are tracked to ensure that they are not imported multiple times.
                --|> 通过解析和加载位置来导入配置数据跟踪资源以确保它们不会被多次导入
                --> 使用`DeferredLogs`,`ConfigDataLocationResolvers`,`ConfigDataLoaders`
            --> `bootstrapContext`中注册`org.springframework.boot.context.properties.bind.Binder`为原型 bean
            --> `processInitial(`
            --> 创建`ConfigDataActivationContext`。`createActivationContext(`
            --> 加载与 profile 无关的配置文件。`processWithoutProfiles(`
            --> 再次创建`ConfigDataActivationContext`。`withProfiles(`
            --> 加载制定 profile 的配置文件。`processWithProfiles(`
            --> 应用到 environment 。`applyToEnvironment(`

默认将使用StandardConfigDataLoaderPropertiesPropertySourceLoader加载配置文件。

前言

SpringBoot 的入口方法如下,入口方法有2个特征

  1. 声明注解@SpringBootApplication
  2. main方法中调用方法org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String...)
1
2
3
4
5
6
7
8
// 如下是简洁版本。
// 通常用户会根据业务需求额外声明一些注解,例如`@PropertySource`,`@ComponentScan`等,参见其它篇章。
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

SpringApplication 构造方法

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    // primarySources 默认为声明注解`@SpringBootApplication`(通常也是调用`SpringApplication#run`的`main`方法)的所在类。
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 从 classpath 探测 web application type,通常为`org.springframework.boot.WebApplicationType#SERVLET`。
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 从"META-INF/ spring.factories"探测`BootstrapRegistryInitializer.class`的实现类。
    this.bootstrapRegistryInitializers = new ArrayList<>(
            getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    // 从"META-INF/ spring.factories"探测`ApplicationContextInitializer.class`的实现类。
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 从"META-INF/ spring.factories"探测`ApplicationListener.class`的实现类。
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 探测 main 方法所在的类,具体方式是获取堆栈信息后过滤 main 方法。
    this.mainApplicationClass = deduceMainApplicationClass();
}

自动配置类 ApplicationContextInitializer 和 ApplicationListener 介绍

SpringBoot 自动配置ApplicationContextInitializer实现,详情如下

前言

SpringBoot 采用“约定大于配置”的思想。

SpringBoot 支持自动配置。

约定大于配置

“约定大于配置”(Convention Over Configuration)是一种软件设计范式,其核心思想是:框架为开发者提供一套默认的、符合大多数人习惯的约定(标准、规范),开发者只需要在不遵守这些约定时,才需要显式地编写配置来指定自己的行为。

参数校验异常

request 请求参数解析可能抛出 3 种常见异常

  1. MethodArgumentNotValidException
    1. 场景:@RequestBody修饰的入参校验
    2. 处理器:RequestResponseBodyMethodProcessor
  2. BindException
    1. 场景:未使用 @RequestBody@RequestParam等注解修饰的入参校验,且入参对象被@Valid@Validated相关注解修饰。
    2. 处理器:ServletModelAttributeMethodProcessor/ModelAttributeMethodProcessor
  3. ConstraintViolationException
    1. 场景:类被@Validated注解修饰,且未使用 @RequestBody修饰入参对象,且入参对象被@Constraint相关注解修饰。
    2. 处理器:org.springframework.validation.beanvalidation.MethodValidationInterceptor

@Validated注解修饰的类的方法均会由 MethodValidationInterceptor 拦截器校验参数,优先级低于请求参数处理器(例如 RequestResponseBodyMethodProcessor)。

请求入口

1
2
3
4
5
6
7
-> Tomcat 网络连接
-> StandardEngineValve
-> StandardHostValve
-> StandardContextValve
-> StandardContextValve
-> ApplicationFilterChain
-> HttpServlet

Servlet 入口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 请求流程
// javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
-> org.springframework.web.servlet.FrameworkServlet#service
    -> 如果是 PATCH 方法或空方法if (httpMethod == HttpMethod.PATCH || httpMethod == null) 
        -> 详情参加 POST 方法org.springframework.web.servlet.FrameworkServlet#processRequest
    -> javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
        -> 根据方法类型路由到不同的方法
            -> GETlastModified 参数相关适配
            -> POSTorg.springframework.web.servlet.FrameworkServlet#doPost
                -> org.springframework.web.servlet.FrameworkServlet#processRequest
                    -> LocaleContextRequestAttributes 等处理
                    -> org.springframework.web.servlet.DispatcherServlet#doService
                        -> 详情参加分支 DispatcherServlet#doDispatchorg.springframework.web.servlet.DispatcherServlet#doDispatch
            -> PUT
            -> OPTION
            -> 其它方法略

请求分发

分支 DispatcherServlet#doDispatch

  1. Aspect 使用场景
  2. 接口定义 Advice/Pointcut/Advisor
  3. Aspect 执行顺序
  4. Aspect-Bean解析流程
    1. SmartInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
    2. SmartInstantiationAwareBeanPostProcessor#postProcessAfterInitialization
  5. Aspect-Interceptor执行流程
    1. JdkDynamicAopProxy#invoke
    2. DynamicAdvisedInterceptor#intercept
    3. ReflectiveMethodInvocation#proceed

  1. PointcutAdvisor = Advice + Pointcut
  2. Advice: AspectJAroundAdvice/AspectJMethodBeforeAdvice/AspectJAfterAdvice/AspectJAfterReturningAdvice/AspectJAfterThrowingAdvice
  3. Pointcut: AspectJExpressionPointcut
  4. PointcutAdvisor: InstantiationModelAwarePointcutAdvisorImpl instanceof PointcutAdvisor
  5. Advisor refers to PointcutAdvisor
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 声明式
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
-> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
-> org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
-> org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator


// 编程式
org.springframework.aop.framework.ProxyFactory
org.springframework.aop.aspectj.annotation.AspectJProxyFactory
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator
 bean name 过滤期望被 AOP 代理的普通 bean
-> org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator#getAdvicesAndAdvisorsForBean
    -> org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator#isSupportedBeanName
        -> org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator#isMatch
配置 advisor/advice/interceptor参见 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#resolveInterceptorNames
-> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#setInterceptorNames


org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
 advisor bean name 过滤 advisor
-> org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator#isEligibleAdvisorBean
    -> org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator#getAdvisorBeanNamePrefix


org.springframework.aop.framework.ProxyFactoryBean
工厂模式创建代理
过滤 advisor/advice/interceptor相关注释 The referenced beans should be of type Interceptor, Advisor or Advice.
-> org.springframework.aop.framework.ProxyFactoryBean#setInterceptorNames

END

HandlerAdapter 介绍

简介

在 Spring MVC 中,HandlerAdapter 是核心组件之一,负责协调控制器(Handler)的执行流程。它的主要作用是适配不同类型的处理器(Handler),使它们能够统一处理请求。

Aspect 动态代理方式

在Spring AOP中,如果目标类实现了至少一个接口,Spring默认会使用JDK动态代理。

JDK动态代理只能代理接口中定义的方法。普通类自身定义的方法(未在接口中声明)不会被代理,代理对象无法“看到”这个方法。

ExposeInvocationInterceptor

将 MethodInvocation 存储到 ThreadLocal 变量中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
	private static final ThreadLocal<MethodInvocation> invocation =
			new NamedThreadLocal<>("Current AOP method invocation");
	public static MethodInvocation currentInvocation() throws IllegalStateException {
		MethodInvocation mi = invocation.get();
        //...
    }
	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		invocation.set(mi);
		try {
			return mi.proceed();
		}
		finally {
			invocation.set(oldInvocation);
		}
	}
}

END