提交 1f7beaa0 编写于 作者: 项羽过江东's avatar 项羽过江东

spring aop 源码解析

上级 4b516e3b
此差异已折叠。
...@@ -11,6 +11,7 @@ repositories { ...@@ -11,6 +11,7 @@ repositories {
dependencies { dependencies {
implementation project(':spring-context') implementation project(':spring-context')
implementation 'javax.annotation:javax.annotation-api:1.3.2'
testImplementation platform('org.junit:junit-bom:5.9.1') testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.junit.jupiter:junit-jupiter'
} }
......
package com.matrix.nickel; package com.matrix.nickel;
import com.matrix.nickel.pojo.Person;
import com.matrix.nickel.service.ContextRefreshEventListner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/** /**
...@@ -14,10 +16,25 @@ public class Main { ...@@ -14,10 +16,25 @@ public class Main {
for (int i = 1; i <= 5; i++) { for (int i = 1; i <= 5; i++) {
System.out.println("i = " + i); System.out.println("i = " + i);
} }
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Person.class);
AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext();
context.addBeanFactoryPostProcessor(new UserServiceBeanFactoryPostProcessor());
context.addApplicationListener(new ContextRefreshEventListner());
context.register(Person.class);
refreshContext(context);
String[] definitionNames = context.getBeanDefinitionNames(); String[] definitionNames = context.getBeanDefinitionNames();
for (String na : definitionNames) { for (String na : definitionNames) {
System.out.println(na); System.out.println(na);
} }
System.out.println("中文");
refreshContext(context);
}
private static void refreshContext(AnnotationConfigApplicationContext context){
if(!context.isActive()){
context.refresh();
}
} }
} }
\ No newline at end of file
package com.matrix.nickel;
import com.matrix.nickel.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
/**
* @author Nickel
* @date 2024-01-08 19:14:44
*/
public class UserServiceBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition("userService", new RootBeanDefinition(UserService.class));
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
package com.matrix.nickel.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.stereotype.Component;
/**
* @author Nickel
* @date 2023-11-22 04:29:08
*/
@Component
@Lazy
public class ContextRefreshEventListner implements ApplicationListener<ContextRefreshedEvent> {
Log log = LogFactory.getLog("contextRefresh");
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
log.info("处理事件:ContextRefreshedEvent");
}
}
package com.matrix.nickel.service;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
* @author Nickel
* @date 2024-01-08 19:00:10
*/
@Service
public class UserService implements InitializingBean {
@PostConstruct
public void init(){
System.out.println("@PostConstruct");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean");
}
}
...@@ -48,6 +48,24 @@ dependencies { ...@@ -48,6 +48,24 @@ dependencies {
} }
// 修改打包的文件名
archivesBaseName = 'aop.demo'
jar {
manifest.attributes["Implementation-Title"] = project.name
manifest.attributes["Implementation-Version"] = project.version
manifest.attributes["Automatic-Module-Name"] = project.name.replace('-', '.') // for Jigsaw
manifest.attributes["Created-By"] =
"${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
from("${rootDir}/framework-docs/src/docs/dist") {
include "license.txt"
include "notice.txt"
into "META-INF"
expand(copyright: new Date().format("yyyy"), version: project.version)
}
}
test { test {
useJUnitPlatform() useJUnitPlatform()
} }
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
\ No newline at end of file
plugins {
id 'java'
}
group = 'com.bonc.cto'
version = '6.1.0-self-SNAPSHOT'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation project(':spring-context')
implementation project(':spring-aop')
// implementation project(':spring-aspects')
implementation project(':spring-web')
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
implementation 'org.projectlombok:lombok:1.18.28'
compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.28'
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.28'
// 如果使用 slf4j 1.0 的 api,桥接到 log4j 会有问题,必须使用 slf4j 2.0 版本适配
implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.7'
implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j2-impl', version: '2.20.0'
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.20.0'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.20.0'
}
test {
useJUnitPlatform()
}
\ No newline at end of file
package com.bonc.cto;
/**
* ${DESC}
*
* @author Nickel
* @date 2023-12-21 12:12:38
*/// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
public static void main(String[] args) {
// Press Alt+Enter with your caret at the highlighted text to see how
// IntelliJ IDEA suggests fixing it.
System.out.printf("Hello and welcome!");
// Press Shift+F10 or click the green arrow button in the gutter to run the code.
for (int i = 1; i <= 5; i++) {
// Press Shift+F9 to start debugging your code. We have set one breakpoint
// for you, but you can always add more by pressing Ctrl+F8.
System.out.println("i = " + i);
}
}
}
\ No newline at end of file
...@@ -19,6 +19,9 @@ ext { ...@@ -19,6 +19,9 @@ ext {
configure(allprojects) { project -> configure(allprojects) { project ->
apply plugin: "org.springframework.build.localdev" apply plugin: "org.springframework.build.localdev"
repositories { repositories {
maven(){
url 'https://maven.aliyun.com/repository/public/'
}
mavenCentral() mavenCentral()
maven { maven {
url "https://repo.spring.io/milestone" url "https://repo.spring.io/milestone"
...@@ -42,6 +45,8 @@ configure(allprojects) { project -> ...@@ -42,6 +45,8 @@ configure(allprojects) { project ->
} }
} }
configure(allprojects - project(":framework-platform")) { configure(allprojects - project(":framework-platform")) {
configurations { configurations {
dependencyManagement { dependencyManagement {
...@@ -56,6 +61,7 @@ configure(allprojects - project(":framework-platform")) { ...@@ -56,6 +61,7 @@ configure(allprojects - project(":framework-platform")) {
} }
} }
configure([rootProject] + javaProjects) { project -> configure([rootProject] + javaProjects) { project ->
group = "org.springframework" group = "org.springframework"
...@@ -122,3 +128,30 @@ configure(rootProject) { ...@@ -122,3 +128,30 @@ configure(rootProject) {
description = "Spring Framework" description = "Spring Framework"
apply plugin: 'org.springframework.build.api-diff' apply plugin: 'org.springframework.build.api-diff'
} }
//publishing {
// publications {
// maven(MavenPublication) {
// // 上传 AAR 包
// afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
// // 向 Maven 仓库中上传源码
// artifact sourceJar
// }
// }
//}
allprojects {
repositories {
mavenLocal()
maven {
url 'https://maven.aliyun.com/repository/public/'
}
maven {
url 'https://maven.aliyun.com/repository/spring/'
}
maven {
url 'https://maven.aliyun.com/repository/central'
}
mavenCentral()
}
}
...@@ -50,9 +50,14 @@ public class JavaConventions { ...@@ -50,9 +50,14 @@ public class JavaConventions {
); );
COMPILER_ARGS = new ArrayList<>(); COMPILER_ARGS = new ArrayList<>();
COMPILER_ARGS.addAll(commonCompilerArgs); COMPILER_ARGS.addAll(commonCompilerArgs);
// COMPILER_ARGS.addAll(Arrays.asList(
// "-Xlint:varargs", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation",
// "-Xlint:unchecked", "-Werror"
// ));
// 解决 -Werror 错误
COMPILER_ARGS.addAll(Arrays.asList( COMPILER_ARGS.addAll(Arrays.asList(
"-Xlint:varargs", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation", "-Xlint:varargs", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation",
"-Xlint:unchecked", "-Werror" "-Xlint:unchecked"
)); ));
TEST_COMPILER_ARGS = new ArrayList<>(); TEST_COMPILER_ARGS = new ArrayList<>();
TEST_COMPILER_ARGS.addAll(commonCompilerArgs); TEST_COMPILER_ARGS.addAll(commonCompilerArgs);
......
version=6.1.0-SNAPSHOT version=6.1.0-self-SNAPSHOT
org.gradle.caching=true org.gradle.caching=true
org.gradle.jvmargs=-Xmx2048m
org.gradle.parallel=true org.gradle.parallel=true
kotlinVersion=1.9.10 kotlinVersion=1.9.10
kotlin.jvm.target.validation.mode=ignore kotlin.jvm.target.validation.mode=ignore
kotlin.stdlib.default.dependency=false kotlin.stdlib.default.dependency=false
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx3096m -Dfile.encoding=UTF-8
org.gradle.configureondemand=true
...@@ -3,6 +3,7 @@ pluginManagement { ...@@ -3,6 +3,7 @@ pluginManagement {
maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/public' }
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release' }
maven { url "https://repo.spring.io/release" } maven { url "https://repo.spring.io/release" }
} }
} }
...@@ -62,4 +63,5 @@ settings.gradle.projectsLoaded { ...@@ -62,4 +63,5 @@ settings.gradle.projectsLoaded {
} }
include '_01-hellospring' include '_01-hellospring'
include '_03-aop-demo' include '_03-aop-demo'
include '_04_web-demo'
...@@ -49,11 +49,11 @@ import org.springframework.lang.Nullable; ...@@ -49,11 +49,11 @@ import org.springframework.lang.Nullable;
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor * @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor * @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor * @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor * @see BeanFactoryPostProcessor
* @since 10.10.2003
*/ */
public interface BeanPostProcessor { public interface BeanPostProcessor {
...@@ -63,12 +63,15 @@ public interface BeanPostProcessor { ...@@ -63,12 +63,15 @@ public interface BeanPostProcessor {
* or a custom init-method). The bean will already be populated with property values. * or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original. * The returned bean instance may be a wrapper around the original.
* <p>The default implementation returns the given {@code bean} as-is. * <p>The default implementation returns the given {@code bean} as-is.
* @param bean the new bean instance *
* @param bean the new bean instance
* @param beanName the name of the bean * @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one; * @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked * if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors * @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* <p>
* 初始化bean之前,相当于把bean注入spring上下文之前
*/ */
@Nullable @Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
...@@ -88,13 +91,16 @@ public interface BeanPostProcessor { ...@@ -88,13 +91,16 @@ public interface BeanPostProcessor {
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other {@code BeanPostProcessor} callbacks. * in contrast to all other {@code BeanPostProcessor} callbacks.
* <p>The default implementation returns the given {@code bean} as-is. * <p>The default implementation returns the given {@code bean} as-is.
* @param bean the new bean instance *
* @param bean the new bean instance
* @param beanName the name of the bean * @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one; * @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked * if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors * @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean * @see org.springframework.beans.factory.FactoryBean
* <p>
* 初始化bean之后,相当于把bean注入spring上下文之后
*/ */
@Nullable @Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
......
...@@ -65,6 +65,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { ...@@ -65,6 +65,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* @see #postProcessAfterInstantiation * @see #postProcessAfterInstantiation
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getBeanClass() * @see org.springframework.beans.factory.support.AbstractBeanDefinition#getBeanClass()
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName() * @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName()
*
* 实例化bean之前,相当于new这个bean之前
*/ */
@Nullable @Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
...@@ -85,6 +87,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { ...@@ -85,6 +87,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* instances being invoked on this bean instance. * instances being invoked on this bean instance.
* @throws org.springframework.beans.BeansException in case of errors * @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessBeforeInstantiation * @see #postProcessBeforeInstantiation
*
* 实例化bean之后,相当于new这个bean之后
*/ */
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true; return true;
...@@ -101,6 +105,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { ...@@ -101,6 +105,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* PropertyValues instance), or {@code null} to skip property population * PropertyValues instance), or {@code null} to skip property population
* @throws org.springframework.beans.BeansException in case of errors * @throws org.springframework.beans.BeansException in case of errors
* @since 5.1 * @since 5.1
*
* bean已经实例化完成,在属性注入时阶段触发,@Autowired,@Resource等注解原理基于此方法实现
*/ */
@Nullable @Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
......
...@@ -93,21 +93,26 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor { ...@@ -93,21 +93,26 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
if (bean instanceof EnvironmentAware environmentAware) { if (bean instanceof EnvironmentAware environmentAware) {
environmentAware.setEnvironment(this.applicationContext.getEnvironment()); environmentAware.setEnvironment(this.applicationContext.getEnvironment());
} }
// 用于获取StringValueResolver的一个扩展类, StringValueResolver用于获取基于String类型的properties的变量,一般我们都用@Value的方式去获取,如果实现了这个Aware接口,把StringValueResolver缓存起来,通过这个类去获取String类型的变量,效果是一样的
if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) { if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {
embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver); embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);
} }
// 用于获取ResourceLoader的一个扩展类,ResourceLoader可以用于获取classpath内所有的资源对象,可以扩展此类来拿到ResourceLoader对象
if (bean instanceof ResourceLoaderAware resourceLoaderAware) { if (bean instanceof ResourceLoaderAware resourceLoaderAware) {
resourceLoaderAware.setResourceLoader(this.applicationContext); resourceLoaderAware.setResourceLoader(this.applicationContext);
} }
// 用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件
if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) { if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {
applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext); applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);
} }
// 用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化
if (bean instanceof MessageSourceAware messageSourceAware) { if (bean instanceof MessageSourceAware messageSourceAware) {
messageSourceAware.setMessageSource(this.applicationContext); messageSourceAware.setMessageSource(this.applicationContext);
} }
if (bean instanceof ApplicationStartupAware applicationStartupAware) { if (bean instanceof ApplicationStartupAware applicationStartupAware) {
applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup()); applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());
} }
// 用来获取ApplicationContext的一个扩展类,ApplicationContext应该是很多人非常熟悉的一个类了,就是spring上下文管理器,可以手动的获取任何在spring上下文注册的bean,我们经常扩展这个接口来缓存spring上下文,包装成静态方法。同时ApplicationContext也实现了BeanFactory,MessageSource,ApplicationEventPublisher等接口,也可以用来做相关接口的事情
if (bean instanceof ApplicationContextAware applicationContextAware) { if (bean instanceof ApplicationContextAware applicationContextAware) {
applicationContextAware.setApplicationContext(this.applicationContext); applicationContextAware.setApplicationContext(this.applicationContext);
} }
......
...@@ -605,7 +605,7 @@ public class CorsConfiguration { ...@@ -605,7 +605,7 @@ public class CorsConfiguration {
/** /**
* Check the origin of the request against the configured allowed origins. * Check the origin of the request against the configured allowed origins.
* @param origin the origin to check * @param origin the origin to check 请求中的 origin
* @return the origin to use for the response, or {@code null} which * @return the origin to use for the response, or {@code null} which
* means the request origin is not allowed * means the request origin is not allowed
*/ */
...@@ -617,6 +617,8 @@ public class CorsConfiguration { ...@@ -617,6 +617,8 @@ public class CorsConfiguration {
String originToCheck = trimTrailingSlash(origin); String originToCheck = trimTrailingSlash(origin);
if (!ObjectUtils.isEmpty(this.allowedOrigins)) { if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
if (this.allowedOrigins.contains(ALL)) { if (this.allowedOrigins.contains(ALL)) {
// allowCredentials 设置为 true,则 allowedOrigins 不能有 * 配置
// 逻辑就是:allowCredentials 表示需要对跨域进行认证,但 origins 的允许竟然是所有的,这样跨域认证就没有必要了
validateAllowCredentials(); validateAllowCredentials();
return ALL; return ALL;
} }
...@@ -626,6 +628,7 @@ public class CorsConfiguration { ...@@ -626,6 +628,7 @@ public class CorsConfiguration {
} }
} }
} }
if (!ObjectUtils.isEmpty(this.allowedOriginPatterns)) { if (!ObjectUtils.isEmpty(this.allowedOriginPatterns)) {
for (OriginPattern p : this.allowedOriginPatterns) { for (OriginPattern p : this.allowedOriginPatterns) {
if (p.getDeclaredPattern().equals(ALL) || p.getPattern().matcher(originToCheck).matches()) { if (p.getDeclaredPattern().equals(ALL) || p.getPattern().matcher(originToCheck).matches()) {
...@@ -684,8 +687,8 @@ public class CorsConfiguration { ...@@ -684,8 +687,8 @@ public class CorsConfiguration {
requestHeader = requestHeader.trim(); requestHeader = requestHeader.trim();
if (allowAnyHeader) { if (allowAnyHeader) {
result.add(requestHeader); result.add(requestHeader);
} } else {
else { // 允许的 header 和实际的 header 求交集
for (String allowedHeader : this.allowedHeaders) { for (String allowedHeader : this.allowedHeaders) {
if (requestHeader.equalsIgnoreCase(allowedHeader)) { if (requestHeader.equalsIgnoreCase(allowedHeader)) {
result.add(requestHeader); result.add(requestHeader);
......
...@@ -71,6 +71,7 @@ public class DefaultCorsProcessor implements CorsProcessor { ...@@ -71,6 +71,7 @@ public class DefaultCorsProcessor implements CorsProcessor {
response.addHeader(HttpHeaders.VARY, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS); response.addHeader(HttpHeaders.VARY, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
} }
// 不是跨域请求,就不处理跨域逻辑
if (!CorsUtils.isCorsRequest(request)) { if (!CorsUtils.isCorsRequest(request)) {
return true; return true;
} }
...@@ -81,12 +82,16 @@ public class DefaultCorsProcessor implements CorsProcessor { ...@@ -81,12 +82,16 @@ public class DefaultCorsProcessor implements CorsProcessor {
} }
boolean preFlightRequest = CorsUtils.isPreFlightRequest(request); boolean preFlightRequest = CorsUtils.isPreFlightRequest(request);
// 大多数情况下,这不会为 null
if (config == null) { if (config == null) {
if (preFlightRequest) { if (preFlightRequest) {
// 如果接收到了预检请求,但没有找到跨域配置,返回错误信息
// 因为只有跨域才会发预检请求,说明跨域了,但没有配置跨域的配置,说明后端缺少对跨域的配置,必须返回异常
// 只要是跨域请求,就必须对跨域请求进行处理,不管是通过还是不公通过,都要处理,spring web 不允许不做任何处理,这里才返回异常,而且是强制性的
rejectRequest(new ServletServerHttpResponse(response)); rejectRequest(new ServletServerHttpResponse(response));
return false; return false;
} } else {
else { // 是跨域请求,但又不是预检请求,不是预检请求,说明浏览器已经通过了预检请求,说明其他什么地方已经处理了跨域的预检,这里就不需要处理,直接放行就可以了
return true; return true;
} }
} }
...@@ -110,7 +115,7 @@ public class DefaultCorsProcessor implements CorsProcessor { ...@@ -110,7 +115,7 @@ public class DefaultCorsProcessor implements CorsProcessor {
*/ */
protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response, protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response,
CorsConfiguration config, boolean preFlightRequest) throws IOException { CorsConfiguration config, boolean preFlightRequest) throws IOException {
// 判断 origin 是否允许
String requestOrigin = request.getHeaders().getOrigin(); String requestOrigin = request.getHeaders().getOrigin();
String allowOrigin = checkOrigin(config, requestOrigin); String allowOrigin = checkOrigin(config, requestOrigin);
HttpHeaders responseHeaders = response.getHeaders(); HttpHeaders responseHeaders = response.getHeaders();
...@@ -121,7 +126,10 @@ public class DefaultCorsProcessor implements CorsProcessor { ...@@ -121,7 +126,10 @@ public class DefaultCorsProcessor implements CorsProcessor {
return false; return false;
} }
// 判断 method 是否允许
// 跨域的请求类型或者对什么请求进行预检
HttpMethod requestMethod = getMethodToUse(request, preFlightRequest); HttpMethod requestMethod = getMethodToUse(request, preFlightRequest);
// 后台允许的跨域请求
List<HttpMethod> allowMethods = checkMethods(config, requestMethod); List<HttpMethod> allowMethods = checkMethods(config, requestMethod);
if (allowMethods == null) { if (allowMethods == null) {
logger.debug("Reject: HTTP '" + requestMethod + "' is not allowed"); logger.debug("Reject: HTTP '" + requestMethod + "' is not allowed");
...@@ -129,6 +137,8 @@ public class DefaultCorsProcessor implements CorsProcessor { ...@@ -129,6 +137,8 @@ public class DefaultCorsProcessor implements CorsProcessor {
return false; return false;
} }
// 如果是预检请求,获取 Access-Control-Request-Headers 的值,如果设置了就是设置的值,不设置就是空,而不是 null
// 判断 header 是否允许
List<String> requestHeaders = getHeadersToUse(request, preFlightRequest); List<String> requestHeaders = getHeadersToUse(request, preFlightRequest);
List<String> allowHeaders = checkHeaders(config, requestHeaders); List<String> allowHeaders = checkHeaders(config, requestHeaders);
if (preFlightRequest && allowHeaders == null) { if (preFlightRequest && allowHeaders == null) {
......
...@@ -241,7 +241,9 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource ...@@ -241,7 +241,9 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
@Override @Override
@Nullable @Nullable
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
// 一般解析出来都是这个格式的 /adapter/hello 的字符串
Object path = resolvePath(request); Object path = resolvePath(request);
// 只有从 ServletRequestPathUtils.getCachedPath 获取到的才会是 PathContainer 类型,否则大多数都是 String 类型
boolean isPathContainer = (path instanceof PathContainer); boolean isPathContainer = (path instanceof PathContainer);
for (Map.Entry<PathPattern, CorsConfiguration> entry : this.corsConfigurations.entrySet()) { for (Map.Entry<PathPattern, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
if (match(path, isPathContainer, entry.getKey())) { if (match(path, isPathContainer, entry.getKey())) {
......
...@@ -84,6 +84,9 @@ public class CorsFilter extends OncePerRequestFilter { ...@@ -84,6 +84,9 @@ public class CorsFilter extends OncePerRequestFilter {
FilterChain filterChain) throws ServletException, IOException { FilterChain filterChain) throws ServletException, IOException {
CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request); CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
// 分析代码,能返回 false 的情况,
// 1. corsConfiguration 为 null 且是预检请求
// 2.
boolean isValid = this.processor.processRequest(corsConfiguration, request, response); boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
if (!isValid || CorsUtils.isPreFlightRequest(request)) { if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return; return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册