Spring AOP

基于spring 4.1.6

一、配置

只讨论形式的配置,对于ProxyFactory和@Aspect 形式暂不讨论,这两种形式只是前置流程不一样。

配置如下:

 

 

 
 
  
              
   
 
   

二、AOP启动入口

spring AOP所有的一切都要从XML Namespace 说起,也就是AOP的启动入口。



上述文件是Spring容器的配置文件的根标签,Spring解析到上述xmlns:aop后,会去一个Map中寻找其对应的Class全路径,对应关系所在文件位置:

aop jar包 META-INF/spring.handlers

内容:

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

通过这个类全路径可以加载一个类,该类会把IOC配置文件中的AOP配置加载容器中,此处注意,Spring中的很多组件都是这种方式加载到Spring的,另外Dubbo、RabbitMQ等也是如此。

public class AopNamespaceHandler extends NamespaceHandlerSupport {
    /**
     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
     * and '{@code scoped-proxy}' tags.
     */
    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
} 

三、AOP初始化配置

接着上面的Namespace继续分析,下面是Namespacce解析类,代码中会区分默认Namespace和第三方组件Namespace,第三方中间件对接到Spring中,大部分通过Namespace形式对接。DefaultBeanDefinitionDocumentReader.class解析如下:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        // nl中包含所有的类""标签
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                } else {
                    // 每个Node中包含Namespace属性,第三方Namespace解析
                    delegate.parseCustomElement(ele);
                }
            }
        }
    } else {
        // 非标签解析
        delegate.parseCustomElement(root);
    }
}

我们跟【delegate.parseCustomElement(ele)】进去,在BeanDefinitionParserDelegate.class中完成NamespaceHandler的获取,即【二、AOP启动入口】

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    String namespaceUri = getNamespaceURI(ele);
    // Namespace对应的类反射加载
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    // 这里解析 ParserContext包含了bean解析过程中所有的相关配置
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

解析【】,通过this.parsers.get()获取对应的解析类,该解析类参考【org.springframework.aop.config.AopNamespaceHandler】

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    return findParserForElement(element, parserContext).parse(element, parserContext);
}

private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    String localName = parserContext.getDelegate().getLocalName(element);
    BeanDefinitionParser parser = this.parsers.get(localName);
    if (parser == null) {
        parserContext.getReaderContext().fatal(
        "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}

获取到BeanDefinitionParser,跟进到BeanDefinitionParser的实现类ConfigBeanDefinitionParser的parse(....)方法中。configureAutoProxyCreator(parserContext, element)非常关键,后续的针对这个对象进行AOP代理的生成,也是AOP的核心。

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef =
        new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);
    
    // 生成AspectJAwareAdvisorAutoProxyCreator对象,注册到Spring
    configureAutoProxyCreator(parserContext, element);
    
    List childElts = DomUtils.getChildElements(element);
    for (Element elt: childElts) {
        String localName = parserContext.getDelegate().getLocalName(elt);
        if (POINTCUT.equals(localName)) {
            parsePointcut(elt, parserContext);
        } else if (ADVISOR.equals(localName)) {
            parseAdvisor(elt, parserContext);
        } else if (ASPECT.equals(localName)) {
            parseAspect(elt, parserContext);
        }
    }
}

我们只针对ASPECT的解析进行分析,其他标签原理类似:


001.png

1、内部是for循环用于解析所有的

2、进一步解析为RootBeanDefinition;

3、根据标签名称获取其类对象(比如AspectJMethodBeforeAdvice.class),然后获取的属性封装到ConstructorArgumentValues(用于封装构造函数参数);

4、第三步获取的AspectJMethodBeforeAdvice对象已经封装了相应的属性值,这些然后封装到AspectJPointcutAdvisor.class,该类中持有Pointcut、Advice和Order参数,这样就生成了一个Aspect;

5、获取所有的标签

6、解析出来中的表达式属性,并解析成RootBeanDefinition,然后注册到Spring

四、AOP生成代理

第二步已经把所有的标签生成了RootBeanDefinition,configureAutoProxyCreator(parserContext, element)这个方法生成了AOP核心类AspectJAwareAdvisorAutoProxyCreator,该类的类关系图:


002.png

AspectJAwareAdvisorAutoProxyCreator是BeanPostProcessor的实现类,核心就在postProcessAfterInitialization(....)这里,该方法会生成代理类。

Spring的启动过程在AbstractApplicationContext的refresh()进行。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
        
        // 创建BeanFactory,没有就创建,第二步就在这里发生的(BeanDefinition的装载)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
        
        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
            
            // 子类可以获取BeanFactoreanFactory
            invokeBeanFactoryPostProcessors(beanFactory);
            
            // 注册所有实现实现了BeanPostProcessor的类,存储在DefaultListableBeanFactory,beanFactory持有上述加载的所有的Bean,其中AspectJAwareAdvisorAutoProxyCreator也在其中 
            
            // 其中BeanId是org.springframework.aop.config.internalAutoProxyCreator,获取不到就create
            registerBeanPostProcessors(beanFactory);
            
            // Initialize message source for this context.
            initMessageSource();
            
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();
            
            // Initialize other special beans in specific context subclasses.
            onRefresh();
            
            // Check for listener beans and register them.
            registerListeners();
            
            // 最关键的Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
            
            // Last step: publish corresponding event.
            finishRefresh();
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                "cancelling refresh attempt: " + ex);
            }
        
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();
            
            // Reset 'active' flag.
            cancelRefresh(ex);
            
            // Propagate exception to caller.
            throw ex;
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

最关键的是finishBeanFactoryInitialization(beanFactory),实例化所有非懒加载的Bean(回顾Bean的生命周期):

1、通过构造函数实例化

2、设置属性

3、回调BeanNameAware、BeanFactoryAware等接口子类的方法

4、遍历BeanPostProcessor的子类,然后回调他们的实现的两个方法(所谓BeanProcessor回调)

5、回调InitializingBean

6、ini-method属性....后续都是Bean的生命周期中的内容,关键要看第4步

当前Spring中有6个Bean和4个BeanPostProcessor:


003.png
004.png

举例说明,当根据Spring Bean生命周期,math在实例化(create)之前,调用BeanPostProcessor的子类的before方法,下面是代码片段:

005.png

上面的红框是用于调用BeanPostProcessor的前置方法,AOP的代理类在BeanPostProcessor的后置方法中生成。

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {
    
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        // 调用后置处理器
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

接下来调用AbstractAutoProxyCreator的postProcessAfterInitialization(....):

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

我们跟wrapIfNecessary(bean, beanName, cacheKey),该方法只对math做了进一步的处理:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // this.advisedBeans这个map中包含beanI->boolean,不可以进一步则进入到下一步判断
    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;
    }
    
    // 当前beanName如果有advice则可以为其创建代理,这里先去查找符合条件的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;
}

查找代理,接下来对当前beanName的符合条件的Advice进行查找:

AbstractAdvisorAutoProxyCreator

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
    // 查找Advice
    List advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

protected List findEligibleAdvisors(Class beanClass, String beanName) {
    // 所有的潜在Advice
    List candidateAdvisors = findCandidateAdvisors();
    // 选取符合条件的Advice
    List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);    // 在链表头添加一个默认ExposeInvocationInterceptor
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

/**
 * Search the given candidate Advisors to find all Advisors that
 * can apply to the specified bean.
 * @param candidateAdvisors the candidate Advisors
 * @param beanClass the target's bean class
 * @param beanName the target's bean name
 * @return the List of applicable Advisors
 * @see ProxyCreationContext#getCurrentProxiedBeanName()
 */
protected List findAdvisorsThatCanApply(
      List candidateAdvisors, Class beanClass, String beanName) {

   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

AopUtils

public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List eligibleAdvisors = new LinkedList();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
         eligibleAdvisors.add(candidate);
      }
   }
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         // already processed
         continue;
      }
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}

public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
   if (advisor instanceof IntroductionAdvisor) {
      return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
   }
   else if (advisor instanceof PointcutAdvisor) {
      PointcutAdvisor pca = (PointcutAdvisor) advisor;
      return canApply(pca.getPointcut(), targetClass, hasIntroductions);
   }
   else {
      // It doesn't have a pointcut so we assume it applies.
      return true;
   }
}

/**
 * Can the given pointcut apply at all on the given class?
 * 

This is an important test as it can be used to optimize * out a pointcut for a class. * @param pc the static or dynamic pointcut to check * @param targetClass the class to test * @param hasIntroductions whether or not the advisor chain * for this bean includes any introductions * @return whether the pointcut can apply on any method */ /** 获取pc的正则表达式,然后获取target的方法列表和正则表达式对比,满足返回true **/ public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } // Pointcut的正则表达式 MethodMatcher methodMatcher = pc.getMethodMatcher(); IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set> classes = new LinkedHashSet>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class clazz : classes) { Method[] methods = clazz.getMethods(); // 目标对象的方法 for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }

获取了所有的Adivce后,就可以生成代理对象了:

protected Object createProxy(
        Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
    
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
    // proxy-target-class属性
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        } else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    
    // Advice封装到ProxyFactory
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    for (Advisor advisor : advisors) {
        proxyFactory.addAdvisor(advisor);
    }
    
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);
    
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    // 创建代理
    return proxyFactory.getProxy(getProxyClassLoader());
}

// 根据配置生成代理
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        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.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    } else {
        return new JdkDynamicAopProxy(config);
    }
}

public Object getProxy(ClassLoader classLoader) {
    // createAopProxy()获取代理,然后具体细节在getProxy()中
    return createAopProxy().getProxy(classLoader);
}

你可能感兴趣的:(Spring AOP)