AOP的xml文件配置如下:
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="xmlAspect" class="com.aop.aspect.XmlAspect"></bean>
<!-- AOP 配置 -->
<aop:config>
<!-- 声明一个切面,并注入切面 Bean,相当于@Aspect -->
<aop:aspect ref="xmlAspect"> <!-- 配置一个切入点,相当于@Pointcut -->
<aop:pointcut expression="execution(* com.aop.service..*(..))" id="simplePointcut"/>
<!-- 配置通知,相当于@Before、@After、@AfterReturn、@Around、@AfterThrowing -->
<aop:before pointcut-ref="simplePointcut" Method="before"/>
<aop:after pointcut-ref="simplePointcut" Method="after"/>
<aop:after-returning pointcut-ref="simplePointcut" Method="afterReturn"/>
<aop:after-throwing pointcut-ref="simplePointcut" Method="afterThrow" throwing="ex"/>
</aop:aspect>
</aop:config>
ioc容器解析中,分析到在方法doRegisterBeanDefinitions中的delegate.parseCustomElement(ele)解析AOP的bean
loadBeanDefinitions->doLoadBeanDefinitions->registerBeanDefinitions-> doRegisterBeanDefinitions->parseBeanDefinitions(root, this.delegate);
//使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean定义的Document对象使用了Spring默认的XML命名空间
if (delegate.isDefaultNamespace(root)) {
//获取Bean定义的Document对象根元素的所有子节点
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//获得Document节点是XML元素节点
if (node instanceof Element) {
Element ele = (Element) node;
//Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
if (delegate.isDefaultNamespace(ele)) {
//使用Spring的Bean规则解析元素节点
parseDefaultElement(ele, delegate);
}
else {
//没有使用Spring默认的XML命名空间,则使用用户自定义的解析规则解析元素节点
delegate.parseCustomElement(ele);
}
}
}
}
else {
//Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
//解析规则解析Document根节点
delegate.parseCustomElement(root);
}
}
<aop:config>不是默认的命名空间namespace,所以遇到<aop:config>标签时, 执行:delegate.parseCustomElement(ele);
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//获取对应的NamespaceHandler即Namespace处理器
//具体到aop这个Namespace的NamespaceHandler是org.springframework.aop.config.AopNamespaceHandler类
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//利用AopNamespaceHandler的parse方法,解析<aop:config>下的内容
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
BeanDefinition parse(Element element, ParserContext parserContext);
public abstract class NamespaceHandlerSupport implements NamespaceHandler
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}
parse:1
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;
}
parse:2
parser.parse(element, parserContext)方法中的parse:
public class AopNamespaceHandler extends NamespaceHandlerSupport
AopNamespaceHandler类有一个初始化方法:
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 SpringConfig