Spring AOP原理与源码分析

╰半橙微兮° 2022-11-07 05:45 294阅读 0赞

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy注解用于开启AOP功能,那么这个注解底层到底做了什么呢?

查看@EnableAspectJAutoProxy的源码,发现它使用@Import注解向Spring容器中注入了一个类型为AspectJAutoProxyRegistrar的Bean:

  1. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  2. @Override
  3. public void registerBeanDefinitions(
  4. AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  5. // 注入一个bean名字为org.springframework.aop.config.internalAutoProxyCreator的AspectJAwareAdvisorAutoProxyCreator
  6. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  7. AnnotationAttributes enableAspectJAutoProxy =
  8. AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
  9. if (enableAspectJAutoProxy != null) {
  10. if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
  11. // proxyTargetClass为true
  12. AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
  13. }
  14. if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
  15. // exposeProxy为true
  16. AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
  17. }
  18. }
  19. }
  20. }

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,而ImportBeanDefinitionRegistrar是spring提供的扩展点之一,主要用来向容器中注入BeanDefinition,spring会根据BeanDefinion来生成Bean。

那么AspectJAutoProxyRegistrar到底向容器中注入了什么BeanDefinion呢?

org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)

  1. @Nullable
  2. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
  3. return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
  4. }
  5. @Nullable
  6. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  7. BeanDefinitionRegistry registry, @Nullable Object source) {
  8. // AnnotationAwareAspectJAutoProxyCreator
  9. return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  10. }
  11. @Nullable
  12. private static BeanDefinition registerOrEscalateApcAsRequired(
  13. Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
  14. Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
  15. if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
  16. BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
  17. if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
  18. int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
  19. int requiredPriority = findPriorityForClass(cls);
  20. if (currentPriority < requiredPriority) {
  21. apcDefinition.setBeanClassName(cls.getName());
  22. }
  23. }
  24. return null;
  25. }
  26. // 注入AspectJAwareAdvisorAutoProxyCreator
  27. RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  28. beanDefinition.setSource(source);
  29. beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
  30. beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  31. registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
  32. return beanDefinition;
  33. }

从源码可以发现AspectJAutoProxyRegistrar向容器中注入了一个类型为AnnotationAwareAspectJAutoProxyCreator的Bean。

那么AnnotationAwareAspectJAutoProxyCreator又是干什么的呢?

AnnotationAwareAspectJAutoProxyCreator主要实现了三个接口(由父类AbstractAutoProxyCreator实现):

  • 实现了BeanFactoryAware,内部持有BeanFactory的引用。
  • 实现了SmartInstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor).postProcessBeforeInstantiation,这个方法在bean的实例化(bean创建之前)之前执行。
  • 实现了BeanPostProcessor.postProcessBeforeInitialization(),这个方法在bean的初始化之前(bean创建之后,属性被赋值之前)执行,BeanPostProcessor.postProcessAfterInitialization()在bean的初始化之后执行。

AnnotationAwareAspectJAutoProxyCreator的继承结构:

在这里插入图片描述

找切面

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

  1. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  2. /** * @see AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() */
  3. // 获取容器中所有的切面Advisor
  4. // 这里返回的切面中的方法已经是有序的了,先按注解顺序(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),再按方法名称
  5. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  6. // 获取所有能够作用于当前Bean上的Advisor
  7. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  8. /** * @see AspectJAwareAdvisorAutoProxyCreator#extendAdvisors(java.util.List) */
  9. // 往集合第一个位置加入了一个DefaultPointcutAdvisor
  10. extendAdvisors(eligibleAdvisors);
  11. if (!eligibleAdvisors.isEmpty()) {
  12. /** * @see AspectJAwareAdvisorAutoProxyCreator#sortAdvisors(java.util.List) */
  13. // 这里是对切面进行排序,例如有@Order注解或者实现了Ordered接口
  14. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  15. }
  16. return eligibleAdvisors;
  17. }

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors

  1. protected List<Advisor> findCandidateAdvisors() {
  2. // Add all the Spring advisors found according to superclass rules.
  3. // 获取容器中所有的切面Advisor
  4. List<Advisor> advisors = super.findCandidateAdvisors();
  5. // Build Advisors for all AspectJ aspects in the bean factory.
  6. if (this.aspectJAdvisorsBuilder != null) {
  7. // 这里还需要解析@Aspect注解,生成Advisor
  8. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  9. }
  10. return advisors;
  11. }

org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply

  1. public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
  2. if (candidateAdvisors.isEmpty()) {
  3. return candidateAdvisors;
  4. }
  5. List<Advisor> eligibleAdvisors = new ArrayList<>();
  6. // InstantiationModelAwarePointcutAdvisorImpl
  7. for (Advisor candidate : candidateAdvisors) {
  8. if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
  9. // IntroductionAdvisor类型为引入切面,具体类型为DeclareParentsAdvisor
  10. eligibleAdvisors.add(candidate);
  11. }
  12. }
  13. boolean hasIntroductions = !eligibleAdvisors.isEmpty();
  14. for (Advisor candidate : candidateAdvisors) {
  15. if (candidate instanceof IntroductionAdvisor) {
  16. // already processed
  17. continue;
  18. }
  19. // PointCut中的ClassFilter.match 匹配类
  20. // PointCut中的MethodMatcher.match 匹配方法
  21. if (canApply(candidate, clazz, hasIntroductions)) {
  22. // @Aspect,类型为InstantiationModelAwarePointcutAdvisorImpl
  23. eligibleAdvisors.add(candidate);
  24. }
  25. }
  26. return eligibleAdvisors;
  27. }

代理对象的创建

代理对象的创建时机位于bean的初始化之后,因为代理对象内部还是需要去调用目标对象的方法,所以需要让目标对象实例化并完成初始化后才会创建代理对象。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

  1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  2. if (bean != null) {
  3. // 先从缓存中获取代理对象
  4. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  5. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  6. // 按需生成代理对象
  7. return wrapIfNecessary(bean, beanName, cacheKey);
  8. }
  9. }
  10. return bean;
  11. }

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

  1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  2. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  3. return bean;
  4. }
  5. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  6. return bean;
  7. }
  8. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return bean;
  11. }
  12. // Create proxy if we have advice.
  13. /** * @see AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean(java.lang.Class, java.lang.String, org.springframework.aop.TargetSource) */
  14. // 获取与当前Bean匹配的切面
  15. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  16. if (specificInterceptors != DO_NOT_PROXY) {
  17. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  18. // 创建代理
  19. Object proxy = createProxy(
  20. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  21. this.proxyTypes.put(cacheKey, proxy.getClass());
  22. return proxy;
  23. }
  24. // 缓存
  25. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  26. return bean;
  27. }

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

  1. protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
  2. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  3. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
  4. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  5. }
  6. // 创建代理工厂
  7. ProxyFactory proxyFactory = new ProxyFactory();
  8. proxyFactory.copyFrom(this);
  9. if (!proxyFactory.isProxyTargetClass()) {
  10. // 进来说明proxyTargetClass=false,指定JDK代理
  11. if (shouldProxyTargetClass(beanClass, beanName)) {
  12. // 进来这里说明BD中有个属性preserveTargetClass=true,可以BD中属性设置的优先级最高
  13. proxyFactory.setProxyTargetClass(true);
  14. }
  15. else {
  16. // 这里会判断bean有没有实现接口,没有就只能使用CGlib
  17. evaluateProxyInterfaces(beanClass, proxyFactory);
  18. }
  19. }
  20. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  21. proxyFactory.addAdvisors(advisors); // 切面
  22. proxyFactory.setTargetSource(targetSource); // 目标对象
  23. customizeProxyFactory(proxyFactory);
  24. proxyFactory.setFrozen(this.freezeProxy);
  25. if (advisorsPreFiltered()) {
  26. proxyFactory.setPreFiltered(true);
  27. }
  28. // 使用JDK或者CGlib创建代理对象
  29. return proxyFactory.getProxy(getProxyClassLoader());
  30. }

org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)

  1. public Object getProxy(@Nullable ClassLoader classLoader) {
  2. if (logger.isTraceEnabled()) {
  3. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  4. }
  5. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  6. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  7. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  8. }

这里主要看JDK动态代理的实现,Proxy.newProxyInstance()的第三个参数为InvocationHandler,而这里传的是this,也就是当前的类肯定实现了InvocationHandler接口。

代理方法的执行

由于是JDK动态代理,那么代理方法的调用肯定会进入InvocationHandler.invoke()方法中,这里的InvocationHandler的实现类为org.springframework.aop.framework.JdkDynamicAopProxy。

org.springframework.aop.framework.JdkDynamicAopProxy#invoke

  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2. Object oldProxy = null;
  3. boolean setProxyContext = false;
  4. TargetSource targetSource = this.advised.targetSource;
  5. Object target = null;
  6. try {
  7. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
  8. // The target does not implement the equals(Object) method itself.
  9. return equals(args[0]);
  10. }
  11. else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
  12. // The target does not implement the hashCode() method itself.
  13. return hashCode();
  14. }
  15. else if (method.getDeclaringClass() == DecoratingProxy.class) {
  16. // There is only getDecoratedClass() declared -> dispatch to proxy config.
  17. return AopProxyUtils.ultimateTargetClass(this.advised);
  18. }
  19. else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
  20. method.getDeclaringClass().isAssignableFrom(Advised.class)) {
  21. // Service invocations on ProxyConfig with the proxy config...
  22. return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
  23. }
  24. Object retVal;
  25. if (this.advised.exposeProxy) {
  26. // Make invocation available if necessary.
  27. oldProxy = AopContext.setCurrentProxy(proxy);
  28. setProxyContext = true;
  29. }
  30. // Get as late as possible to minimize the time we "own" the target,
  31. // in case it comes from a pool.
  32. target = targetSource.getTarget(); // 目标对象
  33. Class<?> targetClass = (target != null ? target.getClass() : null); // 目标对象的类型
  34. // Get the interception chain for this method.
  35. // 这里会对方法进行匹配,因为不是目标对象中的所有方法都需要增强
  36. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  37. // Check whether we have any advice. If we don't, we can fallback on direct
  38. // reflective invocation of the target, and avoid creating a MethodInvocation.
  39. if (chain.isEmpty()) {
  40. // We can skip creating a MethodInvocation: just invoke the target directly
  41. // Note that the final invoker must be an InvokerInterceptor so we know it does
  42. // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
  43. // 没有匹配的切面,直接通过反射调用目标对象的目标方法
  44. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  45. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  46. }
  47. else {
  48. // We need to create a method invocation...
  49. MethodInvocation invocation =
  50. new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  51. // Proceed to the joinpoint through the interceptor chain.
  52. /** * @see ReflectiveMethodInvocation#proceed() */
  53. // 这里才是增强的调用,重点,火炬的传递
  54. retVal = invocation.proceed();
  55. }
  56. // Massage return value if necessary.
  57. Class<?> returnType = method.getReturnType();
  58. if (retVal != null && retVal == target &&
  59. returnType != Object.class && returnType.isInstance(proxy) &&
  60. !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
  61. // Special case: it returned "this" and the return type of the method
  62. // is type-compatible. Note that we can't help if the target sets
  63. // a reference to itself in another returned object.
  64. retVal = proxy;
  65. }
  66. else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
  67. throw new AopInvocationException(
  68. "Null return value from advice does not match primitive return type for: " + method);
  69. }
  70. return retVal;
  71. }
  72. finally {
  73. if (target != null && !targetSource.isStatic()) {
  74. // Must have come from TargetSource.
  75. targetSource.releaseTarget(target);
  76. }
  77. if (setProxyContext) {
  78. // Restore old proxy.
  79. AopContext.setCurrentProxy(oldProxy);
  80. }
  81. }
  82. }

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed

  1. public Object proceed() throws Throwable {
  2. // We start with an index of -1 and increment early.
  3. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  4. // 执行到最后一个Advice,才会到这里执行目标方法
  5. return invokeJoinpoint();
  6. }
  7. Object interceptorOrInterceptionAdvice =
  8. this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  9. if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  10. // Evaluate dynamic method matcher here: static part will already have
  11. // been evaluated and found to match.
  12. // dm.isRuntime()=true的走这
  13. InterceptorAndDynamicMethodMatcher dm =
  14. (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  15. Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
  16. if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
  17. return dm.interceptor.invoke(this);
  18. }
  19. else {
  20. // Dynamic matching failed.
  21. // Skip this interceptor and invoke the next in the chain.
  22. return proceed();
  23. }
  24. }
  25. else {
  26. // It's an interceptor, so we just invoke it: The pointcut will have
  27. // been evaluated statically before this object was constructed.
  28. // 走这
  29. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  30. }
  31. }

interceptorsAndDynamicMethodMatchers中第一个advice为org.springframework.aop.interceptor.ExposeInvocationInterceptor。

ExposeInvocationInterceptor#invoke

org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke

  1. private static final ThreadLocal<MethodInvocation> invocation =
  2. new NamedThreadLocal<>("Current AOP method invocation");
  3. public Object invoke(MethodInvocation mi) throws Throwable {
  4. MethodInvocation oldInvocation = invocation.get();
  5. invocation.set(mi);
  6. try {
  7. return mi.proceed();
  8. }
  9. finally {
  10. invocation.set(oldInvocation);
  11. }
  12. }

ExposeInvocationInterceptor#invoke,只干了一件事就是将MethodInvocation加入到了ThreadLocal中,这样后续可以在其他地方使用ExposeInvocationInterceptor#currentInvocation获取到MethodInvocation,而MethodInvocation中封装了目标对象,目标方法,方法参数等信息。

环绕通知的执行

org.springframework.aop.aspectj.AspectJAroundAdvice#invoke

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. if (!(mi instanceof ProxyMethodInvocation)) {
  3. throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
  4. }
  5. ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
  6. ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
  7. JoinPointMatch jpm = getJoinPointMatch(pmi);
  8. return invokeAdviceMethod(pjp, jpm, null, null);
  9. }

这里会去调用环绕通知的增强方法,而环绕通知的增强方法中会执行proceedingJoinPoint.proceed(),这样就会调用下一个MethodInterceptor–>MethodBeforeAdviceInterceptor。

前置通知的执行

org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
  3. return mi.proceed();
  4. }

这里又会调用MethodInvocation.proceed()传递给下一个MethodInterceptor。

后置通知的执行

org.springframework.aop.aspectj.AspectJAfterAdvice#invoke

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. try {
  3. return mi.proceed();
  4. }
  5. finally {
  6. invokeAdviceMethod(getJoinPointMatch(), null, null);
  7. }
  8. }

先执行MethodInvocation.proceed(),最后在finally块中调用后置通知的增强,不管目标方法有没有抛出异常,finally代码块中的代码都会执行,也就是不管目标方法有没有抛出异常,后置通知都会执行。

返回后通知的执行

org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. Object retVal = mi.proceed();
  3. this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
  4. return retVal;
  5. }

先执行MethodInvocation.proceed(),然后再执行返回后通知的增强。

异常通知的执行

org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. try {
  3. return mi.proceed();
  4. }
  5. catch (Throwable ex) {
  6. if (shouldInvokeOnThrowing(ex)) {
  7. invokeAdviceMethod(getJoinPointMatch(), null, ex);
  8. }
  9. throw ex;
  10. }
  11. }

先执行MethodInvocation.proceed(),如果目标方法抛出了异常就会执行异常通知的增强,然后抛出异常,所以这时返回后通知的增强就不会执行了。

总结各种通知的执行顺序:

  1. Around begin // 环绕通知开始
  2. Before // 前置通知
  3. UserServiceImpl
  4. // 目标方法的执行
  5. AfterReturning
  6. // 返回后通知
  7. After
  8. // 后置通知
  9. Around end // 环绕通知结束

发表评论

表情:
评论列表 (有 0 条评论,294人围观)

还没有评论,来说两句吧...

相关阅读