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

spring aop 源码解析

上级 4b516e3b
此差异已折叠。
......@@ -11,6 +11,7 @@ repositories {
dependencies {
implementation project(':spring-context')
implementation 'javax.annotation:javax.annotation-api:1.3.2'
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
}
......
package com.matrix.nickel;
import com.matrix.nickel.pojo.Person;
import com.matrix.nickel.service.ContextRefreshEventListner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
......@@ -14,10 +16,25 @@ public class Main {
for (int i = 1; i <= 5; 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();
for (String na : definitionNames) {
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 {
}
// 修改打包的文件名
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 {
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 {
configure(allprojects) { project ->
apply plugin: "org.springframework.build.localdev"
repositories {
maven(){
url 'https://maven.aliyun.com/repository/public/'
}
mavenCentral()
maven {
url "https://repo.spring.io/milestone"
......@@ -42,6 +45,8 @@ configure(allprojects) { project ->
}
}
configure(allprojects - project(":framework-platform")) {
configurations {
dependencyManagement {
......@@ -56,6 +61,7 @@ configure(allprojects - project(":framework-platform")) {
}
}
configure([rootProject] + javaProjects) { project ->
group = "org.springframework"
......@@ -122,3 +128,30 @@ configure(rootProject) {
description = "Spring Framework"
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 {
);
COMPILER_ARGS = new ArrayList<>();
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(
"-Xlint:varargs", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation",
"-Xlint:unchecked", "-Werror"
"-Xlint:unchecked"
));
TEST_COMPILER_ARGS = new ArrayList<>();
TEST_COMPILER_ARGS.addAll(commonCompilerArgs);
......
version=6.1.0-SNAPSHOT
version=6.1.0-self-SNAPSHOT
org.gradle.caching=true
org.gradle.jvmargs=-Xmx2048m
org.gradle.parallel=true
kotlinVersion=1.9.10
kotlin.jvm.target.validation.mode=ignore
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 {
maven { url 'https://maven.aliyun.com/repository/public' }
mavenCentral()
gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release' }
maven { url "https://repo.spring.io/release" }
}
}
......@@ -62,4 +63,5 @@ settings.gradle.projectsLoaded {
}
include '_01-hellospring'
include '_03-aop-demo'
include '_04_web-demo'
......@@ -49,11 +49,11 @@ import org.springframework.lang.Nullable;
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
* @since 10.10.2003
*/
public interface BeanPostProcessor {
......@@ -63,12 +63,15 @@ public interface BeanPostProcessor {
* 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.
* <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
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* <p>
* 初始化bean之前,相当于把bean注入spring上下文之前
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
......@@ -88,13 +91,16 @@ public interface BeanPostProcessor {
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other {@code BeanPostProcessor} callbacks.
* <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
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
* <p>
* 初始化bean之后,相当于把bean注入spring上下文之后
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
......
......@@ -65,6 +65,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* @see #postProcessAfterInstantiation
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getBeanClass()
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName()
*
* 实例化bean之前,相当于new这个bean之前
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
......@@ -85,6 +87,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* instances being invoked on this bean instance.
* @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessBeforeInstantiation
*
* 实例化bean之后,相当于new这个bean之后
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
......@@ -101,6 +105,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
* PropertyValues instance), or {@code null} to skip property population
* @throws org.springframework.beans.BeansException in case of errors
* @since 5.1
*
* bean已经实例化完成,在属性注入时阶段触发,@Autowired,@Resource等注解原理基于此方法实现
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
......
......@@ -93,21 +93,26 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
if (bean instanceof EnvironmentAware environmentAware) {
environmentAware.setEnvironment(this.applicationContext.getEnvironment());
}
// 用于获取StringValueResolver的一个扩展类, StringValueResolver用于获取基于String类型的properties的变量,一般我们都用@Value的方式去获取,如果实现了这个Aware接口,把StringValueResolver缓存起来,通过这个类去获取String类型的变量,效果是一样的
if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {
embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);
}
// 用于获取ResourceLoader的一个扩展类,ResourceLoader可以用于获取classpath内所有的资源对象,可以扩展此类来拿到ResourceLoader对象
if (bean instanceof ResourceLoaderAware resourceLoaderAware) {
resourceLoaderAware.setResourceLoader(this.applicationContext);
}
// 用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件
if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {
applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);
}
// 用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化
if (bean instanceof MessageSourceAware messageSourceAware) {
messageSourceAware.setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware applicationStartupAware) {
applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());
}
// 用来获取ApplicationContext的一个扩展类,ApplicationContext应该是很多人非常熟悉的一个类了,就是spring上下文管理器,可以手动的获取任何在spring上下文注册的bean,我们经常扩展这个接口来缓存spring上下文,包装成静态方法。同时ApplicationContext也实现了BeanFactory,MessageSource,ApplicationEventPublisher等接口,也可以用来做相关接口的事情
if (bean instanceof ApplicationContextAware applicationContextAware) {
applicationContextAware.setApplicationContext(this.applicationContext);
}
......
......@@ -605,7 +605,7 @@ public class CorsConfiguration {
/**
* 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
* means the request origin is not allowed
*/
......@@ -617,6 +617,8 @@ public class CorsConfiguration {
String originToCheck = trimTrailingSlash(origin);
if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
if (this.allowedOrigins.contains(ALL)) {
// allowCredentials 设置为 true,则 allowedOrigins 不能有 * 配置
// 逻辑就是:allowCredentials 表示需要对跨域进行认证,但 origins 的允许竟然是所有的,这样跨域认证就没有必要了
validateAllowCredentials();
return ALL;
}
......@@ -626,6 +628,7 @@ public class CorsConfiguration {
}
}
}
if (!ObjectUtils.isEmpty(this.allowedOriginPatterns)) {
for (OriginPattern p : this.allowedOriginPatterns) {
if (p.getDeclaredPattern().equals(ALL) || p.getPattern().matcher(originToCheck).matches()) {
......@@ -684,8 +687,8 @@ public class CorsConfiguration {
requestHeader = requestHeader.trim();
if (allowAnyHeader) {
result.add(requestHeader);
}
else {
} else {
// 允许的 header 和实际的 header 求交集
for (String allowedHeader : this.allowedHeaders) {
if (requestHeader.equalsIgnoreCase(allowedHeader)) {
result.add(requestHeader);
......
......@@ -71,6 +71,7 @@ public class DefaultCorsProcessor implements CorsProcessor {
response.addHeader(HttpHeaders.VARY, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
}
// 不是跨域请求,就不处理跨域逻辑
if (!CorsUtils.isCorsRequest(request)) {
return true;
}
......@@ -81,12 +82,16 @@ public class DefaultCorsProcessor implements CorsProcessor {
}
boolean preFlightRequest = CorsUtils.isPreFlightRequest(request);
// 大多数情况下,这不会为 null
if (config == null) {
if (preFlightRequest) {
// 如果接收到了预检请求,但没有找到跨域配置,返回错误信息
// 因为只有跨域才会发预检请求,说明跨域了,但没有配置跨域的配置,说明后端缺少对跨域的配置,必须返回异常
// 只要是跨域请求,就必须对跨域请求进行处理,不管是通过还是不公通过,都要处理,spring web 不允许不做任何处理,这里才返回异常,而且是强制性的
rejectRequest(new ServletServerHttpResponse(response));
return false;
}
else {
} else {
// 是跨域请求,但又不是预检请求,不是预检请求,说明浏览器已经通过了预检请求,说明其他什么地方已经处理了跨域的预检,这里就不需要处理,直接放行就可以了
return true;
}
}
......@@ -110,7 +115,7 @@ public class DefaultCorsProcessor implements CorsProcessor {
*/
protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response,
CorsConfiguration config, boolean preFlightRequest) throws IOException {
// 判断 origin 是否允许
String requestOrigin = request.getHeaders().getOrigin();
String allowOrigin = checkOrigin(config, requestOrigin);
HttpHeaders responseHeaders = response.getHeaders();
......@@ -121,7 +126,10 @@ public class DefaultCorsProcessor implements CorsProcessor {
return false;
}
// 判断 method 是否允许
// 跨域的请求类型或者对什么请求进行预检
HttpMethod requestMethod = getMethodToUse(request, preFlightRequest);
// 后台允许的跨域请求
List<HttpMethod> allowMethods = checkMethods(config, requestMethod);
if (allowMethods == null) {
logger.debug("Reject: HTTP '" + requestMethod + "' is not allowed");
......@@ -129,6 +137,8 @@ public class DefaultCorsProcessor implements CorsProcessor {
return false;
}
// 如果是预检请求,获取 Access-Control-Request-Headers 的值,如果设置了就是设置的值,不设置就是空,而不是 null
// 判断 header 是否允许
List<String> requestHeaders = getHeadersToUse(request, preFlightRequest);
List<String> allowHeaders = checkHeaders(config, requestHeaders);
if (preFlightRequest && allowHeaders == null) {
......
......@@ -241,7 +241,9 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
@Override
@Nullable
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
// 一般解析出来都是这个格式的 /adapter/hello 的字符串
Object path = resolvePath(request);
// 只有从 ServletRequestPathUtils.getCachedPath 获取到的才会是 PathContainer 类型,否则大多数都是 String 类型
boolean isPathContainer = (path instanceof PathContainer);
for (Map.Entry<PathPattern, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
if (match(path, isPathContainer, entry.getKey())) {
......
......@@ -84,6 +84,9 @@ public class CorsFilter extends OncePerRequestFilter {
FilterChain filterChain) throws ServletException, IOException {
CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
// 分析代码,能返回 false 的情况,
// 1. corsConfiguration 为 null 且是预检请求
// 2.
boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册