spring-aop源码解析:declare-parent

35 篇文章 0 订阅
30 篇文章 0 订阅
spring-aop源码解析:declare-parent

借助Aop的引入,我们可以不侵入性的改变现有的实现,对现有实现类无侵入性的增加方法。

1、举个例子:Einstein从小爱发明,是个发明家,我们创建一个Einstein类,实现发明家(Inventor)接口。随着知识的积累,Einstein也成为了数学家,我们可以在不改变Eistein类的前提下使用declare-parent为Eistein添加数学家的特性。

package com.zhc.aop.declareparent;

public interface Inventor {
	public void invent();
}

 

package com.zhc.aop.declareparent;

public class Einstein implements Inventor {

	@Override
	public void invent() {
		// TODO Auto-generated method stub
		System.out.println("create new thing");
	}

}

 

package com.zhc.aop.declareparent;

public interface Mathematician {
	public void calculate();
}

 

package com.zhc.aop.declareparent;

public class MathematicianImpl implements Mathematician {

	@Override
	public void calculate() {
		System.out.println("calculate the result of the formulae");
	}

}

 

spring-aop.xml配置declare-parent,为Einstein添加特性

 <bean id="Einstein" class="com.zhc.aop.declareparent.Einstein"></bean>
 <aop:config>
 	<aop:aspect>
 		<aop:declare-parents types-matching="com.zhc.aop.declareparent.Einstein" 
 			implement-interface="com.zhc.aop.declareparent.Mathematician"
 			default-impl="com.zhc.aop.declareparent.MathematicianImpl"/>
 	</aop:aspect>
 </aop:config>

 测试类:

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class DeclareParentTest {
	@Test
	public void testEinstein(){
		String xml = "classpath:spring-aop.xml";
	    ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { xml });
	    Inventor inventor = (Inventor) context.getBean("Einstein");
	    inventor.invent();
	    Mathematician mathematician = (Mathematician) context.getBean("Einstein");
	    mathematician.calculate();
    }
}

 

2、源码分析

 ConfigBeanDefinitionParser同过parseDeclareParents方法来解析declare-parents 标签

	/**
	 * Parse a '<code>declare-parents</code>' element and register the appropriate
	 * DeclareParentsAdvisor with the BeanDefinitionRegistry encapsulated in the
	 * supplied ParserContext.
	 * 解析一个declare-parents标签,并且使用BeanDefinitionRegistry注册一个合适的DeclareParentsAdvisor
	 * BeanDefinitionRegistry封装在了parserContext中
	 */
	private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) {
		//BeanDefinition是由BeanDefinitionBuilder创建的,在builder创建BeanDefinition之前,
		//要设置根bean定义(rootBeanDefinition),它指定了bean的Class
		//declare-parents标签内部实现方式是创建了一个切面
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class);
		//添加构造函数的参数
		//这里的构造函数是指DeclareParentsAdvisor的构造函数
		builder.addConstructorArgValue(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE));//新加的接口
		builder.addConstructorArgValue(declareParentsElement.getAttribute(TYPE_PATTERN));//类型匹配表达式
		
		String defaultImpl = declareParentsElement.getAttribute(DEFAULT_IMPL);//新加接口的默认实现
		String delegateRef = declareParentsElement.getAttribute(DELEGATE_REF);//新加接口的实现引用
		
		//新接口实现类和实现引用指定一个即可,且只能指定一个
		if (StringUtils.hasText(defaultImpl) && !StringUtils.hasText(delegateRef)) {
			builder.addConstructorArgValue(defaultImpl);
		}
		else if (StringUtils.hasText(delegateRef) && !StringUtils.hasText(defaultImpl)) {
			builder.addConstructorArgReference(delegateRef);
		}
		else {
			parserContext.getReaderContext().error(
					"Exactly one of the " + DEFAULT_IMPL + " or " + DELEGATE_REF + " attributes must be specified",
					declareParentsElement, this.parseState.snapshot());
		}

		//获取bean定义
		AbstractBeanDefinition definition = builder.getBeanDefinition();
		definition.setSource(parserContext.extractSource(declareParentsElement));
		//注册bean定义
		parserContext.getReaderContext().registerWithGeneratedName(definition);
		return definition;
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值