创建AOP之获取增强器

上篇文章已经分析了创建AOP代理只需要两步,分别是获取增强器,并根据增强器来创建代理.
下面先分析如何获取增强器

	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		// 获取增强器
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		// 找到所有的增强器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 看哪些是适用于bean的增强器
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
	protected List<Advisor> findCandidateAdvisors() {
		// 使用注解方式配置AOP时,不会丢弃对XML配置的支持
		// 在这里调用父类方法加载文件中的AOP声明
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		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<>();
					// 获取所有的beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					// 循环所有的beanName找出对应的增强方法
					for (String beanName : beanNames) {
						// 不合法的bean则略过,规则由子类来定义,默认返回true
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// 获取bean的类型
						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) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								// 解析标记AspectJ注解中的增强方法
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									// 如果是单例,则放入advisorsCache中
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									// 否则放入aspectFactoryCache
									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;
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<Advisor> advisors = new ArrayList<>();
		for (String aspectName : aspectNames) {
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			}
			else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}

到这里我们已经完成了Advisor的提取,在上面的步骤中最重要的是增强器的获取——getAdvisors方法.

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		// 获取标记为AspectJ的类
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        // 获取标记为AspectJ的name
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        // 验证
        this.validate(aspectClass);
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
        List<Advisor> advisors = new ArrayList();
        // 获取类中的所有的增强方法,排出Pointcut的方法
        Iterator var6 = this.getAdvisorMethods(aspectClass).iterator();

        while(var6.hasNext()) {
        	// 遍历
            Method method = (Method)var6.next();
            // 获取方法上的增强器
            Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        	// 如果寻找到的增强器不为空且又配置了增强延迟初始化
        	// 那么需要在首位加入同步实例化增强器
            Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }
		// 获取DeclareParents注解
        Field[] var12 = aspectClass.getDeclaredFields();
        int var13 = var12.length;

        for(int var14 = 0; var14 < var13; ++var14) {
            Field field = var12[var14];
            Advisor advisor = this.getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
        return advisors;
    }

总结一下上面这个方法的功能:
a、首先根据类获取类中除pointcout的方法
b、遍历获取的方法,获取普通增强器
c、如果增强器不为空并且延迟加载则需要创建一个同步实例化增强器
d、根据DeclareParents注解,获取引介增强器

所以这里可以看到这里一共是有三种增强器.
下面就这三种增强器来逐一分析

  1. 普通增强器
    对于普通增强器的获取,其实就是方法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);
    }
  • 切点信息的获取.切点信息就是指注解的表达式信息的获取,比如@Before(“test()”).
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    	// 获取方法上的注解
        AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        } else {
        	// 使用AspectJExpressionPointcut实例封装获取的信息
            AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
			// 提取得到的注解中的表达式
			// 如:@Pointcut("execution(* *.test(..))")   
            ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
            if (this.beanFactory != null) {
                ajexp.setBeanFactory(this.beanFactory);
            }

            return ajexp;
        }
    }
	protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
		// ASPECTJ_ANNOTATION_CLASSES:
		// Pointcut.class, 
		// Around.class, 
		// Before.class, 
		// After.class, 
		// AfterReturning.class, 
		// AfterThrowing.class
		for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
			// 在方法上寻找上面这些注解,
			// 如果存在则封装成AspectJAnnotation
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}
  • 根据切点信息生成增强.
	public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		// 切点表达式
		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()) {
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
					
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			// 对增强器进行初始化
			// 不同类型的标签,增强器增强的位置不同
			// 所以需要不同的增强器来完成不同的逻辑
			// 因为可以根据注解中的信息初始化对应的增强器
			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) {
        Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        this.validate(candidateAspectClass);
        AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        } else if (!this.isAspect(candidateAspectClass)) {
            throw new AopConfigException("Advice must be declared inside an aspect type: Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]");
        } else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Found AspectJ method: " + candidateAdviceMethod);
            }

            Object springAdvice;
            // 根据不同的注解类型封装不同的增强器
            switch(aspectJAnnotation.getAnnotationType()) {
            case AtPointcut:
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }

                return null;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning)aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    ((AbstractAspectJAdvice)springAdvice).setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    ((AbstractAspectJAdvice)springAdvice).setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            default:
                throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);
            }

            ((AbstractAspectJAdvice)springAdvice).setAspectName(aspectName);
            ((AbstractAspectJAdvice)springAdvice).setDeclarationOrder(declarationOrder);
            String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
            if (argNames != null) {
                ((AbstractAspectJAdvice)springAdvice).setArgumentNamesFromStringArray(argNames);
            }

            ((AbstractAspectJAdvice)springAdvice).calculateArgumentBindings();
            return (Advice)springAdvice;
        }
    }
  1. 同步实例化增强器
    如果寻找的增强器不为空,而且又配置了增强延迟初始化,就需要在首位加入同步实例化增强器.同步实例化增强器如下:
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
        public SyntheticInstantiationAdvisor(MetadataAwareAspectInstanceFactory aif) {
            super(aif.getAspectMetadata().getPerClausePointcut(), (method, args, target) -> {
            	// 简单初始化aspect
                aif.getAspectInstance();
            });
        }
    }
  1. 引介增强器
    什么是引介?
    引介是一种特殊的增强,他为类添加一些属性和方法,这样即使一个业务原本没有实现某个接口,通过aop的引介功能,可以动态为该业务添加接口的实现逻辑,让业务类成为这个接口的实现类.
    private Advisor getDeclareParentsAdvisor(Field introductionField) {
        DeclareParents declareParents = (DeclareParents)introductionField.getAnnotation(DeclareParents.class);
        if (declareParents == null) {
            return null;
        } else if (DeclareParents.class == declareParents.defaultImpl()) {
            throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
        } else {
            return new DeclareParentsAdvisor(introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值