Spring源码阅读(六)—AOP获取增强

xiaoxiao2021-02-28  97

Spring源码阅读(六)—AOP获取增强

本文主要分析了AOP功能实现中的自定义标签解析和增强的获取

个人主页:tuzhenyu’s page 原文地址:Spring源码阅读(六)—AOP获取增强

(0) Spring AOP实现的主要步骤

解析AOP自定义标签,注册AnnotationAwareAspectJAutoProxyCreator自动代理创建器

获取增强

创建代理

(1) 解析AOP自定义标签

AOP功能实现的最基本入口在XML配置文件中的AOP功能的开启; <aop:aspectj-autoproxy> 在容器初始化解析XML配置文件会将标签分为普通标签和自定义标签分别进行解析处理. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { 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 { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } } aop标签属于自定义标签会调用相应的处理器进行处理 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } 从NamespaceHandler中获取aop的aspectj-autoproxy对应的解析器是AspectJAutoProxyBeanDefinitionParser public void init() { this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } 所有解析器都是由 BeanDefinitionParser 接口的统一实现,入口都是从 parse函数开始的 public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null; }

registerAspectJAnnotationAutoProxyCreatorIfNecessary 函数是 AnnotationAwareAspectJAutoProxyCreator 注册的地方,也是注册的主要逻辑实现的地方。主要实现了一下三个功能:

AnnotationAwareAspectJAutoProxyCreator的注册或升级

对于 proxy-target-class 以及 expose-proxy 属性的处理,用于判断是否强制使用CGLIB代理模式

注册组件并通知,便于监听器作进一步处理.

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); } 至此,aop自定义标签完成了解析,同时也将AnnotationAwareAspectJAutoProxyCreator注册到了处理器中.

(2) AOP代理实现的入口

spring 容器启动,在每个bean实例话过程中会首先尝试到缓存中获取,获取上失败后会调用createBean()方法从头创建bean.在调用doCreateBean()方法正式创建之前会调用resolveBeforeInstantiation()方法尝试是否创建代理类替代真正的实例,如果创建成功则直接返回跳过后续的真正创建过程,如果创建失败则继续创建bean实例. Object beanInstance; try { beanInstance = this.resolveBeforeInstantiation(beanName, mbd); if(beanInstance != null) { return beanInstance; } } catch (Throwable var6) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6); } 在resolveBeforeInstantiation()方法中会调用提前注册的处理器AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()方法实现代理的创建 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) { Class targetType = this.determineTargetType(beanName, mbd, new Class[0]); if(targetType != null) { bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if(bean != null) { bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null); } return bean; } postProcessAfterInitialization()方法调用wrapIfNecessary()方法进行代理的实现 public Object <strong>postProcessAfterInitialization</strong>(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } wrapIfNecessary()方法实现了aop实现的主要逻辑,调用getAdvicesAndAdvisorsForBean()提取当前bean 的所有增强方法,然后调用createProxy()方法创建具体代理. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.containsKey(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; } Object[] specificInterceptors = <strong>getAdvicesAndAdvisorsForBean</strong>(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; }

(3) AOP增强的获取

getAdvicesAndAdvisorsForBean()主要是通过调用findEligibleAdvisors()方法用来获取该bean的增强列表.主要步骤包括:

寻找所有增强

从所有增强中获取适合该bean的增强.

protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }

findCandidateAdvisors()方法是用来获取所有的增强,主要步骤包括:

获取所有在beanFactory中注册的beanName

遍历所有的beanName,判断是否为声明为AspectJ的类,如果是则进行进一步处理

对标记为AspectJ注解的类进行增强器的提取

将提取结果放入缓存

protected List<Advisor> findCandidateAdvisors() { List advisors = super.findCandidateAdvisors(); advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; } public List<Advisor> buildAspectJAdvisors() { List aspectNames = null; synchronized(this) { aspectNames = this.aspectBeanNames; if(aspectNames == null) { LinkedList var16 = new LinkedList(); LinkedList var15 = new LinkedList(); String[] var17 = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); String[] var18 = var17; int var19 = var17.length; for(int var7 = 0; var7 < var19; ++var7) { String beanName = var18[var7]; if(this.isEligibleBean(beanName)) { Class beanType = this.beanFactory.getType(beanName); if(beanType != null && this.advisorFactory.isAspect(beanType)) { var15.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { BeanFactoryAspectInstanceFactory factory1 = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List classAdvisors = this.advisorFactory.getAdvisors(factory1); if(this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory1); } var16.addAll(classAdvisors); } else { if(this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name \'" + beanName + "\' is a singleton, but aspect instantiation model is not singleton"); } PrototypeAspectInstanceFactory var20 = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, var20); var16.addAll(this.advisorFactory.getAdvisors(var20)); } } } } this.aspectBeanNames = var15; return var16; } } 调用findAdvisorsThatCanApply()方法从所有增强中获取适合该bean的增强 protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); List var4; try { var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName((String)null); } return var4; }

(4) 总结

AOP功能的实现是从XML配置文件中的aop标签解析开始的,标签的解析会注册代理自动创建器用于后续的调用.当从容器中尝试获取bean的时候会在真正创建bean之前尝试创建代理,创建代理主要包括增强的获取和代理的创建两部分,这篇博文主要分析了增强获取的主要流程.

转载请注明原文地址: https://www.6miu.com/read-75245.html

最新回复(0)