开始 简单的 xml 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <bean id ="logUtil" class ="com.devinx3.demo.aop.xml.util.LogUtil" /> <bean class ="com.devinx3.demo.aop.xml.service.DemoService" /> <aop:config > <aop:aspect ref ="logUtil" > <aop:pointcut id ="logPoint" expression ="execution( Object com.devinx3.demo.aop.xml.service.DemoService.* (..))" /> <aop:around method ="around" pointcut-ref ="logPoint" /> <aop:before method ="start" pointcut-ref ="logPoint" /> <aop:after method ="logFinally" pointcut-ref ="logPoint" /> <aop:after-returning method ="stop" pointcut-ref ="logPoint" returning ="result" /> <aop:after-throwing method ="logException" pointcut-ref ="logPoint" throwing ="e" /> </aop:aspect > </aop:config > </beans >
解析 AOP 配置文件 AopNamespaceHandler
定位 : org.springframework.aop.config.AopNamespaceHandler
注册 aop 标签的解析器
1 2 3 4 5 6 7 8 public void init () { registerBeanDefinitionParser("config" , new ConfigBeanDefinitionParser ()); registerBeanDefinitionParser("aspectj-autoproxy" , new AspectJAutoProxyBeanDefinitionParser ()); registerBeanDefinitionDecorator("scoped-proxy" , new ScopedProxyBeanDefinitionDecorator ()); registerBeanDefinitionParser("spring-configured" , new SpringConfiguredBeanDefinitionParser ()); }
config 标签解析器
定位 : org.springframework.aop.config.ConfigBeanDefinitionParser
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public BeanDefinition parse (Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition (element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); configureAutoProxyCreator(parserContext, element); List<Element> 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); } } parserContext.popAndRegisterContainingComponent(); return null ; }
解析 pointcut 标签 解析 pointcut 并构造 AspectJExpressionPointcut 元信息, 注册到 ben 工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private AbstractBeanDefinition parsePointcut (Element pointcutElement, ParserContext parserContext) { String id = pointcutElement.getAttribute(ID); String expression = pointcutElement.getAttribute(EXPRESSION); AbstractBeanDefinition pointcutDefinition = null ; try { this .parseState.push(new PointcutEntry (id)); pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); String pointcutBeanName = id; if (StringUtils.hasText(pointcutBeanName)) { parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); } else { pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); } parserContext.registerComponent( new PointcutComponentDefinition (pointcutBeanName, pointcutDefinition, expression)); } finally { this .parseState.pop(); } return pointcutDefinition; } protected AbstractBeanDefinition createPointcutDefinition (String expression) { RootBeanDefinition beanDefinition = new RootBeanDefinition (AspectJExpressionPointcut.class); beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE); beanDefinition.setSynthetic(true ); beanDefinition.getPropertyValues().add(EXPRESSION, expression); return beanDefinition; }
解析 advice 标签 包含 around, before, after, after-returning, after-throwing
解析 pointcut 并构造 AspectJExpressionPointcut 元信息, 解析 around, before, after, after-returning, after-throwing 并构造 AspectJMethodBeforeAdvice, AspectJAfterAdvice, AspectJAfterReturningAdvice, AspectJAfterThrowingAdvice, AspectJAroundAdvice 元信息 同时构造 AspectJPointcutAdvisor 元信息,并注册到 bean 工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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))); RootBeanDefinition methodDefinition = new RootBeanDefinition (MethodLocatingFactoryBean.class); methodDefinition.getPropertyValues().add("targetBeanName" , aspectName); methodDefinition.getPropertyValues().add("methodName" , adviceElement.getAttribute("method" )); methodDefinition.setSynthetic(true ); RootBeanDefinition aspectFactoryDef = new RootBeanDefinition (SimpleBeanFactoryAwareAspectInstanceFactory.class); aspectFactoryDef.getPropertyValues().add("aspectBeanName" , aspectName); aspectFactoryDef.setSynthetic(true ); AbstractBeanDefinition adviceDef = createAdviceDefinition( adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences); RootBeanDefinition advisorDefinition = new RootBeanDefinition (AspectJPointcutAdvisor.class); advisorDefinition.setSource(parserContext.extractSource(adviceElement)); advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); if (aspectElement.hasAttribute(ORDER_PROPERTY)) { advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); } parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); return advisorDefinition; } finally { this .parseState.pop(); } }
创建通知 的 bean 元信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 private AbstractBeanDefinition createAdviceDefinition ( Element adviceElement, ParserContext parserContext, String aspectName, int order, RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { RootBeanDefinition adviceDefinition = new RootBeanDefinition (getAdviceClass(adviceElement, parserContext)); adviceDefinition.setSource(parserContext.extractSource(adviceElement)); adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName); adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order); if (adviceElement.hasAttribute(RETURNING)) { adviceDefinition.getPropertyValues().add( RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); } if (adviceElement.hasAttribute(THROWING)) { adviceDefinition.getPropertyValues().add( THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); } if (adviceElement.hasAttribute(ARG_NAMES)) { adviceDefinition.getPropertyValues().add( ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); } ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); Object pointcut = parsePointcutProperty(adviceElement, parserContext); if (pointcut instanceof BeanDefinition) { cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); beanDefinitions.add((BeanDefinition) pointcut); } else if (pointcut instanceof String) { RuntimeBeanReference pointcutRef = new RuntimeBeanReference ((String) pointcut); cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); beanReferences.add(pointcutRef); } cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); return adviceDefinition; } private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) { String elementName = parserContext.getDelegate().getLocalName(adviceElement); if (BEFORE.equals(elementName)) { return AspectJMethodBeforeAdvice.class; } else if (AFTER.equals(elementName)) { return AspectJAfterAdvice.class; } else if (AFTER_RETURNING_ELEMENT.equals(elementName)) { return AspectJAfterReturningAdvice.class; } else if (AFTER_THROWING_ELEMENT.equals(elementName)) { return AspectJAfterThrowingAdvice.class; } else if (AROUND.equals(elementName)) { return AspectJAroundAdvice.class; } else { throw new IllegalArgumentException ("Unknown advice kind [" + elementName + "]." ); } }
解析 advisor 标签 解析 advisor 并构造 DefaultBeanFactoryPointcutAdvisor 元信息, 注册到 ben 工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 private void parseAdvisor (Element advisorElement, ParserContext parserContext) { 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 { advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); } Object pointcut = parsePointcutProperty(advisorElement, parserContext); 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(); } }