@ -1,8 +1,9 @@
理论性的文字,我觉得就没必要再扯一遍咯,大道理讲这么多,越听越迷糊。不如直接看源码+注解来的明白痛快。所以话不多说,直接上源码。
理论性的文字,我觉得就没必要再扯一遍咯,大道理讲这么多,越听越迷糊。不如直接看源码+注解来的明白痛快。所以话不多说,直接上源码。
## 1、主要的接口
## 1、主要的接口
#### 1.1、Advice通知
### 1.1、Advice 通知
定义了切面的增强方式,如:前置增强 BeforeAdvice, 后置增强 AfterAdvice, 异常增强 ThrowsAdvice 等。下面看两个主要的子接口的源码。
定义了切面的增强方式,如:前置增强 BeforeAdvice, 后置增强 AfterAdvice, 异常增强 ThrowsAdvice 等。下面看两个主要的子接口的源码。
```java
```java
public interface MethodBeforeAdvice extends BeforeAdvice {
public interface MethodBeforeAdvice extends BeforeAdvice {
@ -22,8 +23,9 @@ public interface AfterReturningAdvice extends AfterAdvice {
}
}
```
```
#### 1.2、Pointcut方法的横切面
### 1.2、Pointcut 方法的横切面
用来定义需要增强的目标方法的集合, 一般使用正则表达式去匹配筛选指定范围内的所有满足条件的目标方法。Pointcut 接口有很多实现,我们主要看一下 JdkRegexpMethodPointcut 和 NameMatchMethodPointcut 的实现原理,前者主要通过正则表达式对方法名进行匹配,后者则通过匹配方法名进行匹配。
用来定义需要增强的目标方法的集合, 一般使用正则表达式去匹配筛选指定范围内的所有满足条件的目标方法。Pointcut 接口有很多实现,我们主要看一下 JdkRegexpMethodPointcut 和 NameMatchMethodPointcut 的实现原理,前者主要通过正则表达式对方法名进行匹配,后者则通过匹配方法名进行匹配。
```java
```java
//JdkRegexpMethodPointcut 的实现源码
//JdkRegexpMethodPointcut 的实现源码
private Pattern[] compiledPatterns = new Pattern[0];
private Pattern[] compiledPatterns = new Pattern[0];
@ -45,8 +47,9 @@ public interface AfterReturningAdvice extends AfterAdvice {
return false;
return false;
}
}
```
```
#### 1.3、Advisor通知器
### 1.3、Advisor 通知器
将 Pointcut 和 Advice 有效地结合在一起。它定义了在哪些方法( Pointcut) 上执行哪些动作( Advice) 。下面看一下 DefaultPointcutAdvisor 的源码实现,它通过持有 Pointcut 和 Advice 属性来将两者有效地结合在一起。
将 Pointcut 和 Advice 有效地结合在一起。它定义了在哪些方法( Pointcut) 上执行哪些动作( Advice) 。下面看一下 DefaultPointcutAdvisor 的源码实现,它通过持有 Pointcut 和 Advice 属性来将两者有效地结合在一起。
```java
```java
public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {
public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {
@ -90,9 +93,12 @@ public abstract class AbstractGenericPointcutAdvisor extends AbstractPointcutAdv
```
```
## 2、spring AOP 的设计与实现
## 2、spring AOP 的设计与实现
AOP 的实现代码中,主要使用了 JDK 动态代理,在特定场景下(被代理对象无 implements 的接口)也用到了 CGLIB 生成代理对象。通过 AOP 的源码设计可以看到,其先为目标对象建立了代理对象,这个代理对象的生成可以使用 JDK 动态代理或 CGLIB 完成。然后启动为代理对象配置的拦截器,对横切面(目标方法集合)进行相应的增强,将 AOP 的横切面设计和 Proxy 模式有机地结合起来,实现了在 AOP 中定义好的各种织入方式。
AOP 的实现代码中,主要使用了 JDK 动态代理,在特定场景下(被代理对象无 implements 的接口)也用到了 CGLIB 生成代理对象。通过 AOP 的源码设计可以看到,其先为目标对象建立了代理对象,这个代理对象的生成可以使用 JDK 动态代理或 CGLIB 完成。然后启动为代理对象配置的拦截器,对横切面(目标方法集合)进行相应的增强,将 AOP 的横切面设计和 Proxy 模式有机地结合起来,实现了在 AOP 中定义好的各种织入方式。
#### 2.1、ProxyFactoryBean
### 2.1、ProxyFactoryBean
这里我们主要以 ProxyFactoryBean 的实现为例,对 AOP 的实现原理进行分析。ProxyFactoryBean 主要持有目标对象 target 的代理对象 aopProxy, 和 Advisor 通知器,而 Advisor 持有 Advice 和 Pointcut, 这样就可以判断 aopProxy 中的方法 是否是某个指定的切面 Pointcut, 然后根据其配置的织入方向( 前置增强/后置增强),通过反射为其织入相应的增强行为 Advice。
这里我们主要以 ProxyFactoryBean 的实现为例,对 AOP 的实现原理进行分析。ProxyFactoryBean 主要持有目标对象 target 的代理对象 aopProxy, 和 Advisor 通知器,而 Advisor 持有 Advice 和 Pointcut, 这样就可以判断 aopProxy 中的方法 是否是某个指定的切面 Pointcut, 然后根据其配置的织入方向( 前置增强/后置增强),通过反射为其织入相应的增强行为 Advice。
先看一下 ProxyFactoryBean 的配置和使用。
先看一下 ProxyFactoryBean 的配置和使用。
```xml
```xml
<!-- 定义自己的 Advisor 实现,其中包含了 Pointcut 和 Advice -->
<!-- 定义自己的 Advisor 实现,其中包含了 Pointcut 和 Advice -->
< bean id = "myAdvisor" class = "com.shuitu.MyAdvisor" / >
< bean id = "myAdvisor" class = "com.shuitu.MyAdvisor" / >
@ -110,8 +116,9 @@ AOP的实现代码中, 主要使用了JDK动态代理, 在特定场景下(
< / property >
< / property >
< / bean >
< / bean >
```
```
#### 2.2、ProxyFactoryBean为配置的target生成AopProxy代理对象
### 2.2、ProxyFactoryBean 为配置的 target 生成 AopProxy 代理对象
ProxyFactoryBean 的 getObject() 方法先对通知器链进行了初始化,然后根据被代理对象类型的不同,生成代理对象。
ProxyFactoryBean 的 getObject() 方法先对通知器链进行了初始化,然后根据被代理对象类型的不同,生成代理对象。
```java
```java
/**
/**
* 返回一个代理对象,当用户从 FactoryBean 中获取 bean 时调用,
* 返回一个代理对象,当用户从 FactoryBean 中获取 bean 时调用,
@ -133,7 +140,8 @@ ProxyFactoryBean的getObject()方法先对通知器链进行了初始化,然
}
}
}
}
```
```
#### 2.3、initializeAdvisorChain()初始化Advisor链
### 2.3、initializeAdvisorChain() 初始化 Advisor 链
```java
```java
/**
/**
* 初始化 Advisor 链,可以发现,其中有通过对 IoC 容器的 getBean() 方法的调用来获取配置好的 advisor 通知器
* 初始化 Advisor 链,可以发现,其中有通过对 IoC 容器的 getBean() 方法的调用来获取配置好的 advisor 通知器
@ -194,7 +202,8 @@ ProxyFactoryBean的getObject()方法先对通知器链进行了初始化,然
}
}
```
```
生成 singleton 的代理对象在 getSingletonInstance 方法中完成,这是 ProxyFactoryBean 生成 AopProxy 代理对象的调用入口。代理对象会封装对 target 对象的调用,针对 target 对象的方法调用会被这里生成的代理对象所拦截。
生成 singleton 的代理对象在 getSingletonInstance 方法中完成,这是 ProxyFactoryBean 生成 AopProxy 代理对象的调用入口。代理对象会封装对 target 对象的调用,针对 target 对象的方法调用会被这里生成的代理对象所拦截。
#### 2.4、getSingletonInstance()生成单例代理对象
### 2.4、getSingletonInstance() 生成单例代理对象
```java
```java
/**
/**
* 返回此类代理对象的单例实例,如果尚未创建该实例,则使用单例模式的懒汉式 创建它
* 返回此类代理对象的单例实例,如果尚未创建该实例,则使用单例模式的懒汉式 创建它
@ -225,7 +234,9 @@ ProxyFactoryBean的getObject()方法先对通知器链进行了初始化,然
return aopProxy.getProxy(this.proxyClassLoader);
return aopProxy.getProxy(this.proxyClassLoader);
}
}
```
```
上面的 createAopProxy() 方法,调用了 ProxyFactoryBean 的父类 ProxyCreatorSupport 中的实现。
上面的 createAopProxy() 方法,调用了 ProxyFactoryBean 的父类 ProxyCreatorSupport 中的实现。
```java
```java
public class ProxyCreatorSupport extends AdvisedSupport {
public class ProxyCreatorSupport extends AdvisedSupport {
@ -255,7 +266,9 @@ public class ProxyCreatorSupport extends AdvisedSupport {
}
}
```
```
下面看一下 AopProxyFactory 接口的实现类 DefaultAopProxyFactory 的代码。
下面看一下 AopProxyFactory 接口的实现类 DefaultAopProxyFactory 的代码。
```java
```java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//AopProxy 代理对象的生成过程:
//AopProxy 代理对象的生成过程:
@ -283,8 +296,10 @@ public class ProxyCreatorSupport extends AdvisedSupport {
}
}
}
}
```
```
可以看到其根据目标对象是否实现了接口,而决定是使用 JDK 动态代理还是 CGLIB 去生成代理对象,而 AopProxy 接口的实现类也只有 JdkDynamicAopProxy 和 CglibAopProxy 这两个。
可以看到其根据目标对象是否实现了接口,而决定是使用 JDK 动态代理还是 CGLIB 去生成代理对象,而 AopProxy 接口的实现类也只有 JdkDynamicAopProxy 和 CglibAopProxy 这两个。
#### 2.5、JDK生成AopProxy代理对象
### 2.5、JDK 生成 AopProxy 代理对象
```java
```java
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@ -316,8 +331,10 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
}
}
}
}
```
```
通过 JdkDynamicAopProxy 的源码可以非常清楚地看到,其使用了 JDK 动态代理的方式生成了代理对象。JdkDynamicAopProxy 实现了 InvocationHandler 接口,并通过 Proxy.newProxyInstance() 方法生成代理对象并返回。
通过 JdkDynamicAopProxy 的源码可以非常清楚地看到,其使用了 JDK 动态代理的方式生成了代理对象。JdkDynamicAopProxy 实现了 InvocationHandler 接口,并通过 Proxy.newProxyInstance() 方法生成代理对象并返回。
#### 2.6、CGLIB生成AopProxy代理对象( CglibAopProxy)
### 2.6、CGLIB 生成 AopProxy 代理对象( CglibAopProxy)
```java
```java
public Object getProxy(ClassLoader classLoader) {
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
if (logger.isDebugEnabled()) {
@ -397,7 +414,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
## 3、spring AOP 拦截器调用的实现
## 3、spring AOP 拦截器调用的实现
在 spring AOP 通过 JDK 的 Proxy 类生成代理对象时,相关的拦截器已经配置到了代理对象持有的 InvocationHandler(即, ProxyBeanFactory) 的 invoke() 方法中,拦截器最后起作用,是通过调用代理对象的目标方法时,在代理类中触发了 InvocationHandler 的 invoke() 回调。通过 CGLIB 实现的 AOP, 原理与此相似。
在 spring AOP 通过 JDK 的 Proxy 类生成代理对象时,相关的拦截器已经配置到了代理对象持有的 InvocationHandler(即, ProxyBeanFactory) 的 invoke() 方法中,拦截器最后起作用,是通过调用代理对象的目标方法时,在代理类中触发了 InvocationHandler 的 invoke() 回调。通过 CGLIB 实现的 AOP, 原理与此相似。
#### 3.1、JdkDynamicAopProxy的invoke()拦截
### 3.1、JdkDynamicAopProxy 的 invoke() 拦截
前面已经通过两种不同的方式生成了 AopProxy 代理对象,下面我们先看一下 JdkDynamicAopProxy 中的 invoke() 回调方法中对拦截器调用的实现。
前面已经通过两种不同的方式生成了 AopProxy 代理对象,下面我们先看一下 JdkDynamicAopProxy 中的 invoke() 回调方法中对拦截器调用的实现。
```java
```java
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
@ -479,8 +497,9 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
}
}
}
}
```
```
#### 3.2、CglibAopProxy的intercept()拦截
### 3.2、CglibAopProxy 的 intercept() 拦截
CglibAopProxy 的 intercept() 回调方法实现和 JdkDynamicAopProxy 的 invoke() 非常相似,只是在 CglibAopProxy 中构造 CglibMethodInvocation 对象来完成拦截器链的调用,而在 JdkDynamicAopProxy 中则是通过构造 ReflectiveMethodInvocation 对象来完成的。
CglibAopProxy 的 intercept() 回调方法实现和 JdkDynamicAopProxy 的 invoke() 非常相似,只是在 CglibAopProxy 中构造 CglibMethodInvocation 对象来完成拦截器链的调用,而在 JdkDynamicAopProxy 中则是通过构造 ReflectiveMethodInvocation 对象来完成的。
```java
```java
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
Object oldProxy = null;
@ -524,8 +543,9 @@ CglibAopProxy的intercept()回调方法实现和JdkDynamicAopProxy的invoke()非
}
}
}
}
```
```
#### 3.3、目标对象中目标方法的调用
### 3.3、目标对象中目标方法的调用
对目标对象中目标方法的调用,是在 AopUtils 工具类中利用反射机制完成的。具体代码如下:
对目标对象中目标方法的调用,是在 AopUtils 工具类中利用反射机制完成的。具体代码如下:
```java
```java
public abstract class AopUtils {
public abstract class AopUtils {
@ -554,8 +574,9 @@ public abstract class AopUtils {
}
}
}
}
```
```
#### 3.4、AOP拦截器链的调用
### 3.4、AOP 拦截器链的调用
JdkDynamicAopProxy 和 CglibAopProxy 虽然使用了不同的代理对象,但对 AOP 拦截的处理却是相同的,都是通过 ReflectiveMethodInvocation 的 proceed() 方法实现的。
JdkDynamicAopProxy 和 CglibAopProxy 虽然使用了不同的代理对象,但对 AOP 拦截的处理却是相同的,都是通过 ReflectiveMethodInvocation 的 proceed() 方法实现的。
```java
```java
public Object proceed() throws Throwable {
public Object proceed() throws Throwable {
//从拦截器链中按顺序依次调用拦截器,直到所有的拦截器调用完毕,开始调用目标方法,
//从拦截器链中按顺序依次调用拦截器,直到所有的拦截器调用完毕,开始调用目标方法,
@ -591,7 +612,7 @@ JdkDynamicAopProxy和CglibAopProxy虽然使用了不同的代理对象, 但对A
}
}
}
}
```
```
#### 3.5、配置通知器
### 3.5、配置通知器
AdvisedSupport 中实现了获取拦截器链的方法,并使用了缓存。
AdvisedSupport 中实现了获取拦截器链的方法,并使用了缓存。
```java
```java
/**
/**
@ -612,7 +633,9 @@ AdvisedSupport中实现了获取拦截器链的方法, 并使用了缓存。
return cached;
return cached;
}
}
```
```
获取拦截器链的工作是由 AdvisorChainFactory 完成的,他是一个拦截器链的生成工厂。由于 AdvisorChainFactory 接口只有一个实现类 DefaultAdvisorChainFactory, 所以我们直接看这个类中的实现就行咯。
获取拦截器链的工作是由 AdvisorChainFactory 完成的,他是一个拦截器链的生成工厂。由于 AdvisorChainFactory 接口只有一个实现类 DefaultAdvisorChainFactory, 所以我们直接看这个类中的实现就行咯。
```java
```java
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
@ -684,7 +707,9 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
}
}
```
```
这里的 advisor 通知器是从 AdvisedSupport 中获取的,而 advisor 的初始化则是在 ProxyFactoryBean 的 getObject() 方法中完成的。
这里的 advisor 通知器是从 AdvisedSupport 中获取的,而 advisor 的初始化则是在 ProxyFactoryBean 的 getObject() 方法中完成的。
```java
```java
/**
/**
* 返回一个代理对象,当用户从 FactoryBean 中获取 bean 时调用,
* 返回一个代理对象,当用户从 FactoryBean 中获取 bean 时调用,
@ -766,9 +791,12 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
this.advisorChainInitialized = true;
this.advisorChainInitialized = true;
}
}
```
```
注意, Advisor 本身就被配置为 bean, 所以它的获取也是通过 IoC 容器获得的。
注意, Advisor 本身就被配置为 bean, 所以它的获取也是通过 IoC 容器获得的。
#### 3.6、Advice通知的实现
### 3.6、Advice 通知的实现
从 DefaultAdvisorChainFactory 类中的 getInterceptorsAndDynamicInterceptionAdvice() 方法我们可以看到,其通过 AdvisorAdapterRegistry 实例对象的 getInterceptors() 方法,利用配置的 advisor 完成了对拦截器的适配和注册。
从 DefaultAdvisorChainFactory 类中的 getInterceptorsAndDynamicInterceptionAdvice() 方法我们可以看到,其通过 AdvisorAdapterRegistry 实例对象的 getInterceptors() 方法,利用配置的 advisor 完成了对拦截器的适配和注册。
```java
```java
public List< Object > getInterceptorsAndDynamicInterceptionAdvice(
public List< Object > getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class targetClass) {
Advised config, Method method, Class targetClass) {
@ -820,7 +848,9 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
return interceptorList;
return interceptorList;
}
}
```
```
DefaultAdvisorAdapterRegistry 的 getInterceptors() 方法封装了 advice 织入实现的入口。
DefaultAdvisorAdapterRegistry 的 getInterceptors() 方法封装了 advice 织入实现的入口。
```java
```java
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
@ -886,7 +916,10 @@ public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Se
}
}
}
}
```
```
从DefaultAdvisorAdapterRegistry的实现中可以看到, 其使用了一系列的AdviceAdapter适配器, 如: MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter, 它们完全和advice的类型一一对应, 它们都是实现了AdviceAdapter接口的同一层次类, 各自承担着不同的适配任务, 一对一地服务于不同的advice实现。下面我们以MethodBeforeAdviceAdapter为例, 看一下其源码实现。
从 DefaultAdvisorAdapterRegistry 的实现中可以看到,其使用了一系列的 AdviceAdapter 适配器, 如: MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter, 它们完全和 advice 的类型
一一对应,它们都是实现了 AdviceAdapter 接口的同一层次类,各自承担着不同的适配任务,一对一地服务于不同的 advice 实现。下面我们以 MethodBeforeAdviceAdapter 为例,看一下其源码实现。
```java
```java
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@ -901,7 +934,9 @@ class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
}
}
```
```
可以看到,其中的 getInterceptor() 方法把 advice 从 advisor 中取出来,然后创建了一个 MethodBeforeAdviceInterceptor 对象,并返回,这个对象中持有对 advice 的引用。下面我们看一下 MethodBeforeAdviceInterceptor 拦截器的源码实现。
可以看到,其中的 getInterceptor() 方法把 advice 从 advisor 中取出来,然后创建了一个 MethodBeforeAdviceInterceptor 对象,并返回,这个对象中持有对 advice 的引用。下面我们看一下 MethodBeforeAdviceInterceptor 拦截器的源码实现。
```java
```java
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
@ -927,11 +962,10 @@ public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Seriali
}
}
```
```
可以看到, MethodBeforeAdviceInterceptor 的 invoke() 方法先是触发了 advice 的 before() 方法,然后才是 MethodInvocation 的 proceed() 方法调用。
可以看到, MethodBeforeAdviceInterceptor 的 invoke() 方法先是触发了 advice 的 before() 方法,然后才是 MethodInvocation 的 proceed() 方法调用。
回顾一下之前的代码,在 AopProxy 代理对象触发的 ReflectiveMethodInvocation 的 proceed() 中,在取得拦截器 interceptor 后调用了其 invoke() 方法。按照 AOP 的配置规则, ReflectiveMethodInvocation 触发的拦截器 invoke() 回调,最终会根据 advice 类型的不同,触发 spring 对不同的 advice 的拦截器封装,比如 MethodBeforeAdvice 最终会触发 MethodBeforeAdviceInterceptor 的 invoke() 回调,其它两个以此类推,这里就不逐一分析咯。
回顾一下之前的代码,在 AopProxy 代理对象触发的 ReflectiveMethodInvocation 的 proceed() 中,在取得拦截器 interceptor 后调用了其 invoke() 方法。按照 AOP 的配置规则, ReflectiveMethodInvocation 触发的拦截器 invoke() 回调,最终会根据 advice 类型的不同,触发 spring 对不同的 advice 的拦截器封装,比如 MethodBeforeAdvice 最终会触发 MethodBeforeAdviceInterceptor 的 invoke() 回调,其它两个以此类推,这里就不逐一分析咯。
另外, 可以结合我GitHub上对spring框架源码的阅读及个人理解一起看, 会更有助于各位开发大佬理解, 如果对你们有帮助的, 还望各位老爷watch, star, fork, 素质三连一波, 地址:
另外,可以结合我 GitHub 上对 spring 框架源码的阅读及个人理解一起看,会更有助于各位开发大佬理解,如果对你们有帮助的,还望各位老爷 watch, star, fork, 素质三连一波, 地址: https://github.com/AmyliaY/spring-aop-reading
spring-aop-reading https://github.com/AmyliaY/spring-aop-reading