1 16 17 package org.springframework.aop.config; 18 19 import java.util.ArrayList ; 20 import java.util.List ; 21 22 import org.w3c.dom.Attr ; 23 import org.w3c.dom.Element ; 24 import org.w3c.dom.Node ; 25 import org.w3c.dom.NodeList ; 26 27 import org.springframework.aop.aspectj.AspectJAfterAdvice; 28 import org.springframework.aop.aspectj.AspectJAfterReturningAdvice; 29 import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice; 30 import org.springframework.aop.aspectj.AspectJAroundAdvice; 31 import org.springframework.aop.aspectj.AspectJExpressionPointcut; 32 import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice; 33 import org.springframework.aop.aspectj.AspectJPointcutAdvisor; 34 import org.springframework.aop.aspectj.DeclareParentsAdvisor; 35 import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor; 36 import org.springframework.beans.factory.config.BeanDefinition; 37 import org.springframework.beans.factory.config.BeanReference; 38 import org.springframework.beans.factory.config.ConstructorArgumentValues; 39 import org.springframework.beans.factory.config.RuntimeBeanNameReference; 40 import org.springframework.beans.factory.config.RuntimeBeanReference; 41 import org.springframework.beans.factory.parsing.CompositeComponentDefinition; 42 import org.springframework.beans.factory.parsing.ParseState; 43 import org.springframework.beans.factory.support.AbstractBeanDefinition; 44 import org.springframework.beans.factory.support.BeanDefinitionBuilder; 45 import org.springframework.beans.factory.support.BeanDefinitionRegistry; 46 import org.springframework.beans.factory.support.RootBeanDefinition; 47 import org.springframework.beans.factory.xml.BeanDefinitionParser; 48 import org.springframework.beans.factory.xml.ParserContext; 49 import org.springframework.util.StringUtils; 50 import org.springframework.util.xml.DomUtils; 51 52 62 class ConfigBeanDefinitionParser implements BeanDefinitionParser { 63 64 private static final String ASPECT = "aspect"; 65 66 private static final String EXPRESSION = "expression"; 67 68 private static final String ID = "id"; 69 70 private static final String POINTCUT = "pointcut"; 71 72 private static final String ADVICE_BEAN_NAME = "adviceBeanName"; 73 74 private static final String ADVISOR = "advisor"; 75 76 private static final String ADVICE_REF = "advice-ref"; 77 78 private static final String POINTCUT_REF = "pointcut-ref"; 79 80 private static final String REF = "ref"; 81 82 private static final String BEFORE = "before"; 83 84 private static final String DECLARE_PARENTS = "declare-parents"; 85 86 private static final String TYPE_PATTERN = "types-matching"; 87 88 private static final String DEFAULT_IMPL = "default-impl"; 89 90 private static final String IMPLEMENT_INTERFACE = "implement-interface"; 91 92 private static final String AFTER = "after"; 93 94 private static final String AFTER_RETURNING_ELEMENT = "after-returning"; 95 96 private static final String AFTER_THROWING_ELEMENT = "after-throwing"; 97 98 private static final String AROUND = "around"; 99 100 private static final String PROXY_TARGET_CLASS = "proxy-target-class"; 101 102 private static final String RETURNING = "returning"; 103 104 private static final String RETURNING_PROPERTY = "returningName"; 105 106 private static final String THROWING = "throwing"; 107 108 private static final String THROWING_PROPERTY = "throwingName"; 109 110 private static final String ARG_NAMES = "arg-names"; 111 112 private static final String ARG_NAMES_PROPERTY = "argumentNames"; 113 114 private static final String ASPECT_NAME_PROPERTY = "aspectName"; 115 116 private static final String DECLARATION_ORDER_PROPERTY = "declarationOrder"; 117 118 private static final String ORDER_PROPERTY = "order"; 119 120 private static final int METHOD_INDEX = 0; 121 122 private static final int POINTCUT_INDEX = 1; 123 124 private static final int ASPECT_INSTANCE_FACTORY_INDEX = 2; 125 126 127 private ParseState parseState = new ParseState(); 128 129 130 public BeanDefinition parse(Element element, ParserContext parserContext) { 131 CompositeComponentDefinition compositeDef = 132 new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); 133 parserContext.pushContainingComponent(compositeDef); 134 135 configureAutoProxyCreator(parserContext, element); 136 137 NodeList childNodes = element.getChildNodes(); 138 for (int i = 0; i < childNodes.getLength(); i++) { 139 Node node = childNodes.item(i); 140 if (node.getNodeType() == Node.ELEMENT_NODE) { 141 String localName = node.getLocalName(); 142 if (POINTCUT.equals(localName)) { 143 parsePointcut((Element ) node, parserContext); 144 } 145 else if (ADVISOR.equals(localName)) { 146 parseAdvisor((Element ) node, parserContext); 147 } 148 else if (ASPECT.equals(localName)) { 149 parseAspect((Element ) node, parserContext); 150 } 151 } 152 } 153 154 parserContext.popAndRegisterContainingComponent(); 155 return null; 156 } 157 158 164 private void configureAutoProxyCreator(ParserContext parserContext, Element element) { 165 AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); 166 boolean proxyTargetClass = Boolean.valueOf(element.getAttribute(PROXY_TARGET_CLASS)).booleanValue(); 167 if (proxyTargetClass) { 168 AopNamespaceUtils.forceAutoProxyCreatorToUseClassProxying(parserContext.getRegistry()); 169 } 170 } 171 172 177 private void parseAdvisor(Element advisorElement, ParserContext parserContext) { 178 AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); 179 String id = advisorElement.getAttribute(ID); 180 181 try { 182 this.parseState.push(new AdvisorEntry(id)); 183 String pointcutBeanName = parsePointcutProperty(advisorElement, parserContext); 184 advisorDef.getPropertyValues().addPropertyValue(POINTCUT, new RuntimeBeanReference(pointcutBeanName)); 185 String advisorBeanName = id; 186 if (StringUtils.hasText(advisorBeanName)) { 187 parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); 188 } 189 else { 190 advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); 191 } 192 boolean pointcutRef = advisorElement.hasAttribute(POINTCUT_REF); 193 if (pointcutBeanName != null) { 194 fireAdvisorEvent(advisorBeanName, pointcutBeanName, advisorDef, parserContext, pointcutRef); 196 } 197 } 198 finally { 199 this.parseState.pop(); 200 } 201 } 202 203 207 private void fireAdvisorEvent( 208 String advisorBeanName, String pointcutBeanName, AbstractBeanDefinition advisorDef, 209 ParserContext parserContext, boolean pointcutRef) { 210 211 AdvisorComponentDefinition componentDefinition; 212 if (pointcutRef) { 213 componentDefinition = new AdvisorComponentDefinition(advisorBeanName, advisorDef); 214 } 215 else { 216 BeanDefinition pointcutDefinition = parserContext.getRegistry().getBeanDefinition(pointcutBeanName); 217 componentDefinition = new AdvisorComponentDefinition(advisorBeanName, advisorDef, pointcutDefinition); 218 } 219 parserContext.registerComponent(componentDefinition); 220 } 221 222 226 private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) { 227 RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class); 228 advisorDefinition.setSource(parserContext.extractSource(advisorElement)); 229 230 if (advisorElement.hasAttribute(ORDER_PROPERTY)) { 231 advisorDefinition.getPropertyValues().addPropertyValue( 232 ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY)); 233 } 234 235 advisorDefinition.getPropertyValues().addPropertyValue( 236 ADVICE_BEAN_NAME, new RuntimeBeanNameReference(advisorElement.getAttribute(ADVICE_REF))); 237 238 return advisorDefinition; 239 } 240 241 private void parseAspect(Element aspectElement, ParserContext parserContext) { 242 String aspectId = aspectElement.getAttribute(ID); 243 String aspectName = aspectElement.getAttribute(REF); 244 245 if (!StringUtils.hasText(aspectName)) { 246 parserContext.getReaderContext().error( 247 "<aspect> tag needs aspect bean reference via 'ref' attribute.", 248 aspectElement, this.parseState.snapshot()); 249 return; 250 } 251 252 try { 253 this.parseState.push(new AspectEntry(aspectId, aspectName)); 254 List beanDefinitions = new ArrayList (); 255 List beanReferences = new ArrayList (); 256 beanReferences.add(new RuntimeBeanReference(aspectName)); 257 258 List declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS); 259 for (int i = METHOD_INDEX; i < declareParents.size(); i++) { 260 Element declareParentsElement = (Element ) declareParents.get(i); 261 beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext)); 262 } 263 264 NodeList nodeList = aspectElement.getChildNodes(); 267 for (int i = 0; i < nodeList.getLength(); i++) { 268 Node node = nodeList.item(i); 269 if (isAdviceNode(node)) { 270 AbstractBeanDefinition advisorDefinition = 271 parseAdvice(aspectName, i, aspectElement, (Element ) node, parserContext, beanReferences); 272 beanDefinitions.add(advisorDefinition); 273 } 274 } 275 276 AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( 277 aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); 278 parserContext.pushContainingComponent(aspectComponentDefinition); 279 280 List pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); 281 for (int i = 0; i < pointcuts.size(); i++) { 282 Element pointcutElement = (Element ) pointcuts.get(i); 283 parsePointcut(pointcutElement, parserContext); 284 } 285 286 parserContext.popAndRegisterContainingComponent(); 287 } 288 finally { 289 this.parseState.pop(); 290 } 291 } 292 293 private AspectComponentDefinition createAspectComponentDefinition( 294 Element aspectElement, String aspectId, List beanDefs, List beanRefs, ParserContext parserContext) { 295 296 BeanDefinition[] beanDefArray = (BeanDefinition[]) beanDefs.toArray(new BeanDefinition[beanDefs.size()]); 297 BeanReference[] beanRefArray = (BeanReference[]) beanRefs.toArray(new BeanReference[beanRefs.size()]); 298 Object source = parserContext.extractSource(aspectElement); 299 return new AspectComponentDefinition(aspectId, beanDefArray, beanRefArray, source); 300 } 301 302 307 private boolean isAdviceNode(Node aNode) { 308 if (!(aNode instanceof Element )) { 309 return false; 310 } 311 else { 312 String name = aNode.getLocalName(); 313 return (BEFORE.equals(name) || AFTER.equals(name) || AFTER_RETURNING_ELEMENT.equals(name) || 314 AFTER_THROWING_ELEMENT.equals(name) || AROUND.equals(name)); 315 } 316 } 317 318 323 private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) { 324 BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class); 325 builder.addConstructorArg(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE)); 326 builder.addConstructorArg(declareParentsElement.getAttribute(TYPE_PATTERN)); 327 builder.addConstructorArg(declareParentsElement.getAttribute(DEFAULT_IMPL)); 328 builder.setSource(parserContext.extractSource(declareParentsElement)); 329 AbstractBeanDefinition definition = builder.getBeanDefinition(); 330 parserContext.getReaderContext().registerWithGeneratedName(definition); 331 return definition; 332 } 333 334 340 private AbstractBeanDefinition parseAdvice(String aspectName, int order, 341 Element aspectElement, Element adviceElement, ParserContext parserContext, List beanReferences) { 342 343 try { 344 this.parseState.push(new AdviceEntry(adviceElement.getLocalName())); 345 346 RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class); 348 methodDefinition.getPropertyValues().addPropertyValue("targetBeanName", aspectName); 349 methodDefinition.getPropertyValues().addPropertyValue("methodName", adviceElement.getAttribute("method")); 350 methodDefinition.setSynthetic(true); 351 352 RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class); 354 aspectFactoryDef.getPropertyValues().addPropertyValue("aspectBeanName", aspectName); 355 aspectFactoryDef.setSynthetic(true); 356 357 AbstractBeanDefinition adviceDef = createAdviceDefinition( 359 adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanReferences); 360 361 RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class); 363 advisorDefinition.setSource(parserContext.extractSource(adviceElement)); 364 advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); 365 if (aspectElement.hasAttribute(ORDER_PROPERTY)) { 366 advisorDefinition.getPropertyValues().addPropertyValue( 367 ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); 368 } 369 370 parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); 372 373 return advisorDefinition; 374 } 375 finally { 376 this.parseState.pop(); 377 } 378 } 379 380 386 private AbstractBeanDefinition createAdviceDefinition( 387 Element adviceElement, ParserContext parserContext, String aspectName, int order, 388 RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List beanReferences) { 389 390 String pointcutBeanName = parsePointcutProperty(adviceElement, parserContext); 391 RuntimeBeanReference pointcutRef = new RuntimeBeanReference(pointcutBeanName); 392 beanReferences.add(pointcutRef); 393 394 RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement)); 395 adviceDefinition.setSource(parserContext.extractSource(adviceElement)); 396 397 adviceDefinition.getPropertyValues().addPropertyValue(ASPECT_NAME_PROPERTY, aspectName); 398 adviceDefinition.getPropertyValues().addPropertyValue(DECLARATION_ORDER_PROPERTY, new Integer (order)); 399 if (adviceElement.hasAttribute(RETURNING)) { 400 adviceDefinition.getPropertyValues().addPropertyValue(RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); 401 } 402 if (adviceElement.hasAttribute(THROWING)) { 403 adviceDefinition.getPropertyValues().addPropertyValue(THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); 404 } 405 if (adviceElement.hasAttribute(ARG_NAMES)) { 406 adviceDefinition.getPropertyValues().addPropertyValue(ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); 407 } 408 409 ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); 410 cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); 411 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); 412 cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); 413 414 return adviceDefinition; 415 } 416 417 420 private Class getAdviceClass(Element adviceElement) { 421 String elementName = adviceElement.getLocalName(); 422 if (BEFORE.equals(elementName)) { 423 return AspectJMethodBeforeAdvice.class; 424 } 425 else if (AFTER.equals(elementName)) { 426 return AspectJAfterAdvice.class; 427 } 428 else if (AFTER_RETURNING_ELEMENT.equals(elementName)) { 429 return AspectJAfterReturningAdvice.class; 430 } 431 else if (AFTER_THROWING_ELEMENT.equals(elementName)) { 432 return AspectJAfterThrowingAdvice.class; 433 } 434 else if (AROUND.equals(elementName)) { 435 return AspectJAroundAdvice.class; 436 } 437 else { 438 throw new IllegalArgumentException ("Unknown advice kind [" + elementName + "]."); 439 } 440 } 441 442 446 private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { 447 String id = pointcutElement.getAttribute(ID); 448 String expression = pointcutElement.getAttribute(EXPRESSION); 449 450 AbstractBeanDefinition pointcutDefinition = null; 451 452 try { 453 this.parseState.push(new PointcutEntry(id)); 454 pointcutDefinition = createPointcutDefinition(expression); 455 pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); 456 457 if (StringUtils.hasText(id)) { 458 parserContext.getRegistry().registerBeanDefinition(id, pointcutDefinition); 459 } 460 else { 461 parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); 462 } 463 464 parserContext.registerComponent( 465 new PointcutComponentDefinition(id, pointcutDefinition, expression)); 466 } 467 finally { 468 this.parseState.pop(); 469 } 470 471 return pointcutDefinition; 472 } 473 474 480 private String parsePointcutProperty(Element element, ParserContext parserContext) { 481 if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) { 482 parserContext.getReaderContext().error( 483 "Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.", 484 element, this.parseState.snapshot()); 485 return null; 486 } 487 else if (element.hasAttribute(POINTCUT)) { 488 Attr pointcutAttr = element.getAttributeNode(POINTCUT); 490 AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(pointcutAttr.getValue()); 491 pointcutDefinition.setSource(parserContext.extractSource(element)); 492 return parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); 493 } 494 else if (element.hasAttribute(POINTCUT_REF)) { 495 return element.getAttribute(POINTCUT_REF); 496 } 497 else { 498 parserContext.getReaderContext().error( 499 "Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.", 500 element, this.parseState.snapshot()); 501 return null; 502 } 503 } 504 505 509 protected AbstractBeanDefinition createPointcutDefinition(String expression) { 510 RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class); 511 beanDefinition.setSingleton(false); 512 beanDefinition.setSynthetic(true); 513 beanDefinition.getPropertyValues().addPropertyValue(EXPRESSION, expression); 514 return beanDefinition; 515 } 516 517 } 518 | Popular Tags |