Primavera 5.x trip Fuente consulta cuarenta y nueve AOP notificación método de orden de ejecución
- Cómo ejecución del método de notificación AOP
- ReflectiveMethodInvocation de ciclos de ejecución proceder
- ExposeInvocationInterceptor 的 invoke
- AspectJAfterThrowingAdvice invocar la excepción de notificación
- Después del regreso exitoso de AfterReturningAdviceInterceptor invocación de notificación
- AspectJAfterAdvice invocación de método de notificación
- AspectJAroundAdvice invocar el asesoramiento en torno
- método de invocación MethodBeforeAdviceInterceptor antes de la notificación
Cómo ejecución del método de notificación AOP
Mira toda la AOP
estructura interna de la orden de ejecución de los métodos básicos de la notificación:
Tomamos un JDK
proxy dinámico, por ejemplo, CGLIB
es similar, cuando se llama a un método, será JdkDynamicAopProxy
el agente de invoke
ejecución:
@Override
@Nullable
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)) {
// 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);
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
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...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 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);
}
}
}
Montón, de hecho, tan pocos importante, en primer lugar obtener todas las notificaciones List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
y luego se envasa en una ReflectiveMethodInvocation
llamada de proceed
método. Pongo el enfoque general de AOP tiene que pasar, se puede ver en la que ya está terminado pidiendo, específicamente la forma de una especie, se puede ir a estudiar, más complicado, de hecho, con el fin de formar un orden pila de llamadas, atraeré a la parte trasera, nos fijamos en el uso de estos, de hecho, nada específico con la primera, que dirigirá la aplicación de la segunda y, a continuación, pasar a realizar en este orden:
ReflectiveMethodInvocation de ciclos de ejecución proceder
El principal es un notificaciones Get recursivos, y luego ejecutados.
@Override
@Nullable
public Object proceed() throws Throwable {
// 循环执行,直到执行完
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//获得通知方法
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.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
ExposeInvocationInterceptor 的 invoke
Yo no lo hice, sobre todo mi.proceed()
, es decir, seguir llamando ReflectiveMethodInvocation的proceed
para hacer llamadas recursivas.
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
AspectJAfterThrowingAdvice invocar la excepción de notificación
De hecho, la capa externa de la captura de pan excepción, y luego continuar a la llamada mi.proceed();
, si una anomalía que puede ser capturado a realizar invokeAdviceMethod
.
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
AbstractAspectJAdvice método de notificación de invokeAdviceMethod
De hecho, este es un método común de notificación, siempre y cuando el método de notificación que se llamará, será la última llamada para llamar a esta dentro de este:
Después del regreso exitoso de AfterReturningAdviceInterceptor invocación de notificación
Justo después de volver más método es llamar el interior invokeAdviceMethod
.
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
AspectJAfterAdvice invocación de método de notificación
Es decir, después de la aplicación de la ejecución invokeAdviceMethod
.
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
AspectJAroundAdvice invocar el asesoramiento en torno
Esto pondrá MethodInvocation
el paquete en ProceedingJoinPoint
y, a continuación, pasar como parámetros cuando se invoca.
@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);
return invokeAdviceMethod(pjp, jpm, null, null);
}
Primer paquete:
Después del uso:
Luego será clonado, tal vez la agencia para proteger los datos de origen, y luego llamar a proceed
:
método de invocación MethodBeforeAdviceInterceptor antes de la notificación
Antes de llamar al método primera notificación método, una llamada al método.
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
El proceso básico es tan abajo, así que por qué está rodeada en la parte delantera, ya que la parte trasera rodeado por agentes del método para llevar a cabo, antes de rodear transformación llevada a cabo con antelación:
Si una excepción es decir:
vistazo a toda la estructura es la siguiente:
HM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZWkxOTg3MTEwMw == , size_16, color_FFFFFF, t_70)
normalmente se puede controlar, que no es inusual, cuestión nada.
Si una excepción es que aparezca en System.out.println("方法调用");
tanto ejecutados directamente System.out.println("logAfter");
, la ejecución no va a ir logReturning
directamente en el catch
interior, con una excepción cuando la información también está en alza.
Pues bien, el básico de AOP
análisis llamada ha terminado, después de que el aviso es en realidad un método bueno para ordenar, llamadas recursivas. De hecho, hay otras características, tales como DeclareParents
, target
, args
y otras anotaciones, con este fundamento, no debería ser difícil, su propia investigación simplemente genial.
Pues bien, hoy aquí, esperamos estudio ayuda y entender, no rocíe el Gran Dios ver, comprender solamente su propio aprendizaje, capacidad limitada, por favor excusa.