Spring AOP的原理
1、创建代理对象
在上一篇文章(Spring AOP的原理(上))中已经分析了创建并获取适配当前bean的增强器,如果在匹配切面的过程中,发现适配的切面,那就需要创建代理对象了。
本文接下来分析AbstractAutoProxyCreator的postProcessAfterInitialization方法:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
调用AbstractAutoProxyCreator的wrapIfNecessary方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//根据bean获取对应的切面信息,如果不为空,则为该bean创建代理对象
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
// protected static final Object[] DO_NOT_PROXY = null;
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建bean的代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理对象给spring容器,spring容器中是bean的代理对象
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
//返回bean本身给spring容器,而不是代理对象
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
//返回bean本身给spring容器,而不是代理对象
return bean;
}
}
创建完的代理对象中有如下信息:
调用AbstractAutoProxyCreator的createProxy方法,设置ProxyFactory创建Proxy需要的一切信息:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
}
//新建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//设置工厂代理类
if (!proxyFactory.isProxyTargetClass()) {
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//设置拦截切面
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
//设置被代理对象(目标对象),目标对象被封装到SingletonTargetSource中了
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
ClassLoader classLoader = this.getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader)classLoader).getOriginalClassLoader();
}
//创建代理对象
return proxyFactory.getProxy(classLoader);
}
调用ProxyFactory的getProxy方法:
public Object getProxy(@Nullable ClassLoader classLoader) {
//先创建AopProxy代理,再获取代理对象。根据目标类是否是接口,AopProxy有jdk动态代理和cglib动态代理
return this.createAopProxy().getProxy(classLoader);
}
调用ProxyCreatorSupport类的createAopProxy方法:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
调用DefaultAopProxyFactory类的createAopProxy方法创建jdk代理或cglib代理:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
//如果目标类是接口,则创建jdk动态代理,否则创建cglib动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
1.1、通过jdk动态代理创建代理对象
先分析jdk动态代理获取代理对象的源码,接着上面的getProxy方法获取代理对象继续分析。
JdkDynamicAopProxy实现InvocationHandler接口,必然重写invoke方法,通过代理对象调用重写后的目标方法时,就会调用此处重写的invoke方法,在invoke方法中对目标方法进行增强。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//创建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
//在上面创建代理对象时,已通过代理工厂proxyFactory.setTargetSource(targetSource);将封装目标对象的targetSource保存到AdvisedSupport的targetSource属性了,此处就是获取该属性的值
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
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);
//1、将增强器转换为方法拦截器
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果拦截器链为空,说明没有真实的增强(advice),仅仅通过反射调用被代理方法
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
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);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
//将拦截器链chain作为一个参数用于创建MethodInvocation对象,invocation.proceed()中就从chain中依次获取拦截器调用invoke方法
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//2、通过拦截器链调用连接点joinpoint(即目标方法),对目标方法进行增强
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
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);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
1.1.1、将增强器转换为方法拦截器
下面先分析将增强器转换为方法拦截器的getInterceptorsAndDynamicInterceptionAdvice方法。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
调用DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
//根据增强器获取拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
根据增强器获取拦截器,调用DefaultAdvisorAdapterRegistry的getInterceptors方法。
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
//如果增强器实现了MethodInterceptor接口,则直接转成拦截器,如AspectJAfterAdvice、AspectJAroundAdvice 和AspectJAfterThrowingAdvice
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
//根据增强器适配器创建拦截器,如AspectJMethodBeforeAdvice和AspectJAfterReturningAdvice
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
看一下适配器MethodBeforeAdviceAdapter的getInterceptor方法。
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
//根据增强器创建拦截器
return new MethodBeforeAdviceInterceptor(advice);
}
}
下面就是MethodBeforeAdviceInterceptor拦截器的源码。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
//持有增强器的引用,增强器作为拦截器的一个实例变量
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
//在拦截器的invoke方法中会调用增强器的增强方法,同时会调用ReflectiveMethodInvocation的proceed方法来调用目标方法
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//调用增强器的增强方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//调用ReflectiveMethodInvocation的proceed方法来调用目标方法
return mi.proceed();
}
}
至此,将增强器转成拦截器的方法逻辑分析完毕。
1.1.2、根据拦截器对目标方法进行增强
现在回过头来再分析ReflectiveMethodInvocation的proceed方法。
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// currentInterceptorIndex的初始值为-1,如果该值等于拦截器数组长度减1,说明没有拦截器了,则调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//通过反射调用目标对象target的目标方法,method.invoke(target, args);
return invokeJoinpoint();
}
//让currentInterceptorIndex自增,获取拦截器数组中的拦截器。拦截器数组是在创建MethodInvocation对象时,通过参数chain拦截器链传进来的。
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
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.
//调用具体拦截器(实现了MethodInterceptor接口)的invoke方法,在invoke方法中会调用增强器的增强方法,
//同时会调用ReflectiveMethodInvocation的proceed方法来调用目标方法,如AspectJAfterAdvice,既是一个增强器,也是一个拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
拓展:下面分析@After、@AfterReturning、@Before、@Around等增强方法的原理。
此处以AspectJAfterAdvice的invoke方法为例,AspectJAfterAdvice是@After增强方法对应的增强器,实现了org.aopalliance.intercept.MethodInterceptor接口,因此,AspectJAfterAdvice既是一个增强器,也是一个拦截器。假如切面类中只有一个增强方法,且是@After注解的方法,则拦截器数组中只有一个拦截器,即AspectJAfterAdvice,拦截器数组的长度为1。在上面第一次调用ReflectiveMethodInvocation的proceed方法时,currentInterceptorIndex的值为-1,不等于拦截器数组长度减1,所以获取拦截器数组中第一个拦截器,也是唯一的一个拦截器,即AspectJAfterAdvice,接着调用AspectJAfterAdvice的invoke方法,即下面这个invoke方法。在invoke方法中又调用了ReflectiveMethodInvocation的proceed方法,此时currentInterceptorIndex的值为0,等于拦截器数组长度减1,所以调用目标方法。由于增强方法是放在finally中的,所以无论目标方法是否能够成功返回,都会执行增强方法。这就是@After注解的方法一定会执行的原因。
注意此处的MethodInterceptor接口是org.aopalliance.intercept包下的。
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了
return mi.proceed();
}
finally {
//调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
在抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法中会调用invokeAdviceMethodWithGivenArgs方法,在该方法中通过反射调用切面类中的增强方法,如下所示:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
// aspectJAdviceMethod是切面类中的增强方法,aspectInstanceFactory.getAspectInstance()是从spring容器中获取切面类对象,通过反射调用切面类中的增强方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
@AfterReturning注解的增强方法对应的增强器是AfterReturningAdvice ,增强器转换之后的拦截器是AfterReturningAdviceInterceptor,同样实现了MethodInterceptor接口,在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量,其invoke方法如下所示。
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
//在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量
private final AfterReturningAdvice advice;
/**
* Create a new AfterReturningAdviceInterceptor for the given advice.
* @param advice the AfterReturningAdvice to wrap
*/
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了
Object retVal = mi.proceed();
//调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
@Before注解的增强方法对应的增强器是AspectJMethodBeforeAdvice,同样继承了抽象父类AbstractAspectJAdvice,另外实现了MethodBeforeAdvice接口。增强器转换之后的拦截器是MethodBeforeAdviceInterceptor,同样实现了MethodInterceptor接口,在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量,其invoke方法如下所示。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
//在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了
return mi.proceed();
}
}
对于@Around注解的增强方法,一般通过如下的方式进行使用,需要在环绕通知之间调用ProceedingJoinPoint的proceed()方法,在该方法中最终会调用目标方法。这是环绕通知与其他四种通知不一样的地方,需要手动调用ProceedingJoinPoint的proceed()方法来调用目标方法,而其他四种通知不需要手动调用目标方法。下面分析一下@Around增强方法的原理。
@Around(value="execution表达式" )
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
//获取目标方法的参数
String name="";
Object args[] = pjp.getArgs();
if(args!=null && args.length>1){
Object arg=args[0];
name = (String) arg;
}
//实现环绕通知
Object result = null;
System.out.println("环绕通知:在目标方法之前执行,比如开启事务");
if("倚天照海".equals(name)){//可以控制目标方法的执行
result = pjp.proceed(); //执行目标方法
}
System.out.println("环绕通知:在目标方法之后执行,比如提交或回滚事务");
//返回目标方法执行的结果,可以修改目标方法的执行结果,影响目标方法的返回值
return result+"ddd";
}
@Around注解的增强方法对应的增强器是AspectJAroundAdvice,同样继承了抽象父类AbstractAspectJAdvice,另外实现了MethodInterceptor接口,说明AspectJAroundAdvice既是一个增强器,也是一个拦截器。其invoke方法如下所示。
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
public AspectJAroundAdvice(
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJAroundAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return false;
}
@Override
protected boolean supportsProceedingJoinPoint() {
return true;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
//调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
/**
* Return the ProceedingJoinPoint for the current invocation,
* instantiating it lazily if it hasn't been bound to the thread already.
* @param rmi the current Spring AOP ReflectiveMethodInvocation,
* which we'll use for attribute binding
* @return the ProceedingJoinPoint to make available to advice methods
*/
protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
return new MethodInvocationProceedingJoinPoint(rmi);
}
}
通过增强器AspectJAroundAdvice的invoke源码可知,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法,在@Around注解的增强方法中会调用ProceedingJoinPoint的proceed()方法(这是程序员手动调用的),通过proceed方法调用目标方法。由上面的增强器AspectJAroundAdvice的源码可知,是通过MethodInvocationProceedingJoinPoint创建的ProceedingJoinPoint,它的proceed方法如下所示。
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
private final ProxyMethodInvocation methodInvocation;
//省略了其他属性和方法
/**
* Create a new MethodInvocationProceedingJoinPoint, wrapping the given
* Spring ProxyMethodInvocation object.
* @param methodInvocation the Spring ProxyMethodInvocation object
*/
public MethodInvocationProceedingJoinPoint(ProxyMethodInvocation methodInvocation) {
Assert.notNull(methodInvocation, "MethodInvocation must not be null");
this.methodInvocation = methodInvocation;
}
@Override
public Object proceed() throws Throwable {
//调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了,
//在proceed方法中会调用目标方法,这就是在@Around增强方法中通过proceed方法调用目标方法的原理
return this.methodInvocation.invocableClone().proceed();
}
@Override
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);
return this.methodInvocation.invocableClone(arguments).proceed();
}
}
1.2、通过cglib动态代理创建代理对象
1.2.1、创建代理对象
下面分析cglib动态代理获取代理对象的源码,接着上面的getProxy方法继续分析:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
int x;
if (rootClass.getName().contains("$$")) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
Class[] var5 = additionalInterfaces;
int var6 = additionalInterfaces.length;
for(x = 0; x < var6; ++x) {
Class<?> additionalInterface = var5[x];
this.advised.addInterface(additionalInterface);
}
}
this.validateClassIfNecessary(proxySuperClass, classLoader);
//Enhancer是CGLIB的字节码增强器,可以很方便的对类进行拓展
Enhancer enhancer = this.createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
//获取拦截回调函数,普通AOP采用的回调函数是Callback aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
Callback[] callbacks = this.getCallbacks(rootClass);
Class<?>[] types = new Class[callbacks.length];
for(x = 0; x < types.length; ++x) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//创建代理对象
return this.createProxyClassAndInstance(enhancer, callbacks);
} catch (IllegalArgumentException | CodeGenerationException var9) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", var9);
} catch (Throwable var10) {
throw new AopConfigException("Unexpected AOP exception", var10);
}
}
调用CglibAopProxy类的getCallbacks方法获取拦截器数组:
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// DynamicAdvisedInterceptor 是CglibAopProxy类中的私有静态内部类,实现了MethodInterceptor 接口
Callback aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
Object targetInterceptor;
if (exposeProxy) {
targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
} else {
targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedInterceptor(this.advised.getTargetSource());
}
Callback targetDispatcher = isStatic ? new CglibAopProxy.StaticDispatcher(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.SerializableNoOp();
Callback[] mainCallbacks = new Callback[]{aopInterceptor, (Callback)targetInterceptor, new CglibAopProxy.SerializableNoOp(), (Callback)targetDispatcher, this.advisedDispatcher, new CglibAopProxy.EqualsInterceptor(this.advised), new CglibAopProxy.HashCodeInterceptor(this.advised)};
Callback[] callbacks;
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);
for(int x = 0; x < methods.length; ++x) {
Method method = methods[x];
//将增强器转换为方法拦截器
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new CglibAopProxy.FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
} else {
callbacks = mainCallbacks;
}
return callbacks;
}
创建代理对象:
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
//为代理类设置回调对象,即方法拦截器,在代理对象重写的目标方法中会调用拦截器的intercept方法
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
至此,通过cglib创建代理对象的代码就结束了。
1.2.2、代理对象调用重写的目标方法
DynamicAdvisedInterceptor是CglibAopProxy的静态内部类,通过cglib动态代理创建代理对象之后,在代理对象的重写的目标方法中会调用DynamicAdvisedInterceptor的intercept方法。下面看一下DynamicAdvisedInterceptor类的源码:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
//重写MethodInterceptor接口中的intercept方法
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
//在上面创建代理对象时,已通过代理工厂proxyFactory.setTargetSource(targetSource);
//将封装目标对象的targetSource保存到AdvisedSupport的targetSource属性了,此处就是获取该属性的值
TargetSource targetSource = this.advised.getTargetSource();
Object var16;
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
//将增强器转换为方法拦截器(如果在一个类的public方法上使用@Transactional注解,在创建该类的bean实例时,
//会创建该类的代理对象,且此处会获取到TransactionInterceptor拦截器,该拦截器也实现了MethodInterceptor接口)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//如果拦截器链为空,说明没有真实的增强(advice),仅仅是对目标方法的反射调用
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//通过反射调用目标方法
retVal = methodProxy.invoke(target, argsToUse);
} else {
//调用ReflectiveMethodInvocation的proceed方法对目标方法进行增强
retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
}
retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
var16 = retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var16;
}
public boolean equals(@Nullable Object other) {
return this == other || other instanceof CglibAopProxy.DynamicAdvisedInterceptor && this.advised.equals(((CglibAopProxy.DynamicAdvisedInterceptor)other).advised);
}
public int hashCode() {
return this.advised.hashCode();
}
}
由此可知,AOP最终是通过DynamicAdvisedInterceptor类来实现对目标类进行增强的。
对AOP原理的流程进行简单总结:
1.在@Configuration类上或启动类上加上@EnableAspectJAutoProxy注解,在容器启动阶段就会加载beanName为internalAutoProxyCreator的AnnotationAwareAspectJAutoProxyCreator保存到beanDefinitionMap中,用于解析@Aspect。AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口和InstantiationAwareBeanPostProcessor接口,并继承了AbstractAutoProxyCreator抽象类。
2.在AbstractAutoProxyCreator的postProcessBeforeInstantiation方法中会调用getCustomTargetSource方法获取自定义目标源,如果针对目标类创建了TargetSource,此处就会提前创建代理对象。除非有需要,否则通常不会针对某个类创建自定义TargetSource,所以在postProcessBeforeInstantiation方法中不会提前创建代理对象。
3.在spring容器初始化bean之后,会调用AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization方法,在该方法中会获取到所有BeanPostProcessor接口的实现类,并调用postProcessAfterInitialization方法。其中就有专门用于生成AOP代理对象的处理器AnnotationAwareAspectJAutoProxyCreator,但是这个实现类中并没有postProcessAfterInitialization方法,而是调用其父类AbstractAutoProxyCreator中的这个方法。(子类继承父类之后,就会拥有父类中的方法和属性)(spring中AOP代理对象就是从此处开始创建的,另一处创建AOP代理对象是在循环依赖中通过二级缓存singletonFactory创建的)
4.在AbstractAutoProxyCreator的postProcessAfterInitialization方法中,主要做了两件事:获取增强器和创建代理对象。先根据bean获取适配的增强器,如果不为空,则为该bean创建代理对象,将代理对象保存到spring容器中。否则返回目标bean本身保存到spring容器中。
5.获取增强器。在抽象类AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法中,首先获取所有的增强器,其次从所有增强器中获取适配当前bean的增强器。
5.1.获取所有的增强器
(1)获取spring容器BeanFactory中所有已注册的beanName;
(2)判断对应的类是不是切面类,即判断类上是否有@Aspect注解;
(3)判断切面类中的方法上是否有@Before、@After、@Around等注解,若有,则为每一个方法创建对应的增强器advisor;
(4)新建的Advisor对象都保存在BeanFactoryAspectJAdvisorsBuilder#advisorsCache中,当AnnotationAwareAspectJAutoProxyCreator拦截bean的创建过程时,从这里面适配是否有切面可用。
5.2.获取适配当前bean的增强器
(1)调用AspectJExpressionPointcut的obtainPointcutExpression方法获取expression表达式(获取@Before、@After等注解方法上的表达式信息);
(2)通过反射获取目标类中的所有方法,循环目标类中的方法与切面类中表达式限定的方法(已封装成增强器)进行比较匹配;
(3)若匹配成功,则获取所有适配当前bean的增强器。
6.创建代理对象。
(1)创建代理工厂,设置创建代理对象所需的一些信息,如设置增强器、目标源等;
(2)如果目标类是接口,则创建jdk动态代理JdkDynamicAopProxy(实现了InvocationHandler接口,重写了invoke方法),否则创建cglib动态代理ObjenesisCglibAopProxy;
(3)通过jdk动态代理JdkDynamicAopProxy创建代理对象时,将自身作为InvocationHandler传给了Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)方法,所以在代理对象调用重写后的目标方法时,会调用JdkDynamicAopProxy的invoke方法。在invoke方法中将增强器转换为方法拦截器,如果拦截器链为空,则直接通过反射调用目标方法,否则调用ReflectiveMethodInvocation的proceed方法,在proceed方法中会调用拦截器的invoke方法,在invoke方法中会调用增强器的增强方法,同时会调用ReflectiveMethodInvocation的proceed方法,通过反射调用目标方法,对目标方法进行增强。
(4) 通过cglib动态代理创建代理对象时,通过Enhancer为代理类设置回调对象,即方法拦截器(实现了org.springframework.cglib.proxy.MethodInterceptor接口,重写了intercept方法,如DynamicAdvisedInterceptor),创建代理对象,在代理对象重写的目标方法中会调用拦截器的intercept方法。在拦截器重写的intercept方法中将增强器转换为方法拦截器(实现了org.aopalliance.intercept.MethodInterceptor接口,该接口中是invoke方法),获取拦截器链,如果拦截器链为空,则在拦截器重写的intercept方法中直接调用MethodProxy类的invoke方法,在该方法中通过反射调用目标对象的目标方法,否则调用ReflectiveMethodInvocation的proceed方法对目标方法进行增强。
注意:上面提到了两种方法拦截器,红色字体标记的方法拦截器实现了org.springframework.cglib.proxy.MethodInterceptor接口,重写了intercept方法,而蓝色字体标记的方法拦截器实现了org.aopalliance.intercept.MethodInterceptor接口,该接口中是invoke方法。增强器转换成的拦截器是后者,例如后置增强器AspectJAfterAdvice实现的就是org.aopalliance.intercept.MethodInterceptor接口。
在创建的代理对象中会对目标方法进行重写,在重写后的目标方法中会调用JdkDynamicAopProxy的invoke方法(通过jdk动态代理生成的代理对象),或者调用DynamicAdvisedInterceptor的intercept方法(通过cglib生成的代理对象),在invoke或intercept方法中都会将增强器转成拦截器。如果增强器实现了org.aopalliance.intercept.MethodInterceptor接口,则增强器本身就是一个拦截器,如AspectJAfterAdvice,否则根据增强器创建对应的拦截器,如根据AspectJMethodBeforeAdvice增强器创建的拦截器是MethodBeforeAdviceInterceptor。
Spring AOP @Before @Around @After 等 advice 的执行顺序:
@Around前置→@Before→目标方法→@AfterRunning(如果有异常→@AfterThrowing) →@After→@Around后置(如果目标方法抛出了异常,@Around的后置通知不会执行)
同一个方法被多个Aspect类拦截,如何指定每个 aspect 的执行顺序呢?
方法有以下两种,不管采用哪种方法,都是值越小的 aspect 越先执行。
1.实现org.springframework.core.Ordered接口,实现它的getOrder()方法
2.给aspect添加@Order注解,该注解全称为:org.springframework.core.annotation.Order
@Order(5)
@Component
@Aspect
public class Aspect1 {
// ...
}
@Order(6)
@Component
@Aspect
public class Aspect2 {
// ...
}
可保证不管在任何情况下, aspect1 中的 advice 总是比 aspect2 中的 advice 先执行。
对于@Around这个advice,不管它有没有返回值,必须要在方法内部调用pjp.proceed();否则,Controller 中的接口将没有机会被执行,从而也导致了 @Before这个advice不会被触发。