SpringAop流程分析

在分析流程之前,我们先简单的实现一下AOP。

@Component
@ComponentScan("com.jxau")
public class EnableComponentScan {
}

定义一个扫描包。然后创建一个类开启AOP的扫描注解

@Component
@EnableAspectJAutoProxy(exposeProxy = true)
public class EnableAop {
}

定义一个切面。

@Component
@Aspect
public class AspectJ {
    //拦截service包下所有类
    @Pointcut("execution(public * com.jxau.service.*.*(..))")
    public void pointCut1(){

    }
    //拦截service包下的saveAccount方法
    @Pointcut("execution(public * com.jxau.service.*.saveAccount*(..))")
    public void pointCut2(){}
    //使用pointCut2
    @Before("pointCut2()")
    public void beforeAdvice(){
        System.out.println("before前置通知");
    }
    //使用pointCut1
    @Around("pointCut1()")
    public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
        System.out.println("around的前置通知");
        Object proceed = point.proceed();
        System.out.println("around的后置通知");
        return proceed;
    }

    @After("execution(public * com.jxau.service.*.*(..))")
    public void afterMethod(){
        System.out.println("afterMethod");
    }

    
    @AfterReturning("execution(public * com.jxau.service.*.*(..))")
    public void returnMethod(){
        System.out.println("returnMethod");
    }
}

然后定义一个被切的类。

public interface AccountService {
    public void saveAccount();
}
@Service
class AccountServiceImpl implements AccountService {
    public void saveAccount() {
        System.out.println("saceAccount");
    }
}

其实这个时候,我们就可以启动了。

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(EnableComponentScan.class);
AccountService bean = applicationContext.getBean(AccountService.class);
bean.saveAccount();

运行结果。
在这里插入图片描述
这样,我们的一个简单的demo就搭建完成了。下面我们来分析一下他的执行流程。

@EnableAspectJAutoProxy

那其实呢,我们整个AOP,其实就是这个注解所开启的,那么这个注解到底做了什么。在这里插入图片描述
其实,不管是@Service还是@Component都会被@ComponentScan注解扫描到,具体如何被扫描的,是从AnnotationConfigApplicationContext入口,在该方法中,会通过ComponentScan注解,然后像解析自定义标签一样,扫描basePackages下的带注解的类,封装为BeanDefinition,然后会遍历这些BeanDefinition,看看其类上有没有@Import、@Compontent等注解,如果有,会继续将涉及的类注册到IOC容器中,因此,我们这个注解之上的import注解就一定会被扫描到,而且会导入一个AspectJAutoProxyRegistrar的类,那看来这个类就是我们的重点了。

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//注册注解AOP入口类
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

这个类中除了构造,其实也就只有这么一个方法,而这个方法会被beanFactory注册beanDefinition的时候调用,核心在第一句代码,我们一步步进去之后,会看到这样的方法。

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }

            return null;
        } else {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }

那这个方法其实也比较简单了,就是注册一个BeanDefinition ,registry.registerBeanDefinition(“org.springframework.aop.config.internalAutoProxyCreator”, beanDefinition);也很明确的告诉我们,注册的这个BeanDefinition 就是AnnotationAwareAspectJAutoProxyCreator.class,他的key值是org.springframework.aop.config.internalAutoProxyCreator,这个BeanDefinition 有很重要的作用。

AOP入口

applyBeanPostProcessorsAfterInitialization

其实在bean实例化和依赖注入的时候,有个位置是AOP的入口,AOP想要用原类,那么一定在该类实例化和依赖注入完成后才可以用,因此AOP入口是在doCreateBean的populateBean方法(实例化后的依赖注入)后进行,即initializeBean方法,如下:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			.....
		}
		else {
			//调用Aware方法
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//调用@PostConstruct,Aware等接口方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//调用InitializingBean接口的afterPropertiesSet方法和init-method
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		.................
		}
		if (mbd == null || !mbd.isSynthetic()) {
			//这里就是AOP的入口了
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;

        Object current;
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
        }

        return result;
    }

这里的意图也很明显,就是遍历所有的BeanPostProcessor接口,调用postProcessAfterInitialization方法,该方法是bean声明周期中,初始化后的后置操作,这里主要交给其子类AbstractAutoProxyCreator处理:那么我们刚刚提到,在注册BeanDefinition 的时候,会注册一个叫AnnotationAwareAspectJAutoProxyCreator的类,这个时候他就会体现出他的作用了,bean在这个类的处理下变成代理对象。
在这里插入图片描述

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;
    }

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在切点pointcut表达式范围内,则获得当前bean的切面
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                //创建代理
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }

这个方法主要两个作用:

  1. 如果当前类在需要增强的范围内,则获取该类的切面
  2. 如果有切面,则创建该类的代理对象并返回

getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
        return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
    }


protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
        List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        this.extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
        }

        return eligibleAdvisors;
    }

那自然,获取切面的方法就是findEligibleAdvisors方法了。那这个方法重要的其实也就是两步。

  1. findCandidateAdvisors,找到工程所有@Aspectj注解的类封装成Advisor返回
  2. findAdvisorsThatCanApply,获得符合当前bean的切面,拿到所有Advisor对象后,就要遍历Advisor集合,判断当前类是否在pointcut表达式的范围中,这里进行模糊匹配,了解就好。

findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
        List<Advisor> advisors = super.findCandidateAdvisors();
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }

        return advisors;
    }

public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					//首先获取容器中的所有bean的名称BeanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						//判断类上是否有@Aspect注解
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

								//创建获取有@Aspect注解类的实例工厂进行获取
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

								//创建切面advisor对象
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}

		................缓存的切面aspectNames不为null但是空的,就返回空集合;
            如果有缓存,就调用getAdvisors获取并加入缓存.....
		return advisors;
	}

其实也比较简单,无非就是遍历当前容器中所有的beanName,然后通过MetadataAwareAspectInstanceFactory实例工厂获取切面对象Advisor。

getAdvisors

	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		//1.借助工厂获取有@Aspect注解的类Class
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//2.获取所有有@Aspect注解的类的beanName
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		//创建工厂的装饰类,获取实例只会获取一次
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();

		//3.循环没有@Pointcut注解的方法
		for (Method method : getAdvisorMethods(aspectClass)) {

			//3.1 具体获取
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		//判断属性上是否有引介注解
		// Find introduction fields.
		for (Field field : aspectClass.getDeclaredFields()) {
			//判断属性上是否有DeclareParents注解,如果有返回切面
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

该方法就是从刚刚的工厂中获取有@Aspect注解的class对象和beanName,然后遍历该类中没有@PointCut注解的类,也就是我们定义的@Around、@Before、@After等注解通知的方法,通过getAdvisor创建具体的切面类。值得注意的是getAdvisorMethods(aspectClass)方法。

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        List<Method> methods = new ArrayList();
        ReflectionUtils.doWithMethods(aspectClass, (method) -> {
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }

        }, ReflectionUtils.USER_DECLARED_METHODS);
        methods.sort(METHOD_COMPARATOR);
        return methods;
    }

这个方法所获得的是没有Pointcut注解的方法。

getAdvisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
        this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        return expressionPointcut == null ? null : new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

这个方法的核心,getPointCut,顾名思义,得到pointCut。

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        } else {
            AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
            ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
            if (this.beanFactory != null) {
                ajexp.setBeanFactory(this.beanFactory);
            }

            return ajexp;
        }
    }

我们发现,最后返回了一个AspectJExpressionPointcut 对象,这个对象里面包含了我们的方法,还设置了一个属性,那么这个属性就是我们的pointCut了,那我们主要关注的方法肯定就是包含这个属性的返回aspectJAnnotation 变量的方法了。

protected static AbstractAspectJAdvisorFactory.AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
		//    private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class[]{Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
        Class[] var1 = ASPECTJ_ANNOTATION_CLASSES;
        int var2 = var1.length;

        for(int var3 = 0; var3 < var2; ++var3) {
            Class<?> clazz = var1[var3];
            AbstractAspectJAdvisorFactory.AspectJAnnotation<?> foundAnnotation = findAnnotation(method, clazz);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }

        return null;
    }

不难看出,其实就是遍历我们的增强注解,找到方法上对应的增强注解,并封装成AspectJAnnotation对象返回,那这个AspectJAnnotation对象是什么样的呢。

public AspectJAnnotation(A annotation) {
			this.annotation = annotation;
    		//这里就是判断当前注解是啥类型,取值是枚举类:
    		//AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
			this.annotationType = determineAnnotationType(annotation);
			try {
				//1. 这里就是解析注解上的value值,即pointcut值,如@Before("pointCut2()")中的pointCut2()或是具体的execution表达式
				this.pointcutExpression = resolveExpression(annotation);
				//2.获取注解上的参数
				Object argNames = AnnotationUtils.getValue(annotation, "argNames");
				this.argumentNames = (argNames instanceof String ? (String) argNames : "");
			}
			catch (Exception ex) {
				throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
			}
		}

封装完成之后,返回到我们的getAdvisor当中。得到返回的AspectJExpressionPointcut对象,最后又要封装成InstantiationModelAwarePointcutAdvisorImpl对象。


	public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		//pointcut类及其他属性赋值
		this.declaredPointcut = declaredPointcut;
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		this.methodName = aspectJAdviceMethod.getName();
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// Static part of the pointcut is a lazy type.
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

			// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
			// If it's not a dynamic pointcut, it may be optimized out
			// by the Spring AOP infrastructure after the first evaluation.
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			//创建了Advice对象
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
        Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
        return advice != null ? advice : EMPTY_ADVICE;
    }
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		//获取有@Aspect注解的类
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);

		//就是前面封装注解信息的方法,这里又进行了一遍
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		AbstractAspectJAdvice springAdvice;

		//这里就会根据注解类型【前面说的枚举】创建不同的advice类
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				//实现了MethodInterceptor接口
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				//实现了MethodBeforeAdvice接口,没有实现MethodInterceptor接口
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				//实现了MethodInterceptor接口
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				//实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				//实现了MethodInterceptor接口
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}

		//计算argNames和类型的对应关系
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

这里我们只要知道是根据注解的类型创建了不同的Advice类,然后返回,而几个Advice类的细节,以及有的实现的MethodInterceptor接口,有的实现的MethodBeforeAdvice接口后面会具体讲解。
到这里就对一个方法完成了全部的解析,并且构造了一个切面对象Advisor,对所有方法处理完之后,返回到buildAspectJAdvisors方法中,然后返回所拿到的这个Advisor集合。一路返回到最初的wrapIfNecessary方法中。

创建代理

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);
		}

		//1.创建代理工厂
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				//设置proxyTargetClass属性
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		//2. 把advice类型的增强包装成advisor切面
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    	//将所有切面放入代理工厂
		proxyFactory.addAdvisors(advisors);
    	//设置目标类
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		用来控制代理工厂被配置后,是否还允许修改代理的配置,默认为false
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		//3.获取代理实例
		return proxyFactory.getProxy(getProxyClassLoader());
	}

public Object getProxy(@Nullable ClassLoader classLoader) {
        return this.createAopProxy().getProxy(classLoader);
    }


protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            this.activate();
        }

        return this.getAopProxyFactory().createAopProxy(this);
    }

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

这里就会根据注解中的ProxyTargetClass属性和目标类是否实现了接口来判断是创建Cglib代理还是JDK动态代理,注意,这里会将config,即我们的代理工厂传入具体的代理类,保存到advised中,而工厂中又保存了所有的切面对象,后面就会用到。

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);
        this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

到这里代理创建完成,在调用相应的方法的时候,就会进入对应代理的invoke方法中。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		//代码1:从代理工厂中拿到TargetSource,内部保存了被代理的实例bean
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			//被代理对象的equals方法和hashCode方法不能被代理,直接走对应的方法,不走下面的切面。
			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();
			}
			........

			Object retVal;
			//设置exposeProxy属性
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			//从targetSource拿到被代理实例
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			//代码2:从代理工厂中拿过执行链, Object是一个被包装成MethodInterceptor类型的Advice对象
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);


			//如果该方法没有执行链,则说明这个方法不需要被拦截,则直接反射调用
			if (chain.isEmpty()) {
				
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 代码3:有调用链,就进行调用
				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())) {
				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);
			}
		}
	}

这里主要做了两个工作:

  • 拿到被代理类后,就通过代理工厂获取该类的调用链
  • 如果如果有执行链,说明需要拦截,就进行增强调用。

先看如何拿到执行链。

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();
		//从代理工厂对象config拿到被代理类的所有切面advisors
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;
		//如本例的around和before两个切面
		for (Advisor advisor : advisors) {
			//大部分走这里
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				//通过切面的pointcut判断当前类是否需要拦截,即匹配通配符
				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 {
						//再通过pointcut判断当前方法是否需要拦截,因为我们可能只拦截部分方法
						match = mm.matches(method, actualClass);
					}
					
					if (match) {//到这里类和方法都匹配,即该方法要进行拦截

						//获取到切面advisor中的advice,并且包装成MethodInterceptor类型的对象
						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;
	}


该方法主要做了如下的事:

  • 匹配当前类是否和切面的pointcut匹配
  • 如果匹配,则判断当前方法是否和切面pointcut匹配
  • 如果都匹配,则将切面中的各种Advice包装成MethodInterceptor后添加到执行链集合返回。这里主要是为了后面调用的时候可以统一调用。
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		Advice advice = advisor.getAdvice();
    /*
    如果是MethodInterceptor类型的,即前面创建Advice时,几个类实现了MethodInterceptor接口:
   		 AspectJAroundAdvice
		AspectJAfterAdvice
		AspectJAfterThrowingAdvice
    */
		if (advice instanceof MethodInterceptor) {
			//包装成MethodInterceptor
			interceptors.add((MethodInterceptor) advice);
		}

		//这里就是将没有实现MethodInterceptor接口的两个Advice: AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice包装成MethodInterceptor
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[0]);
	}

到这里就拿到了当前方法的执行链,如果当类不需要增强,则就不会被匹配拦截,其执行链也就是空,就会直接反射执行其本身的方法,如果不为空,就需要执行代理增强的方法:

链式调用

拿到执行链之后,就会调用proceed方法进行链式调用。

public Object proceed() throws Throwable {
		//	We start with an index of -1 and increment early.
		//代码1:如果执行链中的advice全部调用完毕,则直接调用joinPoint方法,即被代理的方法本身
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
		//interceptorsAndDynamicMethodMatchers就是刚刚获取的执行链,有当前方法需要调用的所有Advice
    	//代码2:这里就会按顺序调用里面的advice,然后索引加1
		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 {

			//代码3:调用MethodInterceptor中具体的invoke方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

这里流程也很简单,就是按顺序取刚刚得到的调用链中的Advice,然后转成MethodInterceptor调用对应子类的invoke方法,当调用的索引和调用链集合一样大时,说明所有的Advice都调用完成了,这时就可以执行被代理的方法。

那么有个问题,这里没有for循环,是如何调用多次的呢?其实很简单,已经说了是链式调用,因此调用完上一个Advice后,会在上一个invoke中的最后再调用proceed方法,这时就开始了下一次Advice的调用。

Advice有多个子类,分别对应Before、Around、AfterRturning、AfterThrowing、After等注解增强。

其首先会调用Around注解方法:

	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);
        //反射调用Around注解中的方法
		return invokeAdviceMethod(pjp, jpm, null, null);
	}
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
			return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
		}
}

这就执行了文章一开始写的Demo中的System.out.println(“around的前置通知”);,然后走到Object proceed = point.proceed();又会回到proceed方法,继续调用,接着就会调用@Before注解的方法,执行System.out.println(“before前置通知”);,之后又会调用proceed()继续上面的流程片【如下】。这时全部Advice已经调用完毕,就会执行被代理的方法,执行System.out.println(“saveAccount…”);,然后从@Around的proceed()返回执行System.out.println(“around的后置通知”);结束调用。

//MethodBeforeAdviceInterceptor #invoke
public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
}

但是@AfterReturning这种需要在被代理方法执行后再执行的Adivice怎么办呢?看一下吧:

//AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
		Object retVal = mi.proceed();
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}

其实,如果调用到该方法,则执行再次进入proceed方法,其实就相当于@Around中的proceed方法的作用,等全部执行完后,再执行后置通知。对应@AfterThrowing是一样的道理,只是将proceed放入了try中,在finally中会判断是否发生异常,如果发生异常,就执行@AfterThrowing注解的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值