zoukankan      html  css  js  c++  java
  • Spring源码解析(六) -- AOP

      最近项目上上了一个功能用到了aop。事情是这样的,本来是我们自己管理调用原生的kafka接口的。不过由于能力有限,决定把kafka交给公司的专业团队。这就有一个需求,要把kafka相关的调用换成公司团队提供的接口。为了不动之前的代码,我采用了aop的方式。对于aop原理还是懂一点点的,源码之前也看过,不过当时没有总结看过就过眼云烟了。这次再重新分析一次aop的实现,并总结记录下。

      1 基本概念

      spring的aop概念很多,关键的有这么几个

      advice:通知,也就是增强的具体逻辑

      pointcut:在某个类的某一个方法,或者某一些方法上切,这种位置信息就是pointcut

      advisor:advice + pointcut

      AnnotationAwareAspectJAutoProxyCreator : 一个beanPostProcessor,正是它在实例化并初始化一个bean之后进行增强,完成代理对象的创建。

      总结下aop代理的流程

      1 在调用getBean过程中,在实例化之前会调用beanPostProcessor的方法

      位置在AbstractAutowireCapableBeanFactory的createBean中的代码段

    try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                }
            }
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }

       AnnotationAwareAspectJAutoProxyCreator 的父类  AbstractAutoProxyCreator  正好实现了 SmartInstantiationAwareBeanPostProcessor

    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
            implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

      所以本篇文章的重点就是,首先分析 AbstractAutoProxyCreator 的postProcessBeforeInstantiation。但是请注意,实际开发中对bean的动态代理并不是在postProcessBeforeInstantiation完成的,

    而是在 postProcessAfterInitialization。但是分析postProcessBeforeInstantiation是很有必要的,因为它会缓存一些信息及完成对全部advisor的解析,并会缓存这些advisor,这些缓存在

    postProcessAfterInitialization的执行时会被调用,如果不分析postProcessBeforeInstantiation,直接读postProcessAfterInitialization的代码就会有疑问,不知道这些缓存值是怎么来的。

      2  AbstractAutoProxyCreator.postProcessBeforeInstantiation   

    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            Object cacheKey = getCacheKey(beanClass, beanName);
    
            if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
                if (this.advisedBeans.containsKey(cacheKey)) {
                    return null;
                }
                if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                    this.advisedBeans.put(cacheKey, Boolean.FALSE);
                    return null;
                }
            }
    
            // Create proxy here if we have a custom TargetSource.
            // Suppresses unnecessary default instantiation of the target bean:
            // The TargetSource will handle target instances in a custom fashion.
            if (beanName != null) {
                TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
                if (targetSource != null) {
                    this.targetSourcedBeans.add(beanName);
                    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                    Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
                    this.proxyTypes.put(cacheKey, proxy.getClass());
                    return proxy;
                }
            }
    
            return null;
        }

      代码不长,而且后半部分一般情况下也不会走到的。 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); 一般情况下都是返回为null所以if分支走不到的。

      这里最重要的就 shouldSkip这里会保存大量的重要信息,不过我们也分析下 isInfrastructureClass

      

    protected boolean isInfrastructureClass(Class<?> beanClass) {
            boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
                    Pointcut.class.isAssignableFrom(beanClass) ||
                    Advisor.class.isAssignableFrom(beanClass) ||
                    AopInfrastructureBean.class.isAssignableFrom(beanClass);
            if (retVal && logger.isTraceEnabled()) {
                logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
            }
            return retVal;
        }

      如果一个类是 Advice,Pointcut,Advisor,AopInfrastructureBean那么一定不能够被aop增强。

      现在分析 shouldSkip,实现类在 AspectJAwareAdvisorAutoProxyCreator中

      

    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
            // TODO: Consider optimization by caching the list of the aspect names
            List<Advisor> candidateAdvisors = findCandidateAdvisors();
            for (Advisor advisor : candidateAdvisors) {
                if (advisor instanceof AspectJPointcutAdvisor) {
                    if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                        return true;
                    }
                }
            }
            return super.shouldSkip(beanClass, beanName);
        }

      该方法本身不难理解,如果要增强的bean的beanName恰好是一个@Aspect注解的类的名字的话,那么是应该跳过的。

      之所以说 shouldSkip是因为 findCandidateAdvisors() 这个方法太重要了。

      实现类在 AnnotationAwareAspectJAutoProxyCreator中

    protected List<Advisor> findCandidateAdvisors() {
            // Add all the Spring advisors found according to superclass rules.
            List<Advisor> advisors = super.findCandidateAdvisors();
            // Build Advisors for all AspectJ aspects in the bean factory.
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
            return advisors;
        }

    这里先把 super是 AbstractAdvisorAutoProxyCreator

      

    protected List<Advisor> findCandidateAdvisors() {
            return this.advisorRetrievalHelper.findAdvisorBeans();
        }
    public List<Advisor> findAdvisorBeans() {
            // Determine list of advisor bean names, if not cached already.
            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!
                    advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Advisor.class, true, false);
                    this.cachedAdvisorBeanNames = advisorNames;
                }
            }
            if (advisorNames.length == 0) {
                return new LinkedList<Advisor>();
            }

      上面只是代码段,没有全部贴出来。因为

      BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false); 一般来说都是返回为空的。因为声明式aop不会在配置文件里明确写advisor,这里只是提一下,

    如果使用配置式aop这里才能拿到配置文件里的advisor。

      回到子类AnnotationAwareAspectJAutoProxyCreator的方法中继续分析。

    public List<Advisor> buildAspectJAdvisors() {
            List<String> aspectNames = this.aspectBeanNames;
    
            if (aspectNames == null) {//aspectNames只会赋值一次,不为null后就不会再进if分支了
                synchronized (this) {
                    aspectNames = this.aspectBeanNames;
                    if (aspectNames == null) {
                        List<Advisor> advisors = new LinkedList<Advisor>();
                        aspectNames = new LinkedList<String>();
                        String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                                this.beanFactory, Object.class, true, false);//拿所有的beanName,挨个扫描
                        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;
                            }
                            if (this.advisorFactory.isAspect(beanType)) { //如果一个bean有注解@Aspect返回为true
                                aspectNames.add(beanName);
                                AspectMetadata amd = new AspectMetadata(beanType, beanName);
                                if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                    MetadataAwareAspectInstanceFactory factory =
                                            new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                    List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);//拿到这个被Aspect注解的所有advisor
                                    if (this.beanFactory.isSingleton(beanName)) {
                                        this.advisorsCache.put(beanName, classAdvisors);//缓存advisor 重要
                                    }
                                    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.emptyList();
            }
            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;
        }

      逻辑很明确就是扫描所有的@Aspect,然后解析其中的每个方法,常见的@Before @After都会在这里被转为Advisor。比如我们可以在一个Aspect中写两个@After注解的方法。那么在这里就会得到

    两个Advisor。

    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
            Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
            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<Advisor>();
            for (Method method : getAdvisorMethods(aspectClass)) {//遍历每一个方法 把每一个方法解析为Advisor
                Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
                if (advisor != null) {
                    advisors.add(advisor);
                }
            }

      

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

      从Advisor的构造函数就能看出来,有一个 Pointcut用来匹配对那个bean增强的, Method candidateAdviceMethod 就是advice,也就是要增强的具体逻辑。

      到这里关键的advisor我们就拿到了并且进行了缓存。具体点说,有两个重要的缓存。

      

    public class BeanFactoryAspectJAdvisorsBuilder {
    
        private final ListableBeanFactory beanFactory;
    
        private final AspectJAdvisorFactory advisorFactory;
    
        private volatile List<String> aspectBeanNames;
    
        private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<String, List<Advisor>>();

      所有的@Aspect注解的类都会被缓存到 aspectBeanNames,而 advisorsCache的key 就是一个@Aspect 的beanName ,values就是该Aspect中包含的Advisor。 

      对于 postProcessBeforeInstantiation的分析就到这里了,重点是postProcessAfterInitialization

      3  AbstractAutoProxyCreator.postProcessAfterInitialization

      首先明确下  postProcessAfterInitialization 是在哪里被调用呢,其实是初始化一个bean的最后阶段

      AbstractAutowireCapableBeanFactory的initializeBean中 

    try {
                invokeInitMethods(beanName, wrappedBean, mbd);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        (mbd != null ? mbd.getResourceDescription() : null),
                        beanName, "Invocation of init method failed", ex);
            }
    
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
            return wrappedBean;

      也就是说当一个bean被实例化,并且已经完成了初始化后,它才被aop增强。这是很符合逻辑的,因为要增强就必须这个bean是完整的。

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean != null) {
                Object cacheKey = getCacheKey(bean.getClass(), beanName);
                if (!this.earlyProxyReferences.contains(cacheKey)) {
                    return wrapIfNecessary(bean, beanName, cacheKey);
                }
            }
            return bean;
        }

      

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
            if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
                return bean;
            }
            if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
                return bean;
            }
            if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
    
            // Create proxy if we have advice.
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                Object proxy = createProxy(
                        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }
    
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

      这里 specificInterceptors 得到的就是InstantiationModelAwarePointcutAdvisor,像我在前一节说的写了两个@After的方法,那么这里就返回两个InstantiationModelAwarePointcutAdvisor

      

      再看看是怎么拿到的Advisor

      

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
            List<Advisor> candidateAdvisors = findCandidateAdvisors();//上节说了,所有advisor会进行缓存,这里直接从缓存拿全部的advisor
            List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//根据切点判断哪些advisor能用来增强这个bean
            extendAdvisors(eligibleAdvisors);
            if (!eligibleAdvisors.isEmpty()) {
                eligibleAdvisors = sortAdvisors(eligibleAdvisors);
            }
            return eligibleAdvisors;
        }

      至于这部分

    if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                Object proxy = createProxy(
                        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }

     就纯粹是JDK动态代理和CGLib代理的内容了。拿到了所有的advisor后,把这些advidor变成责任链模式,根据是@Before还是After 还是@Round 在动态代理的逻辑中 原方法的前后,依次执行。

    4 Advisor和Advice

      有必要分析下获取advisor的逻辑。前面章节介绍过怎么得到advisor,本节具体展开说明下。

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

      看看 InstantiationModelAwarePointcutAdvisorImpl 这个类的构造方法

    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()) {
                // 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;
                this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
            }
        }

      注意 instantiatedAdvice是advisor的一个成员变量。 advice可以理解为对目标类中的目标方法的增强逻辑。代码在 ReflectiveAspectJAdvisorFactory.getAdvice

      代码段

    switch (aspectJAnnotation.getAnnotationType()) {
                case AtBefore:
                    springAdvice = new AspectJMethodBeforeAdvice(
                            candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                    break;
                case AtAfter:
                    springAdvice = new AspectJAfterAdvice(
                            candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                    break;

      可见在@Aspect的bean中的每一个方法上的注解,@Before和@After都会被解析为advice

      之所以,介绍本节是为了下面要介绍的动态代理逻辑

    5 动态代理

      现在拿到了可以适用于某个bean的所有的advisor,动态代理的逻辑适当的讲解一下。来分析下JdkDynamicAopProxy。

    @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 {
                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();
                }
                else if (method.getDeclaringClass() == DecoratingProxy.class) {
                    // There is only getDecoratedClass() declared -> dispatch to proxy config.
                    return AopProxyUtils.ultimateTargetClass(this.advised);
                }
                else 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();
                }
    
                // Get the interception chain for this method.
                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()) {
                    // We can skip creating a MethodInvocation: just invoke the target directly
                    // Note that the final invoker must be an InvokerInterceptor so we know it does
                    // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                    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);
                    // Proceed to the joinpoint through the interceptor chain.
                    retVal = invocation.proceed();
                }
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    在这里还会进行一次过滤,因为选出来的advisor是按照类维度选出来的,该bean的某些方法是不应该被增强的,所以这里还需要按照method维度过滤一次。
    就是那些advisor,但是其实这里是经过了一次转换的,
    chain的元素已经不是advisor了,而是 InterceptorAndDynamicMethodMatcher。
    重点要看的代码就是
    // We need to create a method invocation...
                    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    // Proceed to the joinpoint through the interceptor chain.
                    retVal = invocation.proceed();

      很典型的责任链模式,其实可以好好向spring学学怎么写责任链模式。在new出来一个ReflectiveMethodInvocation时,全部的advisor作为成员变量加入其中。

    @Override
        public Object proceed() throws Throwable {
            //    We start with an index of -1 and increment early.
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                return invokeJoinpoint();
            }
    
            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;
                if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                    return dm.interceptor.invoke(this);
                }
    dm.interceptor.invoke执行的逻辑就是每个advice的执行逻辑。我们可以看看@Before和@After的实现

    AspectJAfterAdvice
    @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
            try {
                return mi.proceed();
            }
            finally {
                invokeAdviceMethod(getJoinPointMatch(), null, null);
            }
        }
    MethodBeforeAdviceInterceptor
    @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
            this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
            return mi.proceed();
        }

      强大的责任链模式。这也能解释为啥before一定在after之前执行,其实spring并没有对before和after进行排序,而是通过这种方法调用栈的顺序优雅实现了。

    6 总结   

      分析了Spring的动态代理后,发现Spring的拓展功能都离不开BeanPostProcessor,动态代理也是基于此。

      在一个bean初始化完成的最后一步,判断该bean是否应该被增强。

      如果应该增强,则对该bean进行增强,同时在spring容器内beanName依旧不变,但是里面的class类型已经不再是原来的了。  

      

      

  • 相关阅读:
    odoo字段
    页签中加按钮 odoo里面
    页签类型按钮上面记录条数获得
    sql语句 这里是取一串数据中的 头 中 尾 几个数据
    python 字典,元组,对象,数组取值方法
    action类型的按钮和object按钮的用法
    数据结构与算法 基于c语言篇
    odoo开发历史订单需求整体思路
    spring框架的ioc和aop
    java注解和反射学习
  • 原文地址:https://www.cnblogs.com/juniorMa/p/13809048.html
Copyright © 2011-2022 走看看