Spring源代码解析7:Spring AOP中对拦截器调用的实现

2019-01-12 11:02

前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为我们提供AOP功能的; 在JdkDynamicAopProxy中生成Proxy对象的时候: 代码

1. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

这里的this参数对应的是InvocationHandler对象,这里我们的

JdkDynamicAopProxy实现了这个接口,也就是说当Proxy对象的函数被调用的时候,这个InvocationHandler的invoke方法会被作为回调函数调用,下面我们看看这个方法的实现: 代码

1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

2. MethodInvocation invocation = null; 3. Object oldProxy = null;

4. boolean setProxyContext = false; 5.

6. TargetSource targetSource = this.advised.targetSource; 7. Class targetClass = null; 8. Object target = null; 9.

10. try {

11. // Try special rules for equals() method and implementation of the

12. // Advised AOP configuration interface. 13.

14. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {

15. // What if equals throws exception!?

16. // This class implements the equals(Object) method itself.

17. return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;

18. }

19. if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {

20. // This class implements the hashCode() method itself.

21. return new Integer(hashCode());

22. }

23. if (Advised.class == method.getDeclaringClass()) { 24. // service invocations on ProxyConfig with the proxy config

25. return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 26. } 27.

28. Object retVal = null; 29.

30. if (this.advised.exposeProxy) {

31. // make invocation available if necessary

32. oldProxy = AopContext.setCurrentProxy(proxy); 33. setProxyContext = true; 34. } 35.

36. // May be null. Get as late as possible to minimize the time we \37. // in case it comes from a pool.

38. // 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例池或者是一个简单的JAVA对象

39. target = targetSource.getTarget(); 40. if (target != null) {

41. targettargetClass = target.getClass(); 42. } 43.

44. // get the interception chain for this method 45. // 这里获得定义好的拦截器链

46. List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(

47. this.advised, proxy, method, targetClass); 48.

49. // Check whether we have any advice. If we don't, we can fallback on direct

50. // reflective invocation of the target, and avoid creating a MethodInvocation.

51. // 如果没有设定拦截器,那么我们就直接调用目标的对应方法

52. if (chain.isEmpty()) {

53. // We can skip creating a MethodInvocation: just invoke the target directly

54. // Note that the final invoker must be an InvokerInterceptor so we know it does

55. // nothing but a reflective operation on the target, and no hot swapping or fancy proxying

56. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); 57. }

58. else {

59. // We need to create a method invocation... 60. // invocation = advised.getMethodInvocationFactory().getMethodInvocation(

61. // proxy, method, targetClass, target, args, chain, advised);

62. // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法

63. // 这里通过构造一个ReflectiveMethodInvocation来实现,下面我们会看这个ReflectiveMethodInvocation类

64. invocation = new ReflectiveMethodInvocation( 65. proxy, target, method, args, targetClass, chain); 66.

67. // proceed to the joinpoint through the interceptor chain

68. // 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的目标方法

69. retVal = invocation.proceed(); 70. } 71.

72. // massage return value if necessary

73. if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) {

74. // Special case: it returned \type of the method is type-compatible

75. // Note that we can't help if the target sets 76. // a reference to itself in another returned object.

77. retVal = proxy; 78. }

79. return retVal; 80. }

81. finally {

82. if (target != null && !targetSource.isStatic()) { 83. // must have come from TargetSource 84. targetSource.releaseTarget(target); 85. } 86.

87. if (setProxyContext) { 88. // restore old proxy

89. AopContext.setCurrentProxy(oldProxy); 90. } 91. } 92.}

我们先看看目标对象方法的调用,这里是通过AopUtils的方法调用 - 使用反射机制来对目标对象的方法进行调用: 代码

1. public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) 2. throws Throwable { 3.

4. // Use reflection to invoke the method.

5. // 利用放射机制得到相应的方法,并且调用invoke 6. try {

7. if (!Modifier.isPublic(method.getModifiers()) || 8. !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {

9. method.setAccessible(true); 10. }

11. return method.invoke(target, args); 12. }

13. catch (InvocationTargetException ex) {

14. // Invoked method threw a checked exception.

15. // We must rethrow it. The client won't see the interceptor.

16. throw ex.getTargetException(); 17. }

18. catch (IllegalArgumentException ex) {

19. throw new AopInvocationException(\ms to be invalid: tried calling method [\

20. method + \

21. }

22. catch (IllegalAccessException ex) {

23. throw new AopInvocationException(\d: \24. } 25.}

对拦截器链的调用处理是在ReflectiveMethodInvocation里实现的: 代码

1. public Object proceed() throws Throwable {

2. // We start with an index of -1 and increment early. 3. // 这里直接调用目标对象的方法,没有拦截器的调用或者拦截器已经调用完了,这个currentInterceptorIndex的初始值是0

4. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) {

5. return invokeJoinpoint(); 6. } 7.

8. Object interceptorOrInterceptionAdvice =

9. this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex);

10. if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

11. // Evaluate dynamic method matcher here: static part will already have

12. // been evaluated and found to match.

13. // 这里获得相应的拦截器,如果拦截器可以匹配的上的话,那就调用拦截器的invoke方法

14. InterceptorAndDynamicMethodMatcher dm =

15. (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;

16. if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {

17. return dm.interceptor.invoke(nextInvocation()); 18. }

19. else {

20. // Dynamic matching failed.

21. // Skip this interceptor and invoke the next in the chain.

22. // 如果拦截器匹配不上,那就调用下一个拦截器,这个时候拦截器链的位置指示后移并迭代调用当前的proceed方法 23. this.currentInterceptorIndex++; 24. return proceed(); 25. } 26. }

27. else {

28. // It's an interceptor, so we just invoke it: The pointcut will have


Spring源代码解析7:Spring AOP中对拦截器调用的实现.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:一线教师课题选择存在问题及成因

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: