`

应用Spring AOP(五)-------XML配置方式

阅读更多

Spring AOP提供了xml配置文件以及Annotation注解的方式更方便的进行AOP的配置。当然这两种方式的最大的好处是更好的降低了代码耦合性。

XML配置的示例工程代码:

 和前面的工程相比,前置通知,后置通知那几个通知类没有了,所有的通知逻辑直接放到了AllLogAdvice类的方法里:

package com.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class AllLogAdvice {
	private Logger logger = Logger.getLogger(AllLogAdvice.class);

	// 此方法将作为前置通知
	public void myBeforeAdvice(JoinPoint jionpoint) {
		// 获取被调用的类名
		String targetClassName = jionpoint.getTarget().getClass().getName();
		// 获取被调用的方法名
		String targetMethodName = jionpoint.getSignature().getName();
		// 日志格式字符串
		String logInfoText = "前置通知:" + targetClassName + "类的"
				+ targetMethodName + "方法开始执行";
		// 将日志信息写入配置的文件中
		logger.info(logInfoText);
	}

	// 此方法将作为后置通知
	public void myAfterReturnAdvice(JoinPoint jionpoint) {
		// 获取被调用的类名
		String targetClassName = jionpoint.getTarget().getClass().getName();
		// 获取被调用的方法名
		String targetMethodName = jionpoint.getSignature().getName();
		// 日志格式字符串
		String logInfoText = "后置通知:" + targetClassName + "类的"
				+ targetMethodName + "方法开始执行";
		// 将日志信息写入配置的文件中
		logger.info(logInfoText);
	}

	// 此方法将作为异常通知
	public void myThrowingAdvice(JoinPoint jionpoint, Exception e) {
		// 获取被调用的类名
		String targetClassName = jionpoint.getTarget().getClass().getName();
		// 获取被调用的方法名
		String targetMethodName = jionpoint.getSignature().getName();
		// 日志格式字符串
		String logInfoText = "异常通知:执行" + targetClassName + "类的"
				+ targetMethodName + "方法时发生异常";
		// 将日志信息写入配置的文件中
		logger.info(logInfoText);
	}

	// 此方法将作为环绕通知
	public void myAroundAdvice(ProceedingJoinPoint jionpoint) throws Throwable {
		long beginTime = System.currentTimeMillis();
		jionpoint.proceed();
		long endTime = System.currentTimeMillis();
		// 获取被调用的方法名
		String targetMethodName = jionpoint.getSignature().getName();
		// 日志格式字符串
		String logInfoText = "环绕通知:" + targetMethodName + "方法调用前时间" + beginTime
				+ "毫秒," + "调用后时间" + endTime + "毫秒";
		// 将日志信息写入配置的文件中
		logger.info(logInfoText);
	}
}

 

 4种通知功能用4个方法来完成了。aop.xml配置文件内容: 

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"	
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
	http://www.springframework.org/schema/aop 
	http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	
	<bean id="myUserService" class="com.service.UserService"></bean>
		
	<!-- 定义日志通知,将日志切面交给Spring容器管理 -->
	<bean id="allLogAdvice" class="com.aop.AllLogAdvice"></bean>	
	
	<!-- 进行aop配置 -->
	<aop:config>	
	  <!-- 配置日志切面 -->
	  <aop:aspect id="logaop" ref="allLogAdvice">	 	  
	       
	    <aop:pointcut id="logpointcut" expression="execution(* com.service.UserService.*(..))" />
	    
	    <!-- 将LogAdvice日志通知中的myBeforeAdvice方法指定为前置通知 -->
	    <aop:before method="myBeforeAdvice" pointcut-ref="logpointcut"/>
	    
	    <!-- 将LogAdvice日志通知中的myAfterReturnAdvice方法指定为后置通知 -->
	    <aop:after-returning method="myAfterReturnAdvice" pointcut-ref="logpointcut"/>
	    
	    <!-- 将LogAdvice日志通知中的方法指定为异常通知 -->
	    <aop:after-throwing method="myThrowingAdvice" pointcut-ref="logpointcut" throwing="e" />
	    
	    <!-- 将LogAdvice日志通知中的方法指定为环绕通知 -->
	    <aop:around method="myAroundAdvice" pointcut-ref="logpointcut"/>
	  </aop:aspect>
	</aop:config>
	
</beans>

 定义pointcut的这句:

<aop:pointcut id="logpointcut" expression="execution(* com.service.UserService.*(..))" />

 expression里的写法参考官网解释的

6.2.3.4节:http://docs.spring.io/spring/docs/2.0.8/reference/aop.html

除了用execution外,还可以用within,this等。

这篇文章解释也不错:http://blog.csdn.net/kkdelta/article/details/7441829

这儿第一个*通配符代表所有的返回值,第二个*代表所有方法,(..)表示任意的参数类型。也就是说com.service.UserService类下面的所有任意返回值,任意参数类型的方法都会被拦截。

 

再看看主测试类MainTest:

package com.test;

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

import com.service.IUserService;

public class MainTest {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				"aop.xml");
		IUserService userService = (IUserService) context
				.getBean("myUserService");

		userService.addUser("ton", 56);
		userService.deleteUser("ton");
	}
}

 这儿得到UserService的bean不再需要一个代理,而是直接用UserService定义的bean。这样的好处就是如果下次要删除通知里的逻辑,不再需要日志的功能了,我不再需要改java文件,直接在配置文件里的有关切面的配置段去掉就可以了,很好的做到了为代码解耦。

 

工程代码文件在附件中。。。。

  • 大小: 13 KB
分享到:
评论
1 楼 Coraction 2014-03-29  

相关推荐

Global site tag (gtag.js) - Google Analytics