Spring与AOP之AspectJ基于XML的实现

12 篇文章 0 订阅

AspectJ 除了提供了基于注解的 AOP 的实现外,还提供了以 XML 方式的实现。切面就是一个 POJO 类,而用于增强的方法就是普通的方法。通过配置文件,将切面中的功能增强织入到了目标类的目标方法中。

实现步骤

(1) 定义业务接口与实现类

//主业务接口
public interface ISomeService {
	//主业务方法
	void doFirst();
	//主业务方法
	String doSecond();
	//主业务方法
	void doThird();

}
//目标类
public class SomeServiceImpl implements ISomeService {

	//目标方法
	@Override
	public void doFirst() {
		System.out.println("执行doFirst()方法");
	}

	//目标方法
	@Override
	public String doSecond() {
		System.out.println("执行doSecond()方法");
		return "abcde";
	}

	//目标方法
	@Override
	public void doThird() {
		System.out.println("执行doThird()方法" + 3 / 0);
		System.out.println("执行doThird()方法");
	}

}

(2) 定义切面 POJO 类

该类为一个 POJO 类,将作为切面出现。其中定义了若干普通方法,将作为不同的通知方法。

// 表示当前类为切面
public class MyAspectJ {
	
	//前置通知
	public void myBefore() {
		System.out.println("执行前置通知方法");
	}
	
//	@Before("execution(* *..ISomeService.doFirst(..))")
	public void myBefore(JoinPoint jp) {
		System.out.println("执行前置通知方法 jp = " + jp);
	}
	
	//后置通知
	public void myAfterReturning() {
		System.out.println("执行后置通知方法");
	}
	
	public void myAfterReturning(Object result) {
		System.out.println("执行后置通知方法 result = " + result);
	}
	
	//环绕通知
	public Object myAround(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("执行环绕通知方法,目标方法执行之前");
		
		//执行目标方法
		Object result = pjp.proceed();
		System.out.println("执行环绕通知方法,目标方法执行之后");
		if (result != null) {
			result = ((String)result).toUpperCase();
		}
		return result;
	}
	
	//异常通知
	public void myAfetrThrowing() {
		System.out.println("执行异常通知方法");
	}
	
	//使用切入点,叫 doThirdPointcut()
	public void myAfterThrowing(Exception ex) {
		System.out.println("执行异常通知方法 ex = " + ex.getMessage());
	}
	
	//最终通知
	public void myAfter() {
		System.out.println("执行最终通知方法");
	}
	
	
}

(3) 注册目标对象与 POJO 切面类

<!-- 注册切面 -->
<bean id="myAspectJ" class="com.huang.xml.MyAspectJ"/>
	
<!-- 注册目标对象 -->
<bean id="someService" class="com.huang.xml.SomeServiceImpl"/>

(4) 在容器中定义 AOP 配置

<!-- AOP配置 -->
	<aop:config>
	    
	    <aop:aspect ref="myAspectJ">
	    <aop:pointcut expression="execution(* *..ISomeService.doFirst(..))" id="doFirstPointcut"/>
	    <aop:pointcut expression="execution(* *..ISomeService.doSecond(..))" id="doSecondPointcut"/>
	    <aop:pointcut expression="execution(* *..ISomeService.doThird(..))" id="doThirdPointcut"/>

	    </aop:aspect>
	</aop:config>

通过其子标签<aop:pointcut/>定义切入点,该标签有两个属性, id 与 expression。分别用于指定该切入点的名称及切入点的值。 expression 的值为 execution 表达式。

子标签<aop:aspect/>定义具体的织入规则:根据不同的通知类型,确定不同的织入时间;将 method 指定的增强方法,按照指定织入时间,织入到切入点指定的目标方法中。

<aop:aspect/>的 ref 属性用于指定使用哪个切面。<aop:aspect/>的子标签是各种不同的通知类型。不同的通知所包含的属性是不同的,但也有共同的属性。

  • method:指定该通知使用的切面中的增强方法。
  • pointcut-ref:指定该通知要应用的切入点。

AspectJ 的 6 种通知的 XML 标签如下:

  • <aop:before/>:前置通知
  • lt;aop:after-returning/>: 后置通知
  • <aop:around/>:环绕通知
  • <aop:after-throwing/>:异常通知
  • <aop:after/>:最终通知
  • <aop:declare-parents/>:引入通知

(5) 定义测试类

	@Test
	public void test01() {
		String resource = "com/huang/xml/applicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
		//serviceProxy为代理对象,而非目标对象
		ISomeService service = (ISomeService) ac.getBean("someService");  
		service.doFirst();
		System.out.println("----------------------");
		service.doSecond();
		System.out.println("----------------------");
		service.doThird();
	}
<aop:before/>前置通知
<!-- 前置通知 -->
<aop:before method="myBefore" pointcut-ref="doFirstPointcut"/>
<aop:before method="myBefore(org.aspectj.lang.JoinPoint)" pointcut-ref="doFirstPointcut"/>

运行结果

{% asset_img aop17.jpg %}

<aop:after-returning/>后置通知

其 XML 的配置中,有一个属性 returning,指定用于接收目标方法的返回值所使用的变量名。其可作为增强方法的参数出现。

<!-- 后置通知 -->
<aop:after-returning method="myAfterReturning" pointcut-ref="doSecondPointcut"/>
<aop:after-returning method="myAfterReturning(java.lang.Object)" pointcut-ref="doSecondPointcut" returning="result"/>

运行结果

{% asset_img aop18.jpg %}

<aop:around/>环绕通知

环绕通知的增强方法一般返回类型为 Object,是目标方法的返回值。并且可以包含一个参数 ProceedingJoinPoint,其方法 proceed()可执行目标方法。

<!-- 环绕通知 -->
<aop:around method="myAround" pointcut-ref="doSecondPointcut"/>

运行结果

{% asset_img aop19.jpg %}

<aop:after-throwing/>异常通知

其 XML 的配置中,有一个属性 throwing,指定用于接收目标方法所抛出异常的变量名。其可作为增强方法的参数出现,该参数为 Throwable 类型。

<!-- 异常通知 -->
<aop:after-throwing method="myAfterThrowing(java.lang.Exception)" pointcut-ref="doThirdPointcut" throwing="ex"/>

运行结果

{% asset_img aop20.jpg %}

<aop:after/>最终通知
<!-- 最终通知 -->
<aop:after method="myAfter" pointcut-ref="doThirdPointcut"/>

运行结果

{% asset_img aop21.jpg %}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值