读书人

spring AOP 例证

发布时间: 2012-09-21 15:47:26 作者: rapoo

spring AOP 例子
先看 advice 类

package com.supben.advice;import java.lang.reflect.Method;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.aop.AfterReturningAdvice;import org.springframework.aop.MethodBeforeAdvice;import org.springframework.aop.ThrowsAdvice;/** * 实现spring advice 接口 *  * @author shencl *  */public class TestAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {private static final Logger log = LoggerFactory.getLogger(TestAdvice.class);/** * before 通知 */public void before(Method method, Object[] args, Object target) throws Throwable {log.info(target.getClass().getSimpleName() + "类的" + method.getName() + "方法,执行TestAdvice的before通知");// 通知要做的业务if (method.getName().startsWith("get")) {log.info("只有方法名是以get开始的方法,才会执行到这句话....");}}/** * after 通知 */public void afterReturning(Object arg0, Method method, Object[] arg2, Object target) throws Throwable {log.info(target.getClass().getSimpleName() + "类的" + method.getName() + "方法,执行TestAdvice的after通知");}/** * 异常通知 */public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {log.info(target.getClass().getSimpleName() + "类的" + method.getName() + "方法,执行TestAdvice的throwing通知");}}




配置文件
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context-2.5.xsd    http://www.springframework.org/schema/tx    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd    http://www.springframework.org/schema/aop    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"><context:annotation-config /><!-- 扫描com.supben 下所有的包--><context:component-scan base-package="com.supben" /><bean id="testAdvice" /><aop:config>   <aop:advisor pointcut="execution(* *..service.*Service.*(..))"advice-ref="testAdvice" /></aop:config></beans>


service接口
package com.supben.service;public interface FirstService {public void get();public void exception();}

service实现类
package com.supben.service.impl;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import com.supben.service.FirstService;@Service("firstService")public class FirstServiceImpl implements FirstService {private static final Logger log = LoggerFactory.getLogger(FirstServiceImpl.class);public void get() {log.info("方法执行ing.....");}public void exception() {throw new RuntimeException("测试异常");}}


测试类
package com.supben.test;import junit.framework.TestCase;import org.junit.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.supben.service.FirstService;import com.supben.spring.SpringContextUtil;public class ServiceTest extends TestCase {/** * 装载spring 配置文件 */static {new ClassPathXmlApplicationContext("application.xml");}@Testpublic void testGet() {FirstService service = SpringContextUtil.getBean("firstService");service.get();}@Testpublic void testGet2() {FirstService service = SpringContextUtil.getBean("firstService");service.exception();}}


测试结果:

2012-05-09 15:10:10,028 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的get方法,执行TestAdvice的before通知
2012-05-09 15:10:10,030 INFO [com.supben.advice.TestAdvice] - 只有方法名是以get开始的方法,才会执行到这句话....
2012-05-09 15:10:10,032 INFO [com.supben.service.impl.FirstServiceImpl] - 方法执行ing.....
2012-05-09 15:10:10,032 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的get方法,执行TestAdvice的after通知



2012-05-09 15:10:10,035 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的exception方法,执行TestAdvice的before通知
2012-05-09 15:10:10,035 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的exception方法,执行TestAdvice的throwing通知

结果分析:
get方法满足执行之前会 执行 before通知,执行完成后会执行after通知。

exception方法执行之前会执行before 通知,因为方法名不是以get开头,所以不会执行before通知的业务逻辑。然后出现异常了会执行throwing通知,因为出异常了,方法没有执行完毕,所以不会触发after通知。


概念:

切面(aspect): 翻译成外貌更合适:整个程序相当于一个密封的圆柱体,即一个外貌,现在要面向这个东西编程,在不改变原来类(FirstServiceImpl)的情况下,改变里边的代码。通知(advice):TestAdvice里边的before,after,throwing方法都是通知。 常见的有前置通知,后置通知,异常通知。
切点(cut-point):定义通知应该应用在哪些地方,本例是FirstServiceImpl中的get方法和exception方法,一般用正则表达式定义。
切点表达式:配置文件中的execution(* *..service.*Service.*(..)) 是一个切点表达式,表示的是一个一个的方法.比如本例中的表达式,意思是 包目录的最后一级是service,类/接口名 后缀为Service的 class文件里的,方法名为任意名称,参数个数不限的 方法。 * 表示任意,(..)表示方法参数个数不限。
目标对象(traget):FirstService就是目标对象。

此外还有两个重要的概念
引入(Introduction):允许为已存在类添加新方法和属性。
代理(Proxy):将通知应用到目标对象后创建的对象。
本文章不讨论。

读书人网 >编程

热点推荐