写在AOP之前
实现MethodInterceptor接口,重写intercept方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
至此,注册了AnnotationAwareAspectJAutoProxyCreator到容器中。
可以看到,AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor后置处理器,并且实现了Ordered接口
它的父类AbstractAutoProxyCreator重写了postProcessBeforeInitialization和postProcessAfterInitialization方法
接下来,在初始化Bean的时候,会调用这个BeanPostProcessor的初始化后处理
然后进到AbstractBeanFactory的getBean()方法,最终进到Bean的初始化方法
调用AbstractAutoProxyCreator的postProcessAfterInitialization方法
获取以上Bean里的所有Advisor,方法和Advisor一对一
方法1获取类里所有的没有@Pointcut注解的Method(可能包含普通的方法),可能是以下几种:
方法2获取以上通知方法的expressionPointcut 切点表达式(普通方法会被过滤掉)
遍历所有的Advisors,是否有任意的Advisors的切点matches(当前的bean)。筛选出所有matches的Advisor
方法1:检查目标对象是否实现了接口,如果是则调用proxyFactory.addInterface(ifc);方法,这样在后面的判断hasNoUserSuppliedProxyInterfaces(config)时就为false
如果否则设置proxyTargetClass属性为true(只有在proxyTargetClass=false的情况下才会进到此方法)
3.可以通过配置文件指定对接口使用CGLIB生成代理(配置proxy-target-class=true)
默认使用JDK自带的Proxy生成代理,碰到以下三种情况例外:
1.ProxyConfig的isOptimize方法为true,这表示让Spring自己去优化而不是用户指定
2.ProxyConfig的isProxyTargetClass方法为true,这表示配置了proxy-target-class="true"
3.ProxyConfig满足hasNoUserSuppliedProxyInterfaces方法执行结果为true,这表示<bean>对象没有实现任何接口或者实现的接口是SpringProxy接口
注:SpringBoot的AOP是自动开启的(spring.aop.auto = true)
可配置spring.aop.proxy-target-class = true强制使用CGLIB动态代理
Proxy.newProxyInstance()方法是执行的关键,有三个参数:
底层实际是调用InvocationHandler.invoke()方法,在这里,也就是调用JdkDynamicAopProxy.invoke()方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
// 如果 expose-proxy 属性为 true,则暴露代理对象
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// 如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal
// 如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
AopContext.setCurrentProxy(oldProxy);
1. 检测 expose-proxy 是否为 true,若为 true,则暴露代理对象
4. 若拦截器链不为空,则创建方法调用器 ReflectiveMethodInvocation 对象
5. 调用 ReflectiveMethodInvocation 对象的 proceed() 方法启动拦截器链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this.methodCache.put(cacheKey, cached);
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
// registry 为 DefaultAdvisorAdapterRegistry 类型
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
* 调用 ClassFilter 对 bean 类型进行匹配,无法匹配则说明当前通知器
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 将 advisor 中的 advice 转成相应的拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
// 若 isRuntime 返回 true,则表明 MethodMatcher 要在运行时做一些检测
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
interceptorList.addAll(Arrays.asList(interceptors));
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
// IntroductionAdvisor 类型的通知器,仅需进行类级别的匹配即可
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
* 若 advice 是 MethodInterceptor 类型的,直接添加到 interceptors 中即可。
* 比如 AspectJAfterAdvice 就实现了 MethodInterceptor 接口
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
* 对于 AspectJMethodBeforeAdvice 等类型的通知,由于没有实现 MethodInterceptor
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
throw new UnknownAdviceTypeException(advisor.getAdvice());
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
2. 若缓存未命中,则调用 getInterceptorsAndDynamicInterceptionAdvice 获取拦截器链
4. 对于 PointcutAdvisor 类型的通知器,这里要调用通知器所持有的切点(Pointcut)对类和方法进行匹配,匹配成功说明应向当前方法织入通知逻辑
5. 调用 getInterceptors 方法对非 MethodInterceptor 类型的通知进行转换(如:@Before @AfterReturning @AfterThrowing)
接下来就是调用 ReflectiveMethodInvocation 对象的 proceed() 方法启动拦截器链
interceptorOrInterceptionAdvice).invoke(this);
这里会先执行一个默认MethodInterceptor的invoke()方法,即ExposeInvocationInterceptor
然后递归调用ReflectiveMethodInvocation.proceed()方法,以@Before前置通知为例:
此时这里调用的是MethodBeforeAdviceInterceptor.invoke()方法
先执行前置通知切面逻辑,然后递归调用下一个拦截器的invoke()方法
https://blog.csdn.net/qq_32331073/article/details/80596084
方法执行的时候,实际上是回调的CglibAopProxy.DynamicAdvisedInterceptor.intercept()方法。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 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);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
1. 检测 expose-proxy 是否为 true,若为 true,则暴露代理对象
3. 如果拦截器链为空并且该方法是public修饰的,则直接通过反射执行目标方法
4. 若拦截器链不为空,则创建方法调用器 CglibMethodInvocation 对象