spring aop 之增强器处理

来源:互联网 发布:js 二维数组 indexof 编辑:程序博客网 时间:2024/06/05 07:39

spring aop 源码分析之增强器获取

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {    //获取标记AspectJ的类        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();    //获取标记Aspect的name           String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();        validate(aspectClass);        // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator        // so that it will only instantiate once.        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);        List<Advisor> advisors = new LinkedList<>();        //遍历增强类方法(除了@Pointcut标注的方法)        for (Method method : getAdvisorMethods(aspectClass)) {            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);        }        // 获取DeclareParents注解        for (Field field : aspectClass.getDeclaredFields()) {            Advisor advisor = getDeclareParentsAdvisor(field);            if (advisor != null) {                advisors.add(advisor);            }        }        return advisors;    }

千呼万唤始出来 这里最重要的方法来了getAdvisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,            int declarationOrderInAspect, String aspectName) {        validate(aif.getAspectMetadata().getAspectClass());//切入点的获取         AspectJExpressionPointcut ajexp =getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());        if (ajexp == null) {            return null;        }//根据切点信息生成增强器        return new InstantiationModelAwarePointcutAdvisorImpl(                this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);    }
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {//获取方法上的注解 AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);        if (aspectJAnnotation == null) {            return null;        }//使用AspectJExpressionPointcut封装获取的信息                AspectJExpressionPointcut ajexp =                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());        return ajexp;    }
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {        Class<?>[] classesToLookFor = new Class<?>[] {                Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};        for (Class<?> c : classesToLookFor) {            AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);            if (foundAnnotation != null) {                return foundAnnotation;            }        }        return null;    }

根据切入点信息生成增强。

public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,            MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {        this.declaredPointcut = ajexp;        this.method = method;        this.atAspectJAdvisorFactory = af;        this.aspectInstanceFactory = aif;        this.declarationOrder = declarationOrderInAspect;        this.aspectName = aspectName;        if (aif.getAspectMetadata().isLazilyInstantiated()) {            // Static part of the pointcut is a lazy type.            Pointcut preInstantiationPointcut =                    Pointcuts.union(aif.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, aif);            this.lazy = true;        }        else {            // A singleton aspect.            this.instantiatedAdvice = `instantiateAdvice`(this.declaredPointcut);            this.pointcut = declaredPointcut;            this.lazy = false;        }    }
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {        return this.atAspectJAdvisorFactory.getAdvice(                this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);    }

//@Before(“say()”),@After(“say()”)增强器是不一样的,所以就需要不同的增强器完成不同的逻辑。下面方法的swtich case 就一目了然了

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,            MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {        Class<?> candidateAspectClass = aif.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() + "]");        }        if (logger.isDebugEnabled()) {            logger.debug("Found AspectJ method: " + candidateAdviceMethod);        }        AbstractAspectJAdvice springAdvice;    //根据不同的注解类型封装不同的增强器        switch (aspectJAnnotation.getAnnotationType()) {            case AtBefore:                springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);                break;            case AtAfter:                springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);                break;            case AtAfterReturning:                springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();                if (StringUtils.hasText(afterReturningAnnotation.returning())) {                    springAdvice.setReturningName(afterReturningAnnotation.returning());                }                break;            case AtAfterThrowing:                springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());                }                break;            case AtAround:                springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);                break;            case AtPointcut:                if (logger.isDebugEnabled()) {                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");                }                return null;            default:                throw new UnsupportedOperationException(                        "Unsupported advice type on method " + candidateAdviceMethod);        }        // Now to configure the advice...        springAdvice.setAspectName(aspectName);        springAdvice.setDeclarationOrder(declarationOrderInAspect);        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);        if (argNames != null) {            springAdvice.setArgumentNamesFromStringArray(argNames);        }        springAdvice.calculateArgumentBindings();        return springAdvice;    }

我们看一下AspectJMethodBeforeAdvice的实现

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {    public AspectJMethodBeforeAdvice(            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {        super(aspectJBeforeAdviceMethod, pointcut, aif);    }    @Override    public void before(Method method, Object[] args, Object target) throws Throwable {        invokeAdviceMethod(getJoinPointMatch(), null, null);    }    @Override    public boolean isBeforeAdvice() {        return true;    }    @Override    public boolean isAfterAdvice() {        return false;    }}

这个before方法是在什么时候调用的呢

假设的代理类是通过jdk方式
看一下JdkDynamicAopProxy的invoke方法

@Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        MethodInvocation invocation;        Object oldProxy = null;        boolean setProxyContext = false;        TargetSource targetSource = this.advised.targetSource;        Class<?> targetClass = null;        Object target = null;        try {        //equals方法处理            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {                // The target does not implement the equals(Object) method itself.                return equals(args[0]);            }    //hash方法处理                  if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {                // The target does not implement the hashCode() method itself.                return hashCode();            }            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;            }            // May be null. Get as late as possible to minimize the time we "own" the target,            // in case it comes from a pool.            target = targetSource.getTarget();            if (target != null) {                targetClass = target.getClass();            }            //获取当前方法的拦截器链            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);            // Check whether we have any advice. If we don't, we can fallback on direct            // reflective invocation of the target, and avoid creating a MethodInvocation.            if (chain.isEmpty()) {                //如果没有任何拦截器那么直接调用切点方法                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);            }            else {                //将拦截器封装在ReflectiveMethodInvocation                // 便于使用proceed进行链接表用拦截器                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);                //执行拦截器链                retVal = invocation.proceed();            }            // Massage return value if necessary.            Class<?> returnType = method.getReturnType();            if (retVal != null && retVal == target && 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);            }        }    }
@Override    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) {            // 动态匹配            InterceptorAndDynamicMethodMatcher dm =                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {                return dm.interceptor.invoke(this);            }            else {                // 不匹配不执行拦截器                return proceed();            }        }        else {            /*普通拦截器,直接调用拦截器,比如:            *AspectJAroundAdvice            *AspectJAfterAdvice            *MethodBeforeAdviceInterceptor            *ExposeInvocationInterceptor            *DelegatePerTargetObjectIntroductionInterceptor            */            //将this作为参数传递保证当前实例中调用链的执行            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);        }    }
原创粉丝点击