Skip to content

Commit

Permalink
源码分析@2024-11-08
Browse files Browse the repository at this point in the history
  • Loading branch information
diguage committed Nov 8, 2024
1 parent e67f892 commit a9699b4
Show file tree
Hide file tree
Showing 430 changed files with 20,908 additions and 62 deletions.
116 changes: 116 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Deploy GitHub Pages
on:
push:
branches:
- analysis
jobs:
deploy-gh-pages:
runs-on: ubuntu-latest
steps:
# https://github.com/actions/checkout
- name: Checkout 🛎️
uses: actions/checkout@v4
with:
ref: analysis
persist-credentials: false

# https://github.com/actions/setup-java
- name: Set up JDK ☕️
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

# https://github.com/actions/setup-node
- name: Setup Node.js 🕸
uses: actions/setup-node@v4
with:
# https://github.com/nvm-sh/nvm#long-term-support
node-version: 'lts/*'

- name: Install Graphviz 🐰
run: |
sudo apt update -y -m
sudo apt install -y python3-pip
# https://graphviz.org/
sudo apt install -y graphviz
# https://blockdiag.com/en/seqdiag/index.html
pip3 install seqdiag
# https://blockdiag.com/en/blockdiag/index.html
pip3 install blockdiag
# https://blockdiag.com/en/actdiag/index.html
pip3 install actdiag
# https://blockdiag.com/en/nwdiag/index.html
pip3 install nwdiag
# https://github.com/Deep-Symmetry/bytefield-svg
npm install -g bytefield-svg
# https://github.com/gtudan/bpmn-js-cmd
npm install -g bpmn-js-cmd
- name: Install font 🎃
run: |
mkdir $HOME/.fonts
cd $HOME/.fonts
wget https://github.com/diguage/open-fonts/releases/download/latest/SourceHanSerifSC-Regular.otf
wget https://github.com/diguage/open-fonts/releases/download/latest/SourceHanSansSC-Regular.otf
wget https://github.com/diguage/open-fonts/releases/download/latest/SourceCodePro-Regular.otf
wget https://github.com/diguage/open-fonts/releases/download/latest/SourceCodePro-It.otf
wget https://github.com/diguage/open-fonts/releases/download/latest/SourceCodePro-Bold.otf
wget https://github.com/diguage/open-fonts/releases/download/latest/SourceCodePro-BoldIt.otf
echo -e "[seqdiag]\nfontpath = $HOME/.fonts/SourceHanSerifSC-Regular.otf" > $HOME/.blockdiagrc
echo -e "\n[blockdiag]\nfontpath = $HOME/.fonts/SourceHanSerifSC-Regular.otf" >> $HOME/.blockdiagrc
echo -e "\n[actdiag]\nfontpath = $HOME/.fonts/SourceHanSerifSC-Regular.otf" >> $HOME/.blockdiagrc
echo -e "\n[nwdiag]\nfontpath = $HOME/.fonts/SourceHanSerifSC-Regular.otf" >> $HOME/.blockdiagrc
# Check result
ls -lh $HOME/.fonts
cat $HOME/.blockdiagrc
- name: Build 🔧
continue-on-error: true
run: ./gradlew :truman:asciidoctor --no-build-cache

- name: Custom Code Style 🐦
run: |
sudo apt install -y sed
sed -i 's/<\/head>/<style>p>code{color: #d14 !important;background-color: #f5f5f5 !important;border: 1px solid #e1e1e8;white-space: nowrap;border-radius: 3px;}<\/style>\n<\/head>/' truman/build/docs/html5/index.html
- name: Compress Style 🍭
run: |
npm install cssnano-cli --global
cd truman/build/docs/html5/css
for f in `ls *.css`;
do
fn="${f%.*}.min.css";
cssnano $f $fn;
rm -rf $f;
mv $fn $f
done
- name: Compress HTML 🦄
run: |
npm install html-minifier --global
cd truman/build/docs/html5
echo '{"caseSensitive":true,
"collapseBooleanAttributes":true,
"keepClosingSlash":true,
"processConditionalComments":true,
"removeComments":true,
"removeEmptyAttributes":true,
"removeRedundantAttributes":true,
"removeScriptTypeAttributes":true,
"removeStyleLinkTypeAttributes":true,
"sortAttributes":true,
"sortClassName":true,
"useShortDoctype":true}' >> html-minifier.config.json
html-minifier -c html-minifier.config.json index.html -o index.min.htm
rm -rf *.html .asciidoctor
mv index.min.htm index.html
# https://github.com/JamesIves/github-pages-deploy-action
- name: Deploy 🚀
continue-on-error: true
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: dgh-pages # The branch the action should deploy to.
folder: truman/build/docs/html5 # The folder the action should deploy.
single-commit: true
39 changes: 39 additions & 0 deletions .github/workflows/sync-main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
on:
schedule:
- cron: '0 4 * * *'
# scheduled at 04:00 everyday

workflow_dispatch: # click the button on Github repo!


jobs:
sync-with-upstream:
runs-on: ubuntu-latest
name: Sync main with upstream latest

steps:
# Step 1: run a standard checkout action, provided by github
- name: Checkout 🛎️
uses: actions/[email protected]
with:
ref: main

# Step 2: run this sync action - specify the upstream repo,
# upstream branch to sync with, and target sync branch
- name: Fork Sync With Upstream 😘
id: sync
uses: aormsby/[email protected]
with:
upstream_repository: spring-projects/spring-framework
upstream_branch: main
target_branch: main
git_pull_args: --ff-only # optional arg use, defaults to simple 'pull'

# Step 3: Display a message if 'sync' step had new commits (simple test)
- name: Check for new commits 🎉
if: steps.sync.outputs.has_new_commits
run: echo "There were new commits."

# Step 4: Print a helpful timestamp for your records (not required, just nice)
- name: Timestamp ✌️
run: date
33 changes: 33 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
= Spring 源码分析^Alpha^
:image_attr: align="center",width=100%


本文档是 D瓜哥 阅读 Spring 源码以及相关文档时的笔记。对学习内容做一些总结和提炼,分享出来也方便大家一起学习,共同进步。

== 友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

[cols="2*^",frame=none]
|===
| image:truman/src/docs/asciidoc/images/alipay.png[title="支付宝", alt="支付宝", width="95%"]
| image:truman/src/docs/asciidoc/images/wxpay.jpg[title="微信", alt="微信", width="95%"]
|===

有些打赏的朋友希望可以加个好友,欢迎关注D瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

image::truman/src/docs/asciidoc/images/wx-jikerizhi.png[{image_attr}]

TIP: **公众号的微信号是: jikerizhi (“极客日志”全拼)**。__因为众所周知的原因,有时图片加载不出来。如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。__

== 官网及版本库

本文档的版本库托管在 Github 上,另外单独发布。

“地瓜哥”博客网:: https://www.diguage.com/[^] 。D瓜哥的个人博客。欢迎光临,不过,内容很杂乱,请见谅。不见谅,你来打我啊,😂😂
本文档官网:: https://diguage.github.io/spring-framework/[^] 。为了方便阅读,这里展示了处理好的文档。阅读请点击这个网址。
本文档版本库:: https://github.com/diguage/spring-framework[^] 。由于组织方式的特殊性,坦白讲,不建议大家发 PR。有问题,欢迎发 Issue 讨论。

== 欢迎搞基

大家有任何问题,可以通过发 Issue 或 在 Discussions 中发帖讨论,我已经开通了 Issues 和 Discussions。
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public class JavaConventions {
COMPILER_ARGS.addAll(commonCompilerArgs);
COMPILER_ARGS.addAll(Arrays.asList(
"-Xlint:varargs", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation",
"-Xlint:unchecked", "-Werror"
// TODO 这里删除了参数 "-Werror"
"-Xlint:unchecked"
));
TEST_COMPILER_ARGS = new ArrayList<>();
TEST_COMPILER_ARGS.addAll(commonCompilerArgs);
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ include "framework-bom"
include "framework-docs"
include "framework-platform"
include "integration-tests"
include 'truman'

rootProject.name = "spring"
rootProject.children.each {project ->
Expand All @@ -53,3 +54,4 @@ settings.gradle.projectsLoaded {
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
package org.springframework.aop;

/**
* `PointcutAdvisor` 才是真正的定义一个 `Pointcut` 和一个 `Advice` 的 `Advisor`。
*
* `DefaultPointcutAdvisor` 是最通用的 `PointcutAdvisor` 实现。
*
* `NameMatchMethodPointcutAdvisor` 是细化后的 `DefaultPointcutAdvisor`。
*
* Superinterface for all Advisors that are driven by a pointcut.
* This covers nearly all advisors except introduction advisors,
* for which method-level matching doesn't apply.
Expand Down
14 changes: 14 additions & 0 deletions spring-aop/src/main/java/org/springframework/aop/TargetSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
import org.springframework.lang.Nullable;

/**
* `TargetSource` 最主要的特性是,每次方法调用都会触发 `TargetSource` 的
* `getTarget()` 方法, `getTarget()` 方法将从相应的 `TargetSource`
* 实现类中取得具体的目标对象,这样就可以控制每次方法调用作用到的具体实例对象。
*
* <p>主要实现有:
*
* <ul>
* <li>SingletonTargetSource -- 内部只持有一个目标对象,每次调用时,都会返回这同一个目标对象。</li>
* <li>PrototypeTargetSource -- 每次调用目标对象上的方法时,都会返回一个新的目标对象实例供调用。注意: `scope` 要设置成 `prototype`;通过 `targetBeanName` 属性指定目标对象的 bean 定义名称,而不是引用。</li>
* <li>HotSwappableTargetSource -- 使用 `HotSwappableTargetSource` 封装目标对象,可以在应用程序运行时,根据某种特定条件,动态地替换目标对象类的具体实现。</li>
* <li>CommonsPool2TargetSource -- 使用 Apache Commons Pool 2 来提供对象池的支持。</li>
* <li>ThreadLocalTargetSource -- 为不同线程调用提供不同的目标对象。保证各自线程上对目标对象的调用,可以被分配到当前线程对应的那个目标对象实例上。注意: scope 要设置成 prototype。</li>
* </ul>
*
* A {@code TargetSource} is used to obtain the current "target" of
* an AOP invocation, which will be invoked via reflection if no around
* advice chooses to end the interceptor chain itself.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
// 激活增强方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ public AspectJAfterAdvice(
}


// 后置通知
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
// 激活增强方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public boolean matches(Class<?> targetClass) {
}

try {
try {
try { // 表达式匹配交给了 AspectJ 来完成了
return obtainPointcutExpression().couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public AspectJMethodBeforeAdvice(
super(aspectJBeforeAdviceMethod, pointcut, aif);
}


// 前置通知
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public void validate(Class<?> aspectClass) throws AopConfigException {
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
//设置敏感的注解类
for (Class<?> annotationType : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation annotation = findAnnotation(method, (Class<Annotation>) annotationType);
if (annotation != null) {
Expand All @@ -123,6 +124,7 @@ protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method)
return null;
}

//获取指定方法上的注解并使用AspectJAnnotation封装
@Nullable
private static AspectJAnnotation findAnnotation(Method method, Class<? extends Annotation> annotationType) {
Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,20 @@ protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}


// tag::findCandidateAdvisors[]
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
//当使用注解方式配置AOP的时候并不是丢弃了对XML配置的支持
//在这里调用父类方法加载配置文件中的AOP声明
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
// end::findCandidateAdvisors[]

@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, Aspect
}


// tag::buildAspectJAdvisors[]
/**
* Look for AspectJ-annotated aspect beans in the current bean factory,
* and return to a list of Spring AOP Advisors representing them.
Expand All @@ -95,24 +96,30 @@ public List<Advisor> buildAspectJAdvisors() {
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//获取所有的beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
//循环所有的beanName找出对应的增强方法
for (String beanName : beanNames) {
//不合法的bean则略过,由子类定义规则,默认返回true
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
//获取对应的bean的类型
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (beanType == null) {
continue;
}
//如果存在Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
try {
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析标记AspectJ注解中的增强方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
Expand Down Expand Up @@ -164,6 +171,7 @@ public List<Advisor> buildAspectJAdvisors() {
}
return advisors;
}
// end::buildAspectJAdvisors[]

/**
* Return whether the aspect bean with the given name is eligible.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut decl
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 根据不同的注解,初始化对应的增强器
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
Expand Down
Loading

0 comments on commit a9699b4

Please sign in to comment.