例子
<bean id="myAop" class="cn.spy.spring.test.MyAop"></bean>
<bean id="myService" class="cn.spy.spring.test.MyService"></bean>
<aop:config>
<aop:pointcut id="myPointCut" expression="execution(* cn.spy.spring.test.MyService.*(..))"/>
<aop:aspect ref="myAop">
<aop:before method="beforeExecute" pointcut-ref="myPointCut"/>
<aop:after method="afterExecute" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
public class MyAop {
public void beforeExecute() {
System.out.println("beforeExecute");
}
public void afterExecute() {
System.out.println("afterExecute");
}
}
public class MyService {
public void execute() {
System.out.println("MyService execute");
}
}
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring.xml"});
MyService myService = ac.getBean("myService", MyService.class);
myService.execute();
}
##结果
beforeExecute
MyService execute
afterExecute
源码解析
从IOC的xml配置解析的位置开始:
DefaultBeanDefinitionDocumentReader类之parseBeanDefinitions
// 解析文档中的根级别元素(import标签,alias标签,bean标签,beans元素)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// Bean定义的document对象使用spring的默认xml命名空间
if (delegate.isDefaultNamespace(root)) {
// 获取bean根元素下的所有子节点
NodeList nl = root.getChildNodes();
// 遍历所有子节点
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 判断节点是否为Element元素节点
if (node instanceof Element) {
// 将节点node强制类型转为Element元素
Element ele = (Element) node;
// 使用Spring的Bean规则解析元素节点
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {// 使用用户自定义的命名空间解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 根节点没有使用spring的默认命名空间,就使用用户自定义的命名空间解析
delegate.parseCustomElement(root);
}
}
说明:
parseDefaultElement方法主要解析的元素是<import>,<alias>,<bean>,<beans>元素等。
parseCustomElement方法主要解析自定义元素。而<aop:config>元素的解析就是在parseCustomElement方法中。
BeanDefinitionParserDelegate类之parseCustomElement方法,解析自定义元素
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
// 获取命名空间Uri
String namespaceUri = getNamespaceURI(ele);
// 通过命名空间Uri获取对应的AopNamespaceHandler(Aop命名空间解析器)
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
// 如果不存在对应的解析器,那么直接返回
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 委派给BeanDefinitionParser解析已经注册的Element
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
NamespaceHandlerSupport类之findParserForElement方法,使用Element的localName查找相应的BeanDefinitionParser (BeanDefinition解析器)
// 委派给BeanDefinitionParser解析已经注册的Element
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
// 使用Element查找对应的BeanDefinitionParser
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 获取元素节点的本地名称
String localName = parserContext.getDelegate().getLocalName(element);
// 通过本地名称获取对应的BeanDefinitionParser(BeanDefinition解析器)
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
ConfigBeanDefinitionParser类之parse方法,解析Element元素转换为BeanDefinition
// 通过element元素解析出BeanDefinition
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 配置创建的代理
// 创建BeanDefinition所需要的代理类
configureAutoProxyCreator(parserContext, element);
// 获取元素的所有子元素
List<Element> childElts = DomUtils.getChildElements(element);
// 遍历所有子元素
for (Element elt: childElts) {
// 获取元素的本地名称
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
// 解析pointcut元素
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
// 解析advisor元素
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
// 解析ASPECT元素
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
// 创建BeanDefinition所需要的代理类
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
AopNamespaceUtils类之registerAspectJAutoProxyCreatorIfNecessary方法
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册AutoProxyCreator定义beanName为BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 处理proxy-target-class和expose-proxy属性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注册组件,并且通知监听器
registerComponentIfNecessary(beanDefinition, parserContext);
}
说明:
- registerAspectJAutoProxyCreatorIfNecessary方法:注册或者升级AnnotationAwareAspectJAutoProxyCreator。
- useClassProxyingIfNecessary方法:处理proxy-target-class以及expose-proxy属性。
- registerComponentIfNecessary方法:注册组件并且通知监听器。
AopConfigUtils类之registerAspectJAutoProxyCreatorIfNecessary方法,注册或者升级AnnotationAwareAspectJAutoProxyCreator
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");
// public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
// 判断BeanDefinition注册集合是否包含internalAutoProxyCreator(自动代理创建器)
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 从注册集合中获取AUTO_PROXY_CREATOR_BEAN_NAME的Bean名称对应的BeanDefinition
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// AspectJAwareAdvisorAutoProxyCreator的名称不等于Bean的Class名称
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 获取当前Bean的Class名称对应的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
// 获取AspectJAwareAdvisorAutoProxyCreator需要的优先级
int requiredPriority = findPriorityForClass(cls);
// 如果当前的internalAutoProxyCreator比需要的AspectJAwareAdvisorAutoProxyCreator优先级低
if (currentPriority < requiredPriority) {
// 设置AspectJAwareAdvisorAutoProxyCreator为BeanDefinition的class名称
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 使用AspectJAwareAdvisorAutoProxyCreator创建BeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 设置切面优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 向ioc容器注册BeanDefinition
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
AopNamespaceUtils类之useClassProxyingIfNecessary方法,处理proxy-target-class和expose-proxy属性
// 处理proxy-target-class和expose-proxy属性
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
// 解析sourceElement元素中的属性proxy-target-class
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
// proxy-target-class属性设置为true
if (proxyTargetClass) {
// 使用internalAutoProxyCreator这个beanName在注册集合BeanDefinitionRegistry中找到对应的BeanDefinition
// 将属性名称proxyTargetClass和值True设置到BeanDefinition
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 解析sourceElement元素中的属性expose-proxy
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
// expose-proxy属性设置为true
if (exposeProxy) {
// 使用internalAutoProxyCreator这个beanName在注册集合BeanDefinitionRegistry中找到对应的BeanDefinition
// 将属性名称exposeProxy和值True设置到BeanDefinition
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
------------开始解析标签 ----------
ConfigBeanDefinitionParser类之parseAspect方法,解析<aop:aspect>标签
private void parseAspect(Element aspectElement, ParserContext parserContext) {
// <aop:aspect>
// 获取aspect的id属性值
String aspectId = aspectElement.getAttribute(ID);
// 获取aspect的ref属性值
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;
// 遍历节点<aop:aspect>标签的子标签
for (int i = 0; i < nodeList.getLength(); i++) {
// 获取当前节点标签
Node node = nodeList.item(i);
// 判断当前节点标签是否为<aop:before>、<aop:after>、<aop:after-returning>、<aop:after-throwing method="">、<aop:around method="">
if (isAdviceNode(node, parserContext)) {
if (!adviceFoundAlready) {
adviceFoundAlready = true;
// 如果aspectName是否为实际的文本
if (!StringUtils.hasText(aspectName)) {
parserContext.getReaderContext().error(
"<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
aspectElement, this.parseState.snapshot());
return;
}
// 将切面名称添加到bean引用集合中
beanReferences.add(new RuntimeBeanReference(aspectName));
}
// 解析通知Advice
AbstractBeanDefinition advisorDefinition = parseAdvice(
aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
// 将切面AdviceDefinition添加集合中
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) {
// 解析切点<aop:pointcut>
parsePointcut(pointcutElement, parserContext);
}
parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}
parseAdvice方法,解析通知Advice
// 解析通知advice
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
// 创建工厂方法BeanDefinition
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);
// 配置通知advice
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));
}
// 将advisorDefinition注册到DefaultListableBeanFactory
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
return advisorDefinition;
}
finally {
this.parseState.pop();
}
}
createAdviceDefinition方法,创建通知BeanDefinition
// 创建AdviceDefinition(BeanDefinition)
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
// 首先获取通知相关需要的类,然后初始化通知的bean实例
// AspectJMethodBeforeAdvice(before)、AspectJAfterAdvice(after)、AspectJAfterReturningAdvice(after-returning)
// AspectJAfterThrowingAdvice(after-throwing)、AspectJAroundAdvice(around)
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
// 设置aspectName属性
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
// 设置declarationOrder属性
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);
// 如果切点是某个BeanDefinition,那么就添加该切点,关联起来
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;
}
总结
绕了一圈的目得就是使用Dom去读取XML,然后解析切面aspect标签、切点point-cut标签,放到adviceDefinition(BeanDefinition),最终注册到DefaultListableBeanFactory。
网友评论