Spring(十一)AspectJ框架开发AOP(基于xml)

来源:互联网 发布:可延迟服务器调度算法 编辑:程序博客网 时间:2024/06/05 17:43

说明

AspectJ是一个基于Java语言的AOP框架
Spring2.0以后新增了对AspectJ切点表达式支持
@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面,所以可以使用xml方式和注解方式来开发AOP
新版本Spring框架,建议使用AspectJ方式来开发AOP
aspectj有五种通知

before( Formals )
前置通知(在方法执行前执行,如果通知抛出异常,阻止方法运行)
after( Formals ) returning [ ( Formal ) ]
后置通知(方法正常返回后执行,如果方法中抛出异常,通知无法执行
必须在方法执行后才执行,所以可以获得方法的返回值。)
after( Formals ) throwing [ ( Formal ) ]
异常停止(方法抛出异常后执行,如果方法没有抛出异常,无法执行)
after( Formals )
最终通知(方法执行完毕后执行,无论方法中是否出现异常,类似try-catch-finally里面的finally块)
around( Formals )
环绕通知( 方法执行前后分别执行,可以阻止方法的执行,必须手动执行目标方法)
在xml中对应:
这里写图片描述

导入的jar包:
1.aop联盟规范
2.spring aop实现
3.aspect规范
4.spring aspect实现
这里写图片描述

xml小例子

编写过程:
1.目标类:实现+接口
2.切面类:编写多个通知
3.aop编程,将通知应用到目标类
4.测试
目标类:
接口

public interface UserService {    public boolean addUser();    public void updateUser();    public void deleteUser();}

实现

public class UserServiceImpl implements UserService {    @Override    public boolean addUser() {        System.out.println("UserServiceDaoImpl addUser");        return true;    }    @Override    public void updateUser() {        //测试抛出异常通知    //  int i=1/0;        System.out.println("UserServiceDaoImpl updateUser");    }    @Override    public void deleteUser() {        System.out.println("UserServiceDaoImpl deleteUser");    }}

切面类
五种通知对方法的方法名称没有限制,但是方法的格式有限制。方法的格式会在xml配置中给出。

public class MyAspect  {    //前置通知    public void before(JoinPoint joinPoint){        System.out.println("MyAspect-before");    }    //最终通知    public void after(JoinPoint joinPoint){        System.out.println("MyAspect-after");    }    //环绕通知    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{        System.out.println("MyAspect-around-前");        Object obj=joinPoint.proceed();//执行目标方法        System.out.println("MyAspect-around-后");        return obj;    }    //后置通知    public void afterReturning(JoinPoint joinPoint,Object ret){        System.out.println("MyAspect-afterReturning  "+joinPoint.getSignature().getName()+"\t"+ret);    }    //异常通知    public void afterThrowing(JoinPoint joinPoint,Throwable e){        System.out.println("MyAspect-afterThrowing "+e.getMessage());    }}   

spring配置

<?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"       xsi:schemaLocation="http://www.springframework.org/schema/beans                             http://www.springframework.org/schema/beans/spring-beans.xsd                            http://www.springframework.org/schema/aop                             http://www.springframework.org/schema/aop/spring-aop.xsd">    <!-- 创建目标类 -->    <bean id="userServiceId" class="com.scx.xmlproxy.test.UserServiceImpl"></bean>     <!-- 创建切面类(通知) -->      <bean id="myAspectId" class="com.scx.xmlproxy.test.MyAspect"></bean>      <!-- aop编程-->     <aop:config proxy-target-class="true">        <aop:aspect ref="myAspectId">            <aop:pointcut expression="execution(* com.scx.xmlproxy.test.*.*(..))" id="myPointCut"/>            <!-- 前置通知                <aop:before method="before" pointcut-ref="myPointCut"/>                方法格式(参数1)                参数1:连接点描述                method:方法名                pointcut:切入点表达式                pointcut-ref:切入点引用            -->            <!-- 最终通知                 <aop:after method="after" pointcut-ref="myPointCut"/>                方法格式(参数1)                参数1:连接点描述            -->            <!-- 环绕通知                    <aop:around method="around" pointcut-ref="myPointCut"/>                     方法格式(参数1)                    参数:org.aspectj.lang.ProceedingJoinPoint             -->             <!-- 后置通知                    <aop:after-returning method="afterReturning" returning="ret" pointcut-ref="myPointCut"/>                    方法格式(参数1,参数2)                    参数1:连接点描述                    参数2:类型Object,参数名 returning="ret" 配置的            -->            <!--                 抛出异常                <aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut" throwing="e"/>                方法格式(参数1,参数2)                参数1:连接点描述对象                参数2:获得异常信息,类型Throwable ,参数名由throwing="e" 配置             -->        </aop:aspect>    </aop:config></beans>

测试:
测试时,最好只执行一个通知,否则结果会和想象的不一样orz.

@org.junit.Test    public void testProxy(){        String xmlPath="com/scx/xmlproxy/test/applicationContext.xml";        ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);        UserService userService=(UserService) applicationContext.getBean("userServiceId");        userService.addUser();        userService.updateUser();        userService.deleteUser();    }

测试结果:
前置通知:
这里写图片描述
后置通知:
这里写图片描述
异常通知:
为了出现异常我在实现类的updateUser方法里面里面添加了int i = 1 /0; 这行代码

这里写图片描述
结果如图所示输出了除0的异常
这时候我们修改为最终通知。运行结果:
这里写图片描述
我们发现updateUser方法没有因为异常输出,但是最终通知输出了。
环绕通知:
这里写图片描述

注解小例子在写篇文章给出~

1 0
原创粉丝点击