文章目錄
Spring Aop的核心
就是生成動態代理
和動態代理織入
,本篇主要講Spring Aop動態代理織入
,Spring Aop生成動態代理
在Spring Aop生成動態代理博文中
織入的定義
將目標對象中和其他對象連接起來的過程叫做織入
織入的種類
- 編譯期織入
執行效率高,不夠靈活
- 裝載時注入
稍微靈活,可以在JVM裝載目標類對象和聲明類對象的時候進行合併,執行效率不夠高
- 運行時織入(動態代理織入)
最靈活,通過配置文件進行目標類對象和通知進行合併的,效率低
Spring Aop屬於運行時織入
,AspectJ採用編譯期織入和類裝載期織入
Spring Aop在調用調用代理方法時,使用責任鏈設計模式
來對目標對象和通知對象執行合併,從而達到在程序運行時織入
調用代理方法
invoke(proxy, method, args)
/**
* 也就是當Proxy對象的代理方法被調用時,JdkDynamicAopProxy的的invoke方法作爲Proxy對象的回調函數被觸發,從而通過invoke的具體實現,來完成對目標對象方法調用的攔截或者說功能的增強工作
* 在Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)生成動態代理對象時,this需要時實現了InvocationHandler接口,並重寫invoke()方法,在invoke()方法中定義代理對象的邏輯
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 根據切面方法獲取攔截器鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果攔截器鏈不存在,就直接調用目標對象的方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
// 如果攔截器鏈存在,就對目標對象的方法進行增強
// 需要在調用目標對象的方法前後調用攔截器方法
else {
// 根據proxy(代理對象)、target(目標對象)、method(方法對象)、args(目標對象調用的方法參數)、targetClass(目標對象的Class對象)、chain(攔截器鏈)來生成攔截器鏈
MethodInvocation 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())) {
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) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
invocation.proceed()
public Object proceed() throws Throwable {
// //從-1開始計數
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 調用目標對象方法
return invokeJoinpoint();
}
// 從攔截器鏈中獲取MethodInterceptor攔截器,然後currentInterceptorIndex並進行++currentInterceptorIndex
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果MethodInterceptor攔截器是InterceptorAndDynamicMethodMatcher類型的
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 這裏每一次都去匹配是否適用於這個目標方法
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 遞歸調用,進行下一個攔截器鏈進行調用
return proceed();
}
}
else {
// 這裏this爲當前ReflectiveMethodInvocation對象
// 在invoke()方法中也進行遞歸調用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
invokeJoinpoint()
/**
* 調用目標對象方法
*/
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
/**
* 調用目標對象方法的真正實現
*/
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// 利用反射來執行目標對象的方法
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
用來處理@Before
、@After
、@AfterRunning
、@AfterThrowing
方法的類都實現了MethodInterceptor接口,重寫了invoke()方法,在方法中各自實現了不同的邏輯
@Before的處理類MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 執行前置通知方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 回調方法,在這裏進行調用後面的MethodInvocation攔截器
return mi.proceed();
}
}
@After的處理類AspectJAfterAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 執行後置通知方法
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
}
@AfterRunning的處理類AfterReturningAdviceInterceptor
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
// 執行最終通知方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
@AfterThrowing的處理類AspectJAfterThrowingAdvice
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 執行異常通知方法
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
}