一些概念
- Advice:一段具体的切面逻辑,例如:目标方法执行前需要执行的那段代码就是
advice
- Advisor:它内部需要指定一个
Advice
,Advisor
决定该拦截哪些方法,拦截后需要完成的工作还是内部的Advice
来做 - Pointcut:切入点,用于定义哪些方法需要被增强或者说需要被拦截
- Aspect:一般会定义一堆
Pointcut
- Joinpoint:一般作为
advice
的第一个参数
加载
在Bean加载完成之后,执行完org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
之后,会执行后置处理器BeanPostProcessors
(org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
),在后置处理器中有AbstractAutoProxyCreator
来判断当前Bean是否有切面,如果有切面的话,就会创建一个代理对象并返回。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 如果存在切面则创建一个代理对象返回
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
getAdvicesAndAdvisorsForBean
中寻找advisor
的逻辑
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 寻找候选的advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 寻找可用的advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 对advisor进行排序(按照order 默认order为Integer.MAX_VALUE)
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
findCandidateAdvisors
中分为了两步获取advisor
- 寻找所有实现了
Advisor
接口的advisor
,其中 - 寻找所有被
@AspectJ
注解标记的advisor
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
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;
}
其中TransactionAttributeSourceAdvisor
就是实现了Advisor
接口,内部有一个TransactionInterceptor
,会通过getAdvice()
返回,因此在后续的advisor
将会使用TransactionInterceptor
来进行切入。
buildAspectJAdvisors()的逻辑主要是寻找所有@AspectJ的Bean,其中org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#aspectBeanNames
为:所有的@AspectJ标记的Bean
aspectBeanNames的判断逻辑
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
中的this.advisorFactory.isAspect(beanType)
进行判断
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
private boolean compiledByAjc(Class<?> clazz) {
// The AJTypeSystem goes to great lengths to provide a uniform appearance between code-style and
// annotation-style aspects. Therefore there is no 'clean' way to tell them apart. Here we rely on
// an implementation detail of the AspectJ compiler.
// AJC_MAGIC = "ajc$";
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().startsWith(AJC_MAGIC)) {
return true;
}
}
return false;
}
可以看到会把类中有Aspect注解的类加入到Advisor中
寻找可用的advisors
org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
遍历类中的所有方法,逐个匹配切入点(pointCut
)
advisors排序
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#sortAdvisors
对advisors进行排序
org.springframework.core.annotation.AnnotationAwareOrderComparator
为advisors的比较器,通过findOrder()提供切面中的order值。
public int compare(Advisor o1, Advisor o2) {
int advisorPrecedence = this.advisorComparator.compare(o1, o2);
if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
}
return advisorPrecedence;
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
org.springframework.core.annotation.AnnotationAwareOrderComparator#findOrder
protected Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
return findOrderFromAnnotation(obj);
}
根据order的大小排,大的优先级低,小的优先级高。
执行
生成的代理类基本都是DynamicAdvisedInterceptor
类型,DynamicAdvisedInterceptor
是CglibAopProxy
的子。
因此会执行到org.springframework.aop.framework.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);
// chain中存储了需要进行调用的切面,其顺序是按照类中的order进行排序
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() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
// 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 = invokeMethod(target, method, argsToUse, methodProxy);
}
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);
}
}
}
接着进入org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
方法
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// proceed方法会循环调用,直到interceptorsAndDynamicMethodMatchers中的所有切面都执行完
// currentInterceptorIndex 为当前调用的第几个切面
// interceptorsAndDynamicMethodMatchers为所有切面
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 每调用一次interceptorsAndDynamicMethodMatchers会加1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 是否是动态生成的Interceptor,通过@AspecJ注解标记的切面都是这种类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
第一个执行的是ExposeInvocationInterceptor
,这个是spring
默认的,通过threadlocal
来记录方法调用的全链路。
ExposeInvocationInterceptor
内部invoke
方法比较简单
public Object invoke(MethodInvocation mi) throws Throwable {
// invocation 为 thread local
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
以@Around
为例,对于动态生成的切面会执行到此处org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint#proceed(java.lang.Object[])
public Object proceed(Object[] arguments) throws Throwable {
Assert.notNull(arguments, "Argument array passed to proceed cannot be null");
if (arguments.length != this.methodInvocation.getArguments().length) {
throw new IllegalArgumentException("Expecting " +
this.methodInvocation.getArguments().length + " arguments to proceed, " +
"but was passed " + arguments.length + " arguments");
}
this.methodInvocation.setArguments(arguments);
// 在执行完invocableClone之后会继续调用proceed()方法,因此会回到前面循环,执行下一个切面
return this.methodInvocation.invocableClone(arguments).proceed();
}
org.springframework.aop.framework.ReflectiveMethodInvocation#invocableClone(java.lang.Object...)
内部逻辑如下,可以看到通过系统调用对当前对象尽行了一次clone
,然后把当前的ReflectiveMethodInvocation
返回,所以可以继续执行proceed()
public MethodInvocation invocableClone(Object... arguments) {
// Force initialization of the user attributes Map,
// for having a shared Map reference in the clone.
if (this.userAttributes == null) {
this.userAttributes = new HashMap<>();
}
// Create the MethodInvocation clone.
try {
// clone() 为系统调用
ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone();
clone.arguments = arguments;
return clone;
}
catch (CloneNotSupportedException ex) {
throw new IllegalStateException(
"Should be able to clone object of type [" + getClass() + "]: " + ex);
}
}
所有切面执行完,最后调用目标方法org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#invokeJoinpoint
,执行完目标方法返回结果。