Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
5138e5e
update repo
lxcecho Dec 10, 2023
d455ec0
Add IOC By Xml
lxcecho Dec 10, 2023
60fedf5
Add IOC By Annotation
lxcecho Dec 10, 2023
86a3f3b
Add AOP Debug demo
lxcecho Dec 10, 2023
c38a173
Merge branch 'spring-projects:6.0.x' into 6.0.x
lxcecho Dec 10, 2023
c2b721a
Custom spring demo
lxcecho Dec 10, 2023
e3d30b9
Add JDBC and TX debug demo
lxcecho Dec 10, 2023
d970afa
Add reflect demo
lxcecho Dec 10, 2023
09116c9
update fault
lxcecho Dec 11, 2023
ea9b69a
add junit test demo
lxcecho Dec 11, 2023
001710f
add resources demo
lxcecho Dec 11, 2023
2e4547e
add i18n demo
lxcecho Dec 11, 2023
744f2fb
add notes
lxcecho Dec 11, 2023
2fc67dd
update demo
lxcecho Dec 12, 2023
ece7428
update demo
lxcecho Dec 12, 2023
71af28d
Merge branch 'spring-projects:6.0.x' into 6.0.x
lxcecho Dec 12, 2023
cf59003
update resource demo
lxcecho Dec 16, 2023
da442db
update tx demo
lxcecho Dec 16, 2023
cf6ced1
xml_anno transaction debug
lxcecho Dec 17, 2023
b5543a0
all anno transaction debug
lxcecho Dec 17, 2023
52e7a89
xml transaction debug
lxcecho Dec 17, 2023
7ffe0a6
resource demo debug
lxcecho Dec 17, 2023
c54cee5
i18n demo debug
lxcecho Dec 17, 2023
5936750
validation demo debug
lxcecho Dec 17, 2023
2244db4
IOC by annotation
lxcecho Dec 17, 2023
87296f1
IOC by xml
lxcecho Dec 17, 2023
ec4f54b
debug
lxcecho Dec 24, 2023
2c3498a
debug
lxcecho Dec 27, 2023
3555a0a
AOP debug
lxcecho Dec 29, 2023
60d7ecb
AOP debug
lxcecho Dec 30, 2023
bf233d2
AOP debug
lxcecho Jan 1, 2024
018b31e
Merge branch 'spring-projects:6.0.x' into 6.0.x
lxcecho Jan 1, 2024
fb35d49
update notes
lxcecho Jan 1, 2024
45aede4
add spring mvc demo
lxcecho Jan 1, 2024
5f24992
add spring mvc demo
lxcecho Jan 2, 2024
aef6c98
tx debug
lxcecho Jan 3, 2024
ccd160b
tx debug
lxcecho Jan 4, 2024
6c81ce5
tx debug
lxcecho Jan 7, 2024
f7df8b9
Merge branch 'spring-projects:6.0.x' into 6.0.x
lxcecho Jan 7, 2024
f2ad507
Merge branch 'spring-projects:6.0.x' into 6.0.x
lxcecho Jan 19, 2024
336d308
tx debug
lxcecho Mar 10, 2024
34d3336
tx debug
lxcecho Mar 24, 2024
55e69bc
tx debug
lxcecho Mar 26, 2024
c89004a
tx debug
lxcecho Mar 30, 2024
b33ccdf
debug
lxcecho Mar 31, 2024
826786c
Merge branch '6.0.x' into 6.0.x
lxcecho Oct 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,25 @@ ext {

configure(allprojects) { project ->
repositories {
mavenLocal()
mavenCentral()
google()
maven {
url "https://repo.spring.io/milestone"
url "https://maven.aliyun.com/repository/spring"
// url "https://repo.spring.io/milestone"
content {
// Netty 5 optional support
includeGroup 'io.projectreactor.netty'
}
}
if (version.contains('-')) {
maven { url "https://repo.spring.io/milestone" }
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/central" }
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/apache-snapshots" }
maven { url "https://maven.aliyun.com/repository/spring" }
maven { url "https://maven.aliyun.com/repository/spring-plugin"}
// maven { url "https://repo.spring.io/milestone" }
}
if (version.endsWith('-SNAPSHOT')) {
maven { url "https://repo.spring.io/snapshot" }
Expand Down
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
# distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=file:///D:/ENV/Gradle/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
13 changes: 13 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
pluginManagement {
repositories {
mavenLocal()
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/central" }
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/apache-snapshots" }
maven { url "https://maven.aliyun.com/repository/spring" }
maven { url "https://maven.aliyun.com/repository/spring-plugin"}
google()
mavenCentral()
gradlePluginPortal()
maven { url "https://repo.spring.io/release" }
Expand Down Expand Up @@ -59,3 +67,8 @@ settings.gradle.projectsLoaded {
}
}
}
include 'spring-lxcecho-sample'
include 'spring-lxcecho'
include 'spring-lxcecho-notes'
include 'spring-lxcecho-mvc-sample'

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import javax.annotation.Nullable;

/**
* Spring AIO 调用链中拦截器的内部核心接口,所有类型的切面最终都会包装成此接口触发统一拦截
*
* Intercepts calls on an interface on its way to the target. These
* are nested "on top" of the target.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, Aspect
* @see #isEligibleBean
*/
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
List<String> aspectNames = this.aspectBeanNames; // TODO 这个值是什么时候赋值的???

if (aspectNames == null) {
synchronized (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionR
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {

// InfrastructureAdvisorAutoProxyCreator 父类是 AbstractAutoProxyCreator,主要是开启 AOP,该类不会和 AOP 那样去扫描 @Before 等注解
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

Expand Down Expand Up @@ -120,10 +120,14 @@ private static BeanDefinition registerOrEscalateApcAsRequired(

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

// 优先判断是否存在默认入口类【internalAutoProxyCreator】的 BeanDefinition
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 注册的入口类不是默认入口类
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 查找当前注入接口的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
// 当前入口类对应的优先级,priority 数字越大,优先级越高
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
Expand All @@ -132,6 +136,7 @@ private static BeanDefinition registerOrEscalateApcAsRequired(
return null;
}

// 封装到 Bean Definition 中,并注册到 BeanDefinitionRegistry 中
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// CglibMethodInvocation:把所有信息封装到这里【代理对象、真实对象、增强器链、当前方法、使用的参数】(这里是 FilterChain)
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,27 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// isOptimize:是否对代理进行优化
// isProxyTargetClass:值为 true,使用 CGLib 代理,默认为 false
// hasNoUserSuppliedProxyInterfaces:如果长度为 0,也就是接口为空,返回 false;或 如果接口类型不是 SpringProxy 类型的,返回 false
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // 如果条件不满足:直接走 JDK 动态代理(return)
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果 targetClass 是接口类,使用 JDK 来生成 Proxy
// 如果目标对象实现了接口,默认情况下会采用 JDK 动态代理
// 但也可以通过配置 proxy-target-class=true 强制使用 CGLIB 代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
// JDK Proxy
return new JdkDynamicAopProxy(config);
}
// CGLIB Proxy
return new ObjenesisCglibAopProxy(config);
}
else {
// JDK Proxy
return new JdkDynamicAopProxy(config);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
this.advised = config;
// 获取代理对象需要实现的接口(业务接口和内置接口)
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 判断接口中是否重写了 equals 和 hashCode 方法
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

Expand All @@ -120,6 +122,11 @@ public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
/**
* 参数 1:类加载器(目标类)
* 参数 2:代理类需要实现的接口,即目标类实现的接口(含系统接口)(数组)
* 参数 3:InvocationHandler 本类实现了此接口
*/
return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this);
}

Expand Down Expand Up @@ -189,6 +196,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
Object oldProxy = null;
boolean setProxyContext = false;

// 拿到 targetSource,其中包含被代理的 Bean 对象
TargetSource targetSource = this.advised.targetSource;
Object target = null;

Expand Down Expand Up @@ -224,23 +232,24 @@ else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);

// Get the interception chain for this method.
// Get the interception chain for this method. 从 ProxyFactory(this.advised) 中构建拦截器链,包含了目标方法的所有切面方法
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// Check whether we have any advice. If we don't, we can fall back on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
if (chain.isEmpty()) { // 被代理对象中没有方法可以被增强,直接返回调用方法
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 直接触发反射 method 调用
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// Proceed to the joinpoint through the interceptor chain. 责任链还是调用:ReflectiveMethodInvocation.proceed();
retVal = invocation.proceed();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ public Object getProxy() {
}

/**
* 通过类加载期获取代理
*
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
Expand All @@ -107,6 +109,7 @@ public Object getProxy() {
* @return the proxy object
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
// 分别进入 createAopProxy() getProxy()
return createAopProxy().getProxy(classLoader);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public void setArguments(Object... arguments) {
@Override
@Nullable
public Object proceed() throws Throwable {
// 若所有的增强方法调用完成,则调用被代理方法
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
Expand All @@ -170,17 +171,19 @@ public Object proceed() throws Throwable {
// been evaluated and found to match.
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.matcher().matches(this.method, targetClass, this.arguments)) {
// 有了前面所有 Advice 统一包装成 MethodInterceptor,可以统一调用 invoke() 方法
return dm.interceptor().invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
return proceed(); // 忽略本次调用,路由到下次调用
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// TODO 事务入口拦截器,都会从这里链式调用触发:org.springframework.transaction.interceptor.TransactionInterceptor.invoke()
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
Expand Down
Loading