[Spring3.x源码]AOP(二)组装配置信息
2013-01-01 11:12
274 查看
AbstractApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");这个过程不仅会解析普通的<bean>标签,<aop>标签也会被解析。
1.IoC在解析XML的时候,DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)中解析根节点的子节点。
isDefaultNamespace()判断标签的命名空间是不是http://www.springframework.org/schema/beans,不是的话表示该标签为自定义标签,调用parseCustomElement解析节点。<aop>竟然也算是自定义标签。
delegate在DefaultBeanDefinitionDocumentReader.createHelper方法创建的。
BeanDefinitionParserDelegate.parseCustomElement(Element ele):
readerContext是XmlReaderContext类的对象,是在DefaultBeanDefinitionDocumentReader中创建BeanDefinitionParserDelegate时,当构造函数的参数传入的。
如果此对象为空,就创建一个createDefaultNamespaceHandlerResolver():
2.回到BeanDefinitionParserDelegate.parseCustomElement中,DefaultNamespaceHandlerResolver.resolve(String namespaceUri),根据标签<aop:config>去取相关的命名空间,在根据虚拟的命名空间去取对应的解析类。
getHandlerMappings():
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);载入配置文件的信息,配置文件地址变量this.handlerMappingsLocation的来源:
将所有包/META-INF/spring.handlers文件内容保存到Map类型的handlerMappings属性中。
AOP的标签<aop>对应的命名空间是http://www.springframework.org/schema/aop,在/spring-aop/src/main/resources/META-INF/spring.handlers这个文件中看看spring.handlers的内容:http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
这里将配置文件开头的命名空间虚拟路径和真实的类关联起来。
暂时回到DefaultNamespaceHandlerResolver.resolve(String namespaceUri)中,AopNamespaceHandler被创建时会执行init初始化操作:
3.将由这个AopNamespaceHandler类将<aop:config>的配置信息转为BeanDefinition
AopNamespaceHandler继承NamespaceHandlerSupport,
返回<aop:config>标签对应的解析类,AopNamespaceHandler.init()方法中已经配置了——ConfigBeanDefinitionParser。
4.到了这里,spring才有解析<aop:config>的意思,ConfigBeanDefinitionParser.parse(Element element, ParseContext parserContext):
在AbstractApplicationContext.refresh()中会调用registerBeanPostProcessors()方法将此bean实例化,并调用beanFactory.addBeanPostProcessor()将其保存到AbstractBeanFactory的属性beanPostProcessors中。(AspectJAwareAdvisorAutoProxyCreator通过复杂继承关系算是实现了BeanPostProcessor接口)
5.开始解析<aop:aspect>标签ConfigBeanDefinitionParser.parseAspect():
createAdviceDefinition()方法将切面信息、切入点信息的整合关联。advisor=advice+pointCut
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));根据切面的类型(如before、after等)调取相应的类,创建切面类信息。
advisor封装advice的信息(1:1),advice含有pointCut的信息(1:1)。
每个<aop:before>这种标签包含了类-方法信息,配置成一个advice。advisor是advice它的封装。
1.IoC在解析XML的时候,DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)中解析根节点的子节点。
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); } }
isDefaultNamespace()判断标签的命名空间是不是http://www.springframework.org/schema/beans,不是的话表示该标签为自定义标签,调用parseCustomElement解析节点。<aop>竟然也算是自定义标签。
delegate在DefaultBeanDefinitionDocumentReader.createHelper方法创建的。
BeanDefinitionParserDelegate.parseCustomElement(Element ele):
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } 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)); }
readerContext是XmlReaderContext类的对象,是在DefaultBeanDefinitionDocumentReader中创建BeanDefinitionParserDelegate时,当构造函数的参数传入的。
this.delegate = createHelper(readerContext, root, parent); protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext, environment); delegate.initDefaults(root, parentDelegate); return delegate; }而DefaultBeanDefinitionDocumentReader的readerContext是在XmlBeanDefinitionReader.registerBeanDefinitions中创建DefaultBeanDefinitionDocumentReader的时候通过赋值的:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //返回DefaultBeanDefinitionDocumentReader BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); //createReaderContext(resource)就是readerContext的来源,返回XmlReaderContext对象 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass)); } private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;XmlBeanDefinitionReader.createReaderContext(resource)是readerContext的来源
protected XmlReaderContext createReaderContext(Resource resource) { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.namespaceHandlerResolver); }而这个this.namespaceHandlerResolver就是BeanDefinitionParserDelegate.parseCustomElement方法中this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);要调用的。
如果此对象为空,就创建一个createDefaultNamespaceHandlerResolver():
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader()); }
2.回到BeanDefinitionParserDelegate.parseCustomElement中,DefaultNamespaceHandlerResolver.resolve(String namespaceUri),根据标签<aop:config>去取相关的命名空间,在根据虚拟的命名空间去取对应的解析类。
public NamespaceHandler resolve(String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); 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.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); } } }
getHandlerMappings():
private Map<String, Object> getHandlerMappings() { if (this.handlerMappings == null) { synchronized (this) { if (this.handlerMappings == null) { try { Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isDebugEnabled()) { logger.debug("Loaded NamespaceHandler mappings: " + mappings); } Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(); CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOException ex) { throw new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } return this.handlerMappings; }
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);载入配置文件的信息,配置文件地址变量this.handlerMappingsLocation的来源:
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers"; private final String handlerMappingsLocation; public DefaultNamespaceHandlerResolver() { this(null, DEFAULT_HANDLER_MAPPINGS_LOCATION); } public DefaultNamespaceHandlerResolver(ClassLoader classLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); } public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) { Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null"); this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); this.handlerMappingsLocation = handlerMappingsLocation; }
将所有包/META-INF/spring.handlers文件内容保存到Map类型的handlerMappings属性中。
AOP的标签<aop>对应的命名空间是http://www.springframework.org/schema/aop,在/spring-aop/src/main/resources/META-INF/spring.handlers这个文件中看看spring.handlers的内容:http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
这里将配置文件开头的命名空间虚拟路径和真实的类关联起来。
暂时回到DefaultNamespaceHandlerResolver.resolve(String namespaceUri)中,AopNamespaceHandler被创建时会执行init初始化操作:
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()); }
3.将由这个AopNamespaceHandler类将<aop:config>的配置信息转为BeanDefinition
AopNamespaceHandler继承NamespaceHandlerSupport,
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; }
返回<aop:config>标签对应的解析类,AopNamespaceHandler.init()方法中已经配置了——ConfigBeanDefinitionParser。
4.到了这里,spring才有解析<aop:config>的意思,ConfigBeanDefinitionParser.parse(Element element, ParseContext parserContext):
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; }configureAutoProxyCreator(parserContext, element);创建AspectJAwareAdvisorAutoProxyCreator实例,备用。
/** * Configures the auto proxy creator needed to support the {@link BeanDefinition BeanDefinitions} * created by the '<code><aop:config/></code>' tag. Will force class proxying if the * '<code>proxy-target-class</code>' attribute is set to '<code>true</code>'. * @see AopNamespaceUtils */ private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); }AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary()
public static void registerAspectJAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } 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; }registry是DefaultListableBeanFactory的实例,registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);将BeanDefinition保存到其beanDefinitionMap属性中。
在AbstractApplicationContext.refresh()中会调用registerBeanPostProcessors()方法将此bean实例化,并调用beanFactory.addBeanPostProcessor()将其保存到AbstractBeanFactory的属性beanPostProcessors中。(AspectJAwareAdvisorAutoProxyCreator通过复杂继承关系算是实现了BeanPostProcessor接口)
5.开始解析<aop:aspect>标签ConfigBeanDefinitionParser.parseAspect():
private void parseAspect(Element aspectElement, ParserContext parserContext) { String aspectId = aspectElement.getAttribute(ID); String aspectName = aspectElement.getAttribute(REF); try { this.parseState.push(new AspectEntry(aspectId, aspectName)); List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>(); List<BeanReference> beanReferences = new ArrayList<BeanReference>(); 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; } beanReferences.add(new RuntimeBeanReference(aspectName)); } AbstractBeanDefinition advisorDefinition = parseAdvice( aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); beanDefinitions.add(advisorDefinition); } } AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); parserContext.pushContainingComponent(aspectComponentDefinition); List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); for (Element pointcutElement : pointcuts) { parsePointcut(pointcutElement, parserContext); } parserContext.popAndRegisterContainingComponent(); } finally { this.parseState.pop(); } }for循环中的isAdviceNode(node, parserContext)做为过滤条件将只解析before、after、after-returning、after-throwing、around这样的子标签
/** * Return <code>true</code> if the supplied node describes an advice type. May be one of: * '<code>before</code>', '<code>after</code>', '<code>after-returning</code>', * '<code>after-throwing</code>' or '<code>around</code>'. */ private boolean isAdviceNode(Node aNode, ParserContext parserContext) { if (!(aNode instanceof Element)) { return false; } else { String name = parserContext.getDelegate().getLocalName(aNode); return (BEFORE.equals(name) || AFTER.equals(name) || AFTER_RETURNING_ELEMENT.equals(name) || AFTER_THROWING_ELEMENT.equals(name) || AROUND.equals(name)); } }将aspectName=log,aspectElement=<aop:aspect>,adviceElement=<aop:after>...当参数传入parseAdvice,解析切面类。
/** * Parses one of '<code>before</code>', '<code>after</code>', '<code>after-returning</code>', * '<code>after-throwing</code>' or '<code>around</code>' and registers the resulting * BeanDefinition with the supplied BeanDefinitionRegistry. * @return the generated advice RootBeanDefinition */ 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 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 RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class); aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName); aspectFactoryDef.setSynthetic(true); // register the pointcut AbstractBeanDefinition adviceDef = createAdviceDefinition( adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences); // configure the advisor 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)); } // register the final advisor parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); return advisorDefinition; } finally { this.parseState.pop(); } }methodDefinition切面信息,包含切面类、方法
createAdviceDefinition()方法将切面信息、切入点信息的整合关联。advisor=advice+pointCut
/** * 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. */ 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; }
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));根据切面的类型(如before、after等)调取相应的类,创建切面类信息。
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 + "]."); } }Object pointcut = parsePointcutProperty(adviceElement, parserContext);返回切入点信息(例子中,配置文件beans.xml中的servicesPointcut)。
/** * Parses the <code>pointcut</code> or <code>pointcut-ref</code> attributes of the supplied * {@link Element} and add a <code>pointcut</code> 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. */ private Object parsePointcutProperty(Element element, ParserContext parserContext) { 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. String expression = element.getAttribute(POINTCUT); AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(element)); return pointcutDefinition; } else if (element.hasAttribute(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; } }
advisor封装advice的信息(1:1),advice含有pointCut的信息(1:1)。
每个<aop:before>这种标签包含了类-方法信息,配置成一个advice。advisor是advice它的封装。
相关文章推荐
- spring通过xml方式配置AOP时,提示错误信息:匹配的通配符是严格的,但是对于元素'aop:aspectj- 自动代理”。
- [Spring3.x源码]AOP(四)切面的执行
- Spring的AOP实现方式—ProxyFactoryBean配置方式实现源码剖析
- [Spring3.x源码]AOP(一)例子
- [Spring3.x源码]AOP(三)代理类的实例化
- spring aop自动配置源码解析
- SpringAOP源码解析之配置解析篇
- [Spring3.x源码]事务(一)配置事务切面
- Spring源码阅读-通用配置实现AOP
- 深入理解Spring 之 源码剖析AOP(XML配置方式)
- Spring+Spring MVC+Mybatis整合配置AOP不生效的解决方案以及Bean初始化重复加载两次(疑难杂症)
- Spring AOP AspectJ注解和XML配置两种实现(Maven构建)
- Spring 3.x企业应用开发实战(10)----AOP切面
- Spring-通过xml配置实现AOP
- Spring中基于配置XML与Annotation注解配置AOP
- Spring中AOP原理,源码学习笔记
- Intellij IDEA中Spring配置aop增强事务 出现BeanCreationException异常处理方法
- Spring源码分析——AOP实现(1)
- java框架篇---spring aop两种配置方式
- Spring AOP记录日志信息