AOP(XML)【理解】【应用】【重点】

来源:互联网 发布:手机淘宝不能追加评论 编辑:程序博客网 时间:2024/06/07 22:04

1.AOP基础实例

A.导入jar包

核心包(4个) 日志(2个) AOP(4个)

Spring进行AOP开发(1个)(3.2资源包)

spring-aop-3.2.0.RELEASE.jar

Spring整合AspectJ框架(3.2资源包)

spring-aspects-3.2.0.RELEASE.jar

AOP联盟规范(1个) (3.0.2依赖包)

com.springsource.org.aopalliance-1.0.0.jar

aspectJ支持(1个) (3.0.2依赖包)

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

B.制作目标对象类(配置成Bean)

public class UserImpl {

//当前类的三个方法中具有共性功能System.out.println("共性功能1"); 抽取出来 public void add(){

//共性功能1被抽取走了,放入到了MyAdvice类中的functionOne方法里 System.out.println("共性功能2");

System.out.println("user add....");

}

}

注意:共性功能被抽取后,不是在原始位置进行调用,而是将共性功能删除

C.将抽取的功能制作成通知(配置成Bean)

public class MyAdvice {

//被抽取的共性功能1

public void functionOne(){

System.out.println("共性功能1");

}

}

说明:被抽取的共性功能制作成独立的类中方法。由于要将两个对象中的内容融合,Spring在控 制其融合的过程必须控制两个对象,因此需要分别将两个类配置为Spring管理的Bean

D.开启AOP空间的支持

<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

">

E.配置AOP的切面

<!-- 配置AOP -->

<aop:config>

<!-- 配置切面,指定切面类的Bean:配置切入点与通知之间的关系 --> <!-- ref:配置切面对应的Bean --> <aop:aspect ref="myAdvice"> <!-- 声明通知的类别是何种类型 前置通知--> <!-- 配置前置通知 --> <!-- aop:before表示在原始方法执行前追加功能 --> <!-- pointcut:配置Spring监控的方法切入点 --> <!-- method:配置的切面类中对应的共性功能-方法名称 --> <aop:before pointcut="execution(* cn.itcast.aop.one.UserImpl.add())" method="functionOne"/> </aop:aspect> </aop:config> F.制作Spring格式的客户端程序测试 ApplicationContext ctx = new ClassPathXmlApplicationContext(“applicationContext.xml”); UserDao dao = (UserDao)ctx.getBean(“userDao”); dao.add(); 2.切入点表达式 格式:execution(切入点表达式) execution([方法的访问控制修饰符] 方法的返回值 包名.类名/接口名.方法名(参数)) 注意:方法的访问控制修饰符可以省略 范例: public void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数无返回值的add方法 void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数无返回值的add方法 方法的返回值可以写具体的返回值,或者写*表示任意返回值 void cn.itcast.UserDAO.add()公共的cn.itcat包中的UserDAO类的无参数无返回值的add方法 * cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数不限定返回值的add方法 包名,方法名 * cn.itcast.*.dao.UserDAO.add() cn包下的itcast包下的任意包下的dao包下的….. * cn.itcast..dao.UserDAO.add() cn包下的itcast包下的任意层包下的dao包下的….. * *..*.*() 任意包下的任意类中的任意方法 参数 add() 无参数 add(*) 一个参数 add(int) 一个int型参数 add(*,*) 两个参数 add(*,int) 两个参数,第一个任意,第二个int add(..) 任意参数 add(*,..) 至少一个参数 特殊格式: * cn.itcast.UserDAO.add(..) && args(int,int) 错误 * cn.itcast.UserDAO.add(..) && args(int,int) 正确 * cn.itcast.UserDAO.add(int,int) && args(a,b) 不常用,正确 * cn.itcast.UserDAO.add(int,int) && args(b,a) 不常用,正确 3.切入点配置方式

切入点配置时,可以设置切面间共享切入点,也可以设置切面内共享切入点,还可以设置局部切入点

格式一:配置在通知类别后面 <aop:before pointcut="execution(public void *..*.*Impl.a*())" …. 格式二:配置在某个切面中,在当前切面范围内共享 <aop:aspect ref="myAdvice"> <!-- 配置同一个切面中使用的公共切入点 --> <aop:pointcut expression="execution(public void *..*.*Impl.a*())" id="pt2"/> <aop:before pointcut-ref="pt2" ….. 格式三:配置在AOP总配置中,在全部范围内共享 <aop:config> <aop:pointcut expression="execution(public void *..*.*Impl.a*())" id="pt1"/> <aop:aspect ref="myAdvice"> <aop:before pointcut-ref="pt1"…… </aop:aspect> </aop:config> 范例: <aop:config> <!-- 所有切面共享的切入点 --> <aop:pointcut expression="execution(* cn.itcast..*Tar*.*())" id="pt"/> <aop:aspect ref="myAdvice"> <!-- 在一个切面内共享的切入点:配置独立的切入点表达式对象 --> <aop:pointcut expression="execution(* cn.itcast..*Tar*.*(..))" id="pt1"/> <aop:before pointcut-ref="pt" method="fn"/> <aop:before pointcut="execution(* *..*.*(..))" method="fn"/> </aop:aspect> <aop:aspect ref="myAdvice"> <!-- 配置独立的切入点表达式对象 --> <aop:pointcut expression="execution(* cn.itcast..*Tar*.*(..))" id="pt2"/> <aop:before pointcut-ref="pt" method="fn"/> <aop:before pointcut-ref="pt" method="fn"/> </aop:aspect> </aop:config> 4.通知类别 通知共有五种类别 before:在原始操作前运行 after: 在原始操作后运行,无论方法是否抛出异常 afterReturning:在原始操作后运行,只有方法正常结束才运行,抛出异常则不运行 afterThrowing:在原始操作中如果抛出异常,运行 around: 在原始操作前后运行,通过ProceedingJoinPoint对象调用procee()方法完成对原始操作的调用 //环绕通知

public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("around before......");

//调用原始方法

pjp.proceed();

System.out.println("around after......");} 通知的配置格式 <aop:before pointcut-ref="pt2" method="before"/> <aop:after pointcut-ref="pt2" method="after"/> <aop:after-returning pointcut-ref="pt2" method="afterReturning"/> <aop:after-throwing pointcut-ref="pt2" method="afterThrowing"/> <aop:around pointcut-ref="pt2" method="around"/> 5.通知顺序 在切入点之前运行的通知 执行允许与配置顺序有关,在上面的先运行 在切入点之后运行的通知 在同一个切面中 执行允许与配置顺序有关,在上面的先运行 在不同的切面中 执行允许与配置顺序有关,与切面的配置顺序相反 总结:不同通知类型执行的顺序以配置顺序为准 6.获取通知参数 为环绕通知之外的通知方法定义形参JoinPoint,该参数必须是通知方法的第一个参数 获取参数:Obejct[] args = jp.getArgs(); 范例: public void before(JoinPoint jp){ Object[] objs = jp.getArgs(); System.out.println("before......"+objs[0]+","+objs[1]); } 为环绕通知方法定义形参ProceedingJoinPoint对象 获取参数:Obejct[] args = pjp.getArgs(); 7.获取通知返回值 afterReturning 与 around可以获取方法的返回值 A.around通知获取返回值 ProceedingJoinPoint对象执行调用原始操作的返回值就是原始方法的运行返回值 Object res = pt.proceed(args); 注意:如果原始方法返回值为void类型,则around方法返回值设置为Object 如果原始方法返回值为非void类型,则around方法内必须将原始方法调用的结果返回 原始方法返回值为void类型的,通知内获取的返回值统一为null public Object around(ProceedingJoinPoint pjp) throws Throwable{ Object res = pjp.proceed(args); return res; } B.afterReturning通知获取返回值 在通知方法的参数中,声明一个Object类型的参数,用于保存方法的返回值 public void afterReturning(JoinPoint jp,Object abc){ System.out.println("afterReturning......"+ abc); } 在配置文件中,为afterReturning声明保存返回值的变量名

<aop:after-returning method="afterReturning" returning="abc"/> 8.获取通知异常对象 异常对象的获取方式与返回值很相似,声明变量,在配置中声明保存异常对象的变量名 <aop:after-throwing pointcut-ref="pt" method="afterThrowing" throwing="e"/> public void afterThrowing (Throwable e){ System.out.println("afterThrowing......."+ e); }



0 0