由于字数超过了限制,因此分红了三篇,承接上篇:
https://www.jianshu.com/p/46e27afd7d96java
代码过宽,能够shift + 鼠标滚轮 左右滑动查看node
<!-- 事务处理,事务只针对service层 --> <aop:config> <aop:pointcut id="pc" expression="execution(public * cn.mrdear.service.impl..*(..))" /> <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" /> </aop:config>
非默认名称空间的标签,走的是这个方法spring
//4.若是该标签属于其余的名称空间好比:context,aop等 //xmlns:aop="http://www.springframework.org/schema/aop" //xmlns:context="http://www.springframework.org/schema/context" delegate.parseCustomElement(ele);
进入这个方法,在BeanDefinitionParserDelegate类中express
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { //拿到标签对应的名称空间URI //好比:http://www.springframework.org/schema/aop String namespaceUri = getNamespaceURI(ele); //4.1拿到名称空间处理器解析器,去解析URI,获取名称空间处理器 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } //4.2经过处理器的某个解析器解析对应标签 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
DefaultNamespaceHandlerResolver是名称空间处理器解析器的默认实现app
跟踪标记4.1的方法ide
//4.1拿到名称空间处理器解析器,去解析URI,获取名称空间处理器 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); /** * Locate the {@link NamespaceHandler} for the supplied namespace URI * from the configured mappings. * * 根据提供的 namespace URI 从配置映射中找到 NamespaceHandler */ @Override public NamespaceHandler resolve(String namespaceUri) { //拿处处理器解析器中全部的处理器 Map<String, Object> handlerMappings = getHandlerMappings(); //拿到指定的处理器 Object handlerOrClassName = handlerMappings.get(namespaceUri); //若是为null就返回null if (handlerOrClassName == null) { return null; } //若是是实例就返回实例 else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } //不然就必定是字符串 else { String className = (String) handlerOrClassName; try { //经过加载器生成处理器的Class对象 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); //必需要实现NamespaceHandler接口 if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } //实例化一个 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); //初始化,进入这个方法,里面初始化多个解析器 namespaceHandler.init(); //用实例覆盖原先handlerMappings中的字符串 handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", ex); } catch (LinkageError err) { throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", err); } } } /** * 这个方法在类AopNamespaceHandler中 * * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}' * and '{@code scoped-proxy}' tags. * * 为config、spring-configured、aspectj-autoproxy以及scoped-proxy标签注册BeanDefinitionParsers */ @Override public void init() { //这里面每个解析器都对应着AOP名称空间下的一个标签 //不一样的处理器注册的解析器都不同 //这里随便找一个解析器,查看他的注册流程 // 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()); } /** * 此方法在类AopNamespaceHandler的父类NamespaceHandlerSupport中 * * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to * handle the specified element. The element name is the local (non-namespace qualified) * name. * * 子类能够调用这个方法注册指定的BeanDefinitionParser去处理相关的标签 * 这个elementName是个局部名称(不包含名称空间) */ protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { //将解析器注册到这个名称空间处理器的parsers属性中, //parsers是一个HashMap this.parsers.put(elementName, parser); }
跟踪标记4.2的方法oop
进入处理器的抽象父类NamespaceHandlerSupport中ui
入参传递了一个ParserContext解析器上下文,ParserContext中拿到了阅读器上下文的引用,代理的引用,containingBd在这里为nullthis
//4.2经过处理器的某个解析器解析对应标签 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); /** * Parses the supplied {@link Element} by delegating to the {@link BeanDefinitionParser} that is * registered for that {@link Element}. * * 经过委派给根据对应标签所注册的解析器,来解析提供的标签 */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { //将标签名称做为key,去处理器内部的parsers属性中,获取对应的value值,也就是解析器 //利用解析器来解析这个标签,进入这个方法。 return findParserForElement(element, parserContext).parse(element, parserContext); } /** * 由于解析是的<aop:config>,因此该方法在ConfigBeanDefinitionParser类中 * * Parse the specified {@link Element} and register the resulting * {@link BeanDefinition BeanDefinition(s)} with the * {@link org.springframework.beans.factory.xml.ParserContext#getRegistry() BeanDefinitionRegistry} * embedded in the supplied {@link ParserContext}. * <p>Implementations must return the primary {@link BeanDefinition} that results * from the parse if they will ever be used in a nested fashion (for example as * an inner tag in a {@code <property/>} tag). Implementations may return * {@code null} if they will <strong>not</strong> be used in a nested fashion. * * 解析指定的标签,并注册最终的结果bean Definition到内嵌在ParserContext中的bean工厂中 */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { //一个组件集合,里面包含了多个组件,以标签名(包含了名称空间)做为名称,好比aop:config //里面包含的多个组件就是aop:config的子标签,包含对标签属性的描述 //好比xml中pointcut子标签就是一个组件,advisor子标签也是一个组件 //这个组件记录了子标签的name属性或者expression属性,根据不一样子标签,属性不同 CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); //将组件集合保存在parserContext解析器上下文的containingComponents属性中 parserContext.pushContainingComponent(compositeDef); //4.2.1配置自动代理建立器 configureAutoProxyCreator(parserContext, element); //配置完建立器后拿到全部子标签 List<Element> childElts = DomUtils.getChildElements(element); for (Element elt: childElts) { //拿到全部子标签localName,也就是不包括名称空间的标签名字 String localName = parserContext.getDelegate().getLocalName(elt); //若是子标签是pointcut if (POINTCUT.equals(localName)) { //4.2.2解析pointcut子标签 parsePointcut(elt, parserContext); } //若是子标签是advisor else if (ADVISOR.equals(localName)) { //4.2.3解析advisor子标签 parseAdvisor(elt, parserContext); } //若是子标签是aspect else if (ASPECT.equals(localName)) { //4.2.4解析aspect子标签 parseAspect(elt, parserContext); } } //4.2.5弹出组件 parserContext.popAndRegisterContainingComponent(); return null; }
跟踪标记4.2.1的方法spa
此方法在类ConfigBeanDefinitionParser中实现
//4.2.1配置自动代理建立器 configureAutoProxyCreator(parserContext, element); /** * Configures the auto proxy creator needed to support the {@link BeanDefinition BeanDefinitions} * created by the '{@code <aop:config/>}' tag. Will force class proxying if the * '{@code proxy-target-class}' attribute is set to '{@code true}'. * * 配置自动代理建立器,支持由<aop:config/>标签建立的beanDefinition * 若是标签的proxy-target-class属性被设置为true,那么强制代理 */ private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); } /** * 进入AopNamespaceUtils类中的静态方法 */ public static void registerAspectJAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { //4.2.1.1若是必要的话注册AspectJ自动代理建立器 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); //4.2.1.2若是必要的话使用CLass代理 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); //4.2.1.3若是必要的话注册组件 registerComponentIfNecessary(beanDefinition, parserContext); }
先跟踪标记4.2.1.1的方法
该方法在AopConfigUtils类中实现
//4.2.1.1若是必要的话注册AspectJ自动代理建立器 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { //传递了一个AspectJAwareAdvisorAutoProxyCreator的Class,进入这个方法 return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //工厂中是否已经注册了org.springframework.aop.config.internalAutoProxyCreator if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); //若是已经有注册了internalAutoProxyCreator,而且和入参传递的不是同一个Class, //那么就根据优先级进行选择 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { //类AopConfigUtils中有个ArrayList属性APC_PRIORITY_LIST,在类静态构造中依次加入了 //几个建立器,这个方法就是查找某个建立器在APC_PRIORITY_LIST中的索引,若是没有找到就报错 int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); //internalAutoProxyCreator的索引为0,入参的AspectJAwareAdvisorAutoProxyCreator //索引为1,后者要大,因此从新设置下apcDefinition的beanClass if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } //直接返回null return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
跟踪标记4.2.1.2
此方法的实如今AopNamespaceUtils类中
//4.2.1.2若是必要的话使用CLass代理 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) { if (sourceElement != null) { //查看是否有设置proxy-target-class属性 boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } //查看是否有设置expose-proxy属性 boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
跟踪标记4.2.1.3
此方法的实如今AopNamespaceUtils类中
//4.2.1.3若是必要的话注册组件 registerComponentIfNecessary(beanDefinition, parserContext); private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) { //由于前面建立器中的beanClass用了新的那个,因此返回的beanDefinition为null, //这里的beanDefinition也就为null了,跳过 if (beanDefinition != null) { BeanComponentDefinition componentDefinition = new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME); parserContext.registerComponent(componentDefinition); } }
跟踪标记4.2.2
此方法的实如今ConfigBeanDefinitionParser类中
//4.2.2解析pointcut子标签 parsePointcut(elt, parserContext); /** * Parses the supplied {@code <pointcut>} and registers the resulting * Pointcut with the BeanDefinitionRegistry. * * 解析<pointcut>标签,注册结果到bean工厂中 */ private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { //拿到id和expression的属性 String id = pointcutElement.getAttribute(ID); String expression = pointcutElement.getAttribute(EXPRESSION); AbstractBeanDefinition pointcutDefinition = null; try { //解析前放入,解析后弹出 this.parseState.push(new PointcutEntry(id)); //建立一个bean definition,提早指定AspectJExpressionPointcut.class为beanClass //默认多例,同步,将expression添加到bean definition的propertyValues中 pointcutDefinition = createPointcutDefinition(expression); //这里走null pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); String pointcutBeanName = id; //有无id走不一样方法 if (StringUtils.hasText(pointcutBeanName)) { //走的工厂注册方法,上面跟踪过,能够回看3.3.1标记 parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); } else { pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); } //注册组件,进入这个方法查看 parserContext.registerComponent( new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression)); } finally { //解析前放入,解析后弹出 this.parseState.pop(); } return pointcutDefinition; } /** * 此方法的实如今ParserContext类中 */ public void registerComponent(ComponentDefinition component) { //拿到parserContext中containingComponents属性里的最后一个元素 //这个元素是在4.2标记中parse方法里被放入,组件名称叫作aop:config CompositeComponentDefinition containingComponent = getContainingComponent(); if (containingComponent != null) { //增长嵌套的组件,进入这个方法 containingComponent.addNestedComponent(component); } else { this.readerContext.fireComponentRegistered(component); } } /** * 这个方法在CompositeComponentDefinition类中 * * Add the given component as nested element of this composite component. * * 增长指定的组件,做为这个组件的嵌套元素 */ public void addNestedComponent(ComponentDefinition component) { Assert.notNull(component, "ComponentDefinition must not be null"); //也就是在CompositeComponentDefinition类中的nestedComponents属性中, //将入参的component添加进去 //nestedComponents是一个LinkedList this.nestedComponents.add(component); }
跟踪标记4.2.3
此方法的实如今ConfigBeanDefinitionParser类中
//4.2.3若是子标签是advisor parseAdvisor(elt, parserContext); /** * Parses the supplied {@code <advisor>} element and registers the resulting * {@link org.springframework.aop.Advisor} and any resulting {@link org.springframework.aop.Pointcut} * with the supplied {@link BeanDefinitionRegistry}. * * 解析 <advisor> 标签,并注册 Advisor 结果和其余 Pointcut 结果到工厂中 */ private void parseAdvisor(Element advisorElement, ParserContext parserContext) { // 4.2.3.1 建立一个顾问的 BeanDefinition AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); String id = advisorElement.getAttribute(ID); try { this.parseState.push(new AdvisorEntry(id)); String advisorBeanName = id; if (StringUtils.hasText(advisorBeanName)) { // 注册到工厂 parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); } else { // 没有 id 属性,生成默认规则的名字再注册到工厂 advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); } // 4.2.3.2 解析切入点属性 Object pointcut = parsePointcutProperty(advisorElement, parserContext); // advisorDef 添加 pointcut 等属性,而后将 advisorDef 注册到组件组合定义中 if (pointcut instanceof BeanDefinition) { advisorDef.getPropertyValues().add(POINTCUT, pointcut); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut)); } else if (pointcut instanceof String) { advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut)); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef)); } } finally { this.parseState.pop(); } }
跟踪标记4.2.3.1
此方法的实如今ConfigBeanDefinitionParser类中
// 4.2.3.1 建立一个顾问的 BeanDefinition AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); /** * Create a {@link RootBeanDefinition} for the advisor described in the supplied. Does <strong>not</strong> * parse any associated '{@code pointcut}' or '{@code pointcut-ref}' attributes. * * 建立一个 advisor 的 RootBeanDefinition,不解析任何关联的 pointcut 或 pointcut-ref 属性 */ private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) { RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class); advisorDefinition.setSource(parserContext.extractSource(advisorElement)); // 拿到 advisor 标签上的 advice-ref 属性 String adviceRef = advisorElement.getAttribute(ADVICE_REF); if (!StringUtils.hasText(adviceRef)) { parserContext.getReaderContext().error( "'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot()); } else { // 添加到属性键值对集合中 advisorDefinition.getPropertyValues().add( ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef)); } // 拿到标签上的 order 属性 if (advisorElement.hasAttribute(ORDER_PROPERTY)) { // 添加到属性键值对集合中 advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY)); } return advisorDefinition; }
跟踪标记4.2.3.2
此方法的实如今ConfigBeanDefinitionParser类中
// 4.2.3.2 解析切入点属性 Object pointcut = parsePointcutProperty(advisorElement, parserContext); /** * Parses the {@code pointcut} or {@code pointcut-ref} attributes of the supplied * {@link Element} and add a {@code pointcut} property as appropriate. Generates a * {@link org.springframework.beans.factory.config.BeanDefinition} for the pointcut if necessary * and returns its bean name, otherwise returns the bean name of the referred pointcut. * * 解析标签上的 pointcut 属性或者 pointcut-ref 属性,并适当的添加 pointcut 属性。 * 若是必要的话生成一个 pointcut 的 BeanDefinition,并返回 bean name,不然返回引用的 pointcut 的 bean name */ private Object parsePointcutProperty(Element element, ParserContext parserContext) { // pointcut 和 pointcut-ref 不能同时存在 if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) { parserContext.getReaderContext().error( "Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.", element, this.parseState.snapshot()); return null; } else if (element.hasAttribute(POINTCUT)) { // Create a pointcut for the anonymous pc and register it. // 为匿名电脑建立一个切入点并注册 // 拿到标签上的 pointcut String expression = element.getAttribute(POINTCUT); // AspectJExpressionPointcut 做为 bean class 建立一个 beanDefinition // beanDefinition 设置同步、原型,表达式添加到属性键值对集合中 AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(element)); return pointcutDefinition; } else if (element.hasAttribute(POINTCUT_REF)) { // 拿到标签上的 pointcut-ref String pointcutRef = element.getAttribute(POINTCUT_REF); if (!StringUtils.hasText(pointcutRef)) { parserContext.getReaderContext().error( "'pointcut-ref' attribute contains empty value.", element, this.parseState.snapshot()); return null; } // 直接返回字符串 return pointcutRef; } else { parserContext.getReaderContext().error( "Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.", element, this.parseState.snapshot()); return null; } }
跟踪标记4.2.4
此方法的实如今ConfigBeanDefinitionParser类中
//4.2.4若是子标签是aspect parseAspect(elt, parserContext); private void parseAspect(Element aspectElement, ParserContext parserContext) { // aspect 标签上的两属性 String aspectId = aspectElement.getAttribute(ID); String aspectName = aspectElement.getAttribute(REF); try { this.parseState.push(new AspectEntry(aspectId, aspectName)); // 存放 BeanDefinition List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>(); // 存放字符串的引用对象 List<BeanReference> beanReferences = new ArrayList<BeanReference>(); // aspect 标签中有子标签 declare-parents List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS); for (int i = METHOD_INDEX; i < declareParents.size(); i++) { Element declareParentsElement = declareParents.get(i); beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext)); } // We have to parse "advice" and all the advice kinds in one loop, to get the // ordering semantics right. // 为了获得正确顺序,咱们不得不在一个循环中解析"通知"和全部通知类型 // 拿到标签下的子节点 NodeList nodeList = aspectElement.getChildNodes(); boolean adviceFoundAlready = false; for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); // 子节点是五种通知类型的状况下:前置、后置、最终、异常、环绕通知 if (isAdviceNode(node, parserContext)) { // 在解析第一个通知时才进入 if (!adviceFoundAlready) { adviceFoundAlready = true; if (!StringUtils.hasText(aspectName)) { parserContext.getReaderContext().error( "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.", aspectElement, this.parseState.snapshot()); return; } // 将 aspect 标签的 ref 属性值(字符串)包装后,添加到一个集合中 beanReferences.add(new RuntimeBeanReference(aspectName)); } // 4.2.4.1 解析通知 AbstractBeanDefinition advisorDefinition = parseAdvice( aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); // 返回的 Bean Definition 添加到另外一个集合中 beanDefinitions.add(advisorDefinition); } } // new 一个 AspectComponentDefinition AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); parserContext.pushContainingComponent(aspectComponentDefinition); // 若是aspect标签下还有pointcut子标签,调用4.2.2方法进行解析 List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); for (Element pointcutElement : pointcuts) { parsePointcut(pointcutElement, parserContext); } // 将新建立的 AspectComponentDefinition 注册到组合组件定义器中 parserContext.popAndRegisterContainingComponent(); } finally { this.parseState.pop(); } }
跟踪标记4.2.4.1
此方法的实如今ConfigBeanDefinitionParser类中
// 4.2.4.1 解析通知 AbstractBeanDefinition advisorDefinition = parseAdvice( aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); /** * Parses one of '{@code before}', '{@code after}', '{@code after-returning}', * '{@code after-throwing}' or '{@code around}' and registers the resulting * BeanDefinition with the supplied BeanDefinitionRegistry. * * 解析五个通知标签中的一个,而且注册最终的 BeanDefinition 到工厂中 */ private AbstractBeanDefinition parseAdvice( String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { try { this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement))); // create the method factory bean // 建立一个 method factory bean 的 RootBeanDefinition RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class); methodDefinition.getPropertyValues().add("targetBeanName", aspectName); methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method")); methodDefinition.setSynthetic(true); // create instance factory definition // 建立一个 instance factory definition 的 RootBeanDefinition RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class); aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName); aspectFactoryDef.setSynthetic(true); // register the pointcut // 注册 pointcut ,进入这个方法 AbstractBeanDefinition adviceDef = createAdviceDefinition( adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences); // configure the advisor // 配置顾问 // 建立一个顾问的 RootBeanDefinition RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class); advisorDefinition.setSource(parserContext.extractSource(adviceElement)); // 将前面获得的通知的 BeanDefinition 添加到顾问的 constructorArgumentValues 中 advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); // 是否有优先级属性在 aspect 标签上,添加进属性键值对集合中 if (aspectElement.hasAttribute(ORDER_PROPERTY)) { advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); } // register the final advisor // 注册最终顾问的 RootBeanDefinition parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); return advisorDefinition; } finally { this.parseState.pop(); } } /** * Creates the RootBeanDefinition for a POJO advice bean. Also causes pointcut * parsing to occur so that the pointcut may be associate with the advice bean. * This same pointcut is also configured as the pointcut for the enclosing * Advisor definition using the supplied MutablePropertyValues. * * 建立一个 POJO 通知 bean 的 RootBeanDefinition 。这使得切入点被解析,并和通知 bean 产生了关联。 * 相同的切入点也会被封闭的顾问定义配置为切入点。顾问使用提供的 MutablePropertyValues */ private AbstractBeanDefinition createAdviceDefinition( Element adviceElement, ParserContext parserContext, String aspectName, int order, RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { // 根据不一样的通知类型设置 beanClass,建立 RootBeanDefinition RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext)); adviceDefinition.setSource(parserContext.extractSource(adviceElement)); adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName); // 这个 order 是子标签(通知标签)被遍历时,所处集合的位置 adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order); // returning 属性 if (adviceElement.hasAttribute(RETURNING)) { adviceDefinition.getPropertyValues().add( RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); } // throwing 属性 if (adviceElement.hasAttribute(THROWING)) { adviceDefinition.getPropertyValues().add( THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); } // arg-names 属性 if (adviceElement.hasAttribute(ARG_NAMES)) { adviceDefinition.getPropertyValues().add( ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); } ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); // 添加上一层方法建立的 RootBeanDefinition cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); // 若是是切入点的引用,直接返回字符串,不然建立一个 RootBeanDefinition ,设置表达式等属性并返回 Object pointcut = parsePointcutProperty(adviceElement, parserContext // 添加解析了切入点属性后的返回值 if (pointcut instanceof BeanDefinition) { cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); // Bean Definition 的状况添加到一个集合 beanDefinitions.add((BeanDefinition) pointcut); } else if (pointcut instanceof String) { RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); // 字符串的状况添加到另一个集合 beanReferences.add(pointcutRef); } // 添加上一层方法建立的 RootBeanDefinition cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); return adviceDefinition; }
跟踪标记4.2.5
此方法的实如今ParserContext类中
//4.2.5弹出组件 parserContext.popAndRegisterContainingComponent(); public void popAndRegisterContainingComponent() { registerComponent(popContainingComponent()); } public CompositeComponentDefinition popContainingComponent() { //先将ParserContext类containingComponents属性的组件弹出 //好比aop:config,这个组件中包含着多个子标签对应的嵌套组件 return (CompositeComponentDefinition) this.containingComponents.pop(); } //拿到弹出的组件进行注册 public void registerComponent(ComponentDefinition component) { //再拿到parserContext中的containingComponents属性中,最后一个组件 //可是这里前面已经弹出,这里已经没有,因此返回null CompositeComponentDefinition containingComponent = getContainingComponent(); if (containingComponent != null) { containingComponent.addNestedComponent(component); } else { //没作具体的实现 this.readerContext.fireComponentRegistered(component); } }
到这里整个loadBeanDefinitions方法跟踪完成。
有兴趣的能够看下,spring配置文件中,组件扫描标签
https://www.jianshu.com/p/e764a6959eeb
——————————————————————————————————
<aop:config>
标签来讲,其对应的解析器为 ConfigBeanDefinitionParserpointcut
、advisor
、aspect
,根据不一样标签走不一样方法——————————————————————————————————
<aop:config>
标签上有配置属性proxy-target-class
或者expose-proxy
等,则将其添加到 BeanDefinition 的属性键值对集合中。parserContext
中,其实就是将建立器的 BeanDefinition 添加到组合组件定义器中——————————————————————————————————
pointcut
方法:建立 bean definition,指定 beanClass,默认多例,同步,将切入点表达式expression
添加到bean definition的propertyValues中;将 bean definition 注册到工厂;包裹 bean definition 注册到组合组件定义器中。advisor
方法:建立 bean definition,指定 beanClass,以adviceBeanName
为key,将标签上属性advice-ref
的值以 RuntimeBeanNameReference 类包装后,添加到 BeanDefinition 的属性键值对集合中;而后注册 bean definition; 解析pointcut-ref
或者pointcut
属性,添加到 BeanDefinition 的属性键值对集合中;包裹 bean definition 注册到组合组件定义器中。aspect
方法——————————————————————————————————
aspect
方法aspect
标签上属性 id、ref 的值,建两集合,一个放 BeanDefinition ,一个放字符串的引用对象。aspect
标签下还有pointcut
子标签,调用标签pointcut
方法进行解析——————————————————————————————————
MethodLocatingFactoryBean.class
为 beanClass、设置为同步、将标签aspect
上的 ref 属性值和通知标签(例如:aop:before
)上的 method 属性值添加到 methodDefinition 的属性键值对集合中SimpleBeanFactoryAwareAspectInstanceFactory.class
为 beanClass、设置为同步、将标签aspect
上的 ref 属性值添加到 aspectFactoryDef 的属性键值对集合中AspectJPointcutAdvisor.class
为 beanClass,拿到 advisorDefinition 的 constructorArgumentValues 属性,添加 adviceDefinition