6.4Spring的AOP的解析——候选代理的获取

2019-02-12  本文已影响0人  szhlcy

findCandidateAdvisors方法的实现由AnnotationAwareAspectJAutoProxyCreator类完成的(父类为AbstractAdvisorAutoProxyCreator)。

    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        //当使用注解的方式配置AOP的时候并不是不使用对XML配置,在这里调用父类方法加载配置文件中的AOP声明
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }

先看super.findCandidateAdvisors()方法

public List<Advisor> findAdvisorBeans() {
        // 确定代理bean名称列表。
        String[] advisorNames = null;
        synchronized (this) {
            advisorNames = this.cachedAdvisorBeanNames;
            if (advisorNames == null) {
                // Do not initialize FactoryBeans here: We need to leave all regular beans uninitialized to let the auto-proxy creator apply to them!
                //按照代理抽象类Advisor的class获取所有的当前beanFactory中Advisor类型的bean的beanName
                advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Advisor.class, true, false);
                this.cachedAdvisorBeanNames = advisorNames;
            }
        }
        //如果没有符合的列表,就返回空
        if (advisorNames.length == 0) {
            return new LinkedList<Advisor>();
        }

        List<Advisor> advisors = new LinkedList<Advisor>();
        for (String name : advisorNames) {
            //判断给定name的bean是否符合条件,默认返回true
            if (isEligibleBean(name)) {
                //如果当前bean正在创建中就不处理
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipping currently created advisor '" + name + "'");
                    }
                }
                //否则把bean的name加入到列表中
                else {
                    try {
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    }
                    catch (BeanCreationException ex) {
                        Throwable rootCause = ex.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {
                            BeanCreationException bce = (BeanCreationException) rootCause;
                            if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Skipping advisor '" + name +
                                            "' with dependency on currently created bean: " + ex.getMessage());
                                }
                                // Ignore: indicates a reference back to the bean we're trying to advise.
                                // We want to find advisors other than the currently created bean itself.
                                continue;
                            }
                        }
                        throw ex;
                    }
                }
            }
        }
        return advisors;
    }

AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAdvisorAutoProxyCreator,在实现获取增强的方法中除了保留父类的获取配文件中定义的增强外,同时添加了获取Bean 的注解增强的功能,实现是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来实现的。

    private List<String> aspectBeanNames;

    private final ListableBeanFactory beanFactory;

    //在当前bean工厂中查找所有符合条件的Advisor bean,忽略FactoryBeans并排除当前正在创建的bean
    public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = null;

        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<Advisor>();
                aspectNames = new LinkedList<String>();
                //按照代理的class获取所有的beanName
                String[] beanNames =
                        BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
                //循环所有的beanName找出对应的增强方法
                for (String beanName : beanNames) {
                    //不符合条件的bean则略过,有子类定义规则,默认返回true
                    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
                    //获取对应的bean的类型
                    Class beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    //如果存在Aspect注解,AbstractAspectJAdvisorFactory类中实现了isAspect方法,根据是否有注解判断
                    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)) {
                                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;
            }
        }

        if (aspectNames.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        //记录在缓存中
        List<Advisor> advisors = new LinkedList<Advisor>();
        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方法去实现this.advisorFactory.getAdvisors(factory);
 ReflectiveAspectJAdvisorFactory类的getAdvisors方法是实现了AspectJAdvisorFactory接口的。

    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
        //获取标记为Aspect的类的class
        final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
        //获取标记为Aspect的name
        final String aspectName = maaif.getAspectMetadata().getAspectName();
        //验证
        validate(aspectClass);

        // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
        // so that it will only instantiate once.
        //先懒加载一次需要被包装的传进来的AspectInstanceFactory
        final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(maaif);

        final List<Advisor> advisors = new LinkedList<Advisor>();
        //获取需要修饰的方法
        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);
        }

        // Find introduction fields.
        //获取DeclareParents注解
        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        return advisors;
    }

    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new LinkedList<Method>();
        ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
            public void doWith(Method method) throws IllegalArgumentException {
                // Exclude pointcuts
                //如果方法声明为Pointcut那么就不处理
                if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                    methods.add(method);
                }
            }
        });
        Collections.sort(methods, METHOD_COMPARATOR);
        return methods;
    }

 函数中首先完成了对增强器的获取,包括获取注解以及根据注解生成增强的步骤,然后考虑到在配置中可能会将增强配置成延迟初始化,那么需要在首位加入同步实例化增强器保证增强使用之前的实例化,最后是对DeclareParents注解的获取。

1.获取普通增强器

 普通增强器的获取逻辑通过getAdvisor方法(不是getAdvisors)实现,实现步骤包括对切点的注解的获取以及根据注解信息生成增强。

    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);
    }
1.切点信息的获取

 获取切点信息就是指定注解的表达式信息的获取,比如@Before("test()")

    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]);
        //提取得到的注解中的表达式如:
        //@Pointcut("execution(* *.*test*(..))")中的execution(* *.*test*(..))
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        return ajexp;
    }
    
    protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
        //设置敏感的注解类
        Class<? extends Annotation>[] classesToLookFor = new Class[] {
                Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
        for (Class<? extends Annotation> c : classesToLookFor) {
            AspectJAnnotation foundAnnotation = findAnnotation(method, c);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }
        return null;
    }

    //获取制定方法上的注解并使用AspectJAnnotation封装
    private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
        A result = AnnotationUtils.findAnnotation(method, toLookFor);
        if (result != null) {
            return new AspectJAnnotation<A>(result);
        }
        else {
            return null;
        }
    }
2。根据切点信息生成增强

 所有的增强都由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl统一封装的。

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

 在封装的过程中只是简单地将信息封装在类的实例中,所有的信息单地赋值,在实例初始化的过程总还完成了对于增强器的初始化。因为不同的增强所体现的逻辑是不同的,比如@Before("test()")与@After("test()")标签的不同就是增强器增强的位置不同,所以就需要不同的增强器来完成不同的逻辑,而根据注解中的信息初始化对应的增强器就是在instantiateAdvice函数中完成。

    private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
        return this.atAspectJAdvisorFactory.getAdvice(
                this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
    }
    
    //这个方法是ReflectiveAspectJAdvisorFactory类实现了AspectJAdvisorFactory接口的方法
    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;
    }

 从方法中可以看出,Spring会根据不同的注解生成不同的增强器,例如AtBefore会对应AspectJMethodBeforeAdvice,而在AspectJMethodBeforeAdvice中完成了增强方法的逻辑。接下来对常用的增强器进行分析:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

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

}

 其中的属性MethodBeforeAdvice代表着前置增强的AspectJMethodBeforeAdvice,跟踪Before方法:

    public void before(Method method, Object[] args, Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
        
    /**
     * Invoke the advice method.
     * @param jpMatch the JoinPointMatch that matched this execution join point    
     * @param returnValue the return value from the method execution (may be null)
     * @param ex the exception thrown by the method execution (may be null)
     * @return the invocation result
     * @throws Throwable in case of invocation failure
     */
    protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
    }
    
    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
            actualArgs = null;
        }
        try {
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            // TODO AopUtils.invokeJoinpointUsingReflection
            //激活增强方法
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    this.aspectJAdviceMethod + "]; pointcut expression [" +
                    this.pointcut.getPointcutExpression() + "]", ex);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }

invokeAdviceMethodWithGivenArgs方法中的aspectJAdviceMethod正是对于前置增强的方法,在这里实现了调用

 后置增强与前置增强有稍许不一致的地方。前置增强,大致的结构是在拦截器链中放置MethodBeforeAdviceInterceptor,而在MethodBeforeAdviceInterceptor中又放置了AspectJMethodBeforeAdvice,并在调用invoke时首先串联调用。但是后置增强的时候却不一样,没有提供中间的类,而是直接在拦截器链中使用了中间的AspectJAfterAdvice。

public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {

    public AspectJAfterAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {

        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }

    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        finally {
            //激活增强方法
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }

    public boolean isBeforeAdvice() {
        return false;
    }

    public boolean isAfterAdvice() {
        return true;
    }

}

2.增加同步实例化增强器

 如果寻找的增强器不为空而且又配置了增强延迟初始化,那么就需要在首位加入同步实例化增强器。同步实例化增强器SyntheticInstantiationAdvisor如下。

    protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {

        public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
            super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
                //目标方法前调用,类似@Before
                public void before(Method method, Object[] args, Object target) {
                    // Simply instantiate the aspect
                    //简单初始化aspect
                    aif.getAspectInstance();
                }
            });
        }
    }

3.获取DeclareParents注解

DeclareParents主要用于引介增强的注解形式的实现,而其实现方式的普通增强类似,只是使用DeclareParentsAdvisor功能进行封装了

    private Advisor getDeclareParentsAdvisor(Field introductionField) {
        DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
        if (declareParents == null) {
            // Not an introduction field
            return null;
        }

        if (DeclareParents.class.equals(declareParents.defaultImpl())) {
            // This is what comes back if it wasn't set. This seems bizarre...
            // TODO this restriction possibly should be relaxed
            throw new IllegalStateException("defaultImpl must be set on DeclareParents");
        }
        
        return new DeclareParentsAdvisor(
                introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
    }

 获取到了代理的列表之后就是找合适的代理了寻找匹配的代理增强

上一篇下一篇

猜你喜欢

热点阅读