首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

应用Spring AOP(1)

2013-11-16 
应用Spring AOP(一)??????? AOP即Aspect-Oriented Programming,面向方面编程。AOP和OOP类似,也是一种编程模

应用Spring AOP(一)

??????? AOP即Aspect-Oriented Programming,面向方面编程。AOP和OOP类似,也是一种编程模式。但是AOP并不能取代OOP,它只是对OOP的扩展和补充。Spring AOP是基于AOP编程模式的一个框架,它实现了AOP范围内的大多数功能,包括Advice、Pointcut等。

??????? AOP典型的应用场景:


?前置通知:

package com.aop;import java.lang.reflect.Method;import org.apache.log4j.Logger;import org.springframework.aop.MethodBeforeAdvice;public class BeforeLogAdvice implements MethodBeforeAdvice {private Logger logger = Logger.getLogger(BeforeLogAdvice.class);public void before(Method method, Object[] args, Object target)throws Throwable {String targetClassName = target.getClass().getName();String targetMethodName = method.getName();// args[0] = "Juve";//可以改变参数String logInfoText = "前置通知:" + targetClassName + "类的"+ targetMethodName + "方法开始执行";logger.info(logInfoText);}}

?前置通知用于将方面代码插入方法之前,也就是说,在方法执行之前,会首先执行前置通知里的代码。包含前置通知代码的类就是方面,这个类需要实现org.springframework.aop.MethodBeforeAdvice接口。该接口中的before方法如上,参数中的method表示处于切点的方法,args表示这些方法的参数值(可以在这儿改变参数值),target表示这些方法所在的类的对象实例。

?

后置通知:

package com.aop;import java.lang.reflect.Method;import org.apache.log4j.Logger;import org.springframework.aop.AfterReturningAdvice;public class AfterLogAdvice implements AfterReturningAdvice {private Logger logger = Logger.getLogger(AfterLogAdvice.class);public void afterReturning(Object returnValue, Method method,Object[] args, Object target) throws Throwable {// 获取被调用的类名String targetClassName = target.getClass().getName();// 获取被调用的方法名String targetMethodName = method.getName();// 日志格式字符串String logInfoText = "后置通知:" + targetClassName + "类的"+ targetMethodName + "方法已经执行";// 将日志信息写入配置的文件中logger.info(logInfoText);}}

后置通知的代码在调用被拦截的方法后调用。注意afterReturning方法的第一参数returnValue表示被拦截的方法的返回值。

?

环绕通知:

package com.aop;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.apache.log4j.Logger;public class LogAroundAdvice implements MethodInterceptor {private Logger logger = Logger.getLogger(LogAroundAdvice.class);public Object invoke(MethodInvocation invocation) throws Throwable {// 获取被调用的方法名String targetMethodName = invocation.getMethod().getName();/*invocation.getArguments()[0] = "Alex";//也可以得到或者改变要执行的方法的参数 */long beginTime = System.currentTimeMillis();invocation.proceed(); //调用被拦截的方法long endTime = System.currentTimeMillis();// 日志格式字符串String logInfoText = "环绕通知:" + targetMethodName + "方法调用前时间" + beginTime+ "毫秒," + "调用后时间" + endTime + "毫秒";// 将日志信息写入配置的文件中logger.info(logInfoText);//这儿相当于强行将拦截的方法的返回值设成了nullreturn null;//return invocation.proceed();}}

?环绕通知能力最强,可以在方法调用前执行通知代码,可以决定是否还调用目标方法。也就是说它可以控制被拦截的方法的执行,还可以控制被拦截方法的返回值。

?

异常通知:

package com.aop;import org.apache.log4j.Logger;import java.lang.reflect.Method;import org.springframework.aop.ThrowsAdvice;public class ThrowsLogAdvice implements ThrowsAdvice {private Logger logger = Logger.getLogger(ThrowsLogAdvice.class);public void afterThrowing(Method method, Object[] args, Object target,Throwable exeptionClass) {// 获取被调用的类名String targetClassName = target.getClass().getName();// 获取被调用的方法名String targetMethodName = method.getName();// 日志格式字符串String logInfoText = "异常通知:执行" + targetClassName + "类的"+ targetMethodName + "方法时发生异常";// 将日志信息写入配置的文件中logger.info(logInfoText);}/*public void afterThrowing(IllegalArgumentException e){System.out.println(e.getMessage());}*/}

如果在调用方法时发生异常,异常通知类可以提供一个机会来处理所发生的异常。org.springframework.aop.ThrowsAdvice接口中afterThrowing有两种重载形式:

public void afterThrowing(Throwable e);public void afterThrowing(Method method, Object[] args, Object target, Throwable exeptionClass);

第一种重载形式中,e表示方法抛出的异常类型。如果参数e的类型与异常类型不匹配,afterThrowing将不会被调用。如果这两种重载形式同时存在,并且都匹配抛出的异常类型,那么第一种重载形式优先调用。

?

目标接口IUserService和类UserService:

package com.service;public interface IUserService {public void addUser(String name, int age);public void deleteUser(String name);}

?

package com.service;public class UserService implements IUserService {public void addUser(String name, int age) {//省略诸如操作数据库等复杂的逻辑操作System.out.println("add user "+ name +" successfully");}public void deleteUser(String name) {//省略诸如操作数据库等复杂的逻辑操作System.out.println("deleted one user named " + name);throw new RuntimeException("这是特意抛出的异常信息!");}}

这个工程中用到了log4j,log4j.properties的配置文件内容就不贴出来了。别忘了在WEB-INF里的logs目录下新建几个log文件。

?

applicationContext.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"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-3.0.xsd"><bean id="myUserService" ref="myUserService"></property></bean></beans>

?这里目标类和几个通知类的bean定义就不说了,重点看一下id为myProxy的ProxyFactoryBean的代理类的定义,它包含三个属性:

proxyInterface:代理所实现的接口。Spring AOP无法截获未在该属性指定的接口中的方法。

interceptorNames:用于拦截方法的拦截器名,通知类是其中一种类型,也可以是Advisor。

target:目标类。要注意的是一个代理只能有一个target。

?

主测试类:

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("applicationContext.xml");IUserService userService = (IUserService) context.getBean("myProxy");userService.addUser("ton", 56);userService.deleteUser("ton");}}

?可以看到,这儿应用的bean是myProxy,而不是myUserService。运行结果如下:

[INFO ] [22:08:13] com.aop.BeforeLogAdvice - 前置通知:com.service.UserService类的addUser方法开始执行add user ton successfully[INFO ] [22:08:13] com.aop.LogAroundAdvice - 环绕通知:addUser方法调用前时间1382969293109毫秒,调用后时间1382969293109毫秒[INFO ] [22:08:13] com.aop.AfterLogAdvice - 后置通知:com.service.UserService类的addUser方法已经执行[INFO ] [22:08:13] com.aop.BeforeLogAdvice - 前置通知:com.service.UserService类的deleteUser方法开始执行deleted one user named ton[INFO ] [22:08:13] com.aop.ThrowsLogAdvice - 异常通知:执行com.service.UserService类的deleteUser方法时发生异常Exception in thread "main" java.lang.RuntimeException: 这是特意抛出的异常信息!

?

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

热点排行