(转)spring aop(下)
Posted xdxxdx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(转)spring aop(下)相关的知识,希望对你有一定的参考价值。
昨天记录了Spring AOP学习的一部分(http://www.cnblogs.com/yanbincn/archive/2012/08/13/2635413.html),本来是想一口气梳理完的。但是大晚上时间不够(无奈一场奥运篮球总决赛耗费掉了2小时,不过的确相当精彩),又考虑到篇幅太长,阅读性比较差,所以将后半部分更偏于应用的重起一篇随笔。
利用方式一的配置起来,可见代码还是非常的厚重的,定义一个切面就要定义一个切面类,然而切面类中,就一个通知方法,着实没有必要。所以Spring提供了,依赖aspectj的schema配置和基于aspectj 注解方式。这两种方式非常简介方便使用,也是项目中普遍的使用方式。梳理之:
4、方式二:schema配置
a、业务类:
/**
* 业务类
*
* @author yanbin
*
*/
public class AspectBusiness {
/**
* 切入点
*/
public String delete(String obj) {
System.out.println("==========调用切入点:" + obj + "说:你敢删除我!===========\\n");
return obj + ":瞄~";
}
public String add(String obj) {
System.out.println("================这个方法不能被切。。。============== \\n");
return obj + ":瞄~ 嘿嘿!";
}
public String modify(String obj) {
System.out.println("=================这个也设置加入切吧====================\\n");
return obj + ":瞄改瞄啊!";
}
}
b、切面类:切面类中,包含了所有的通知
/**
* 定义一个切面
*
* @author yanbin
*
*/
public class AspectAdvice {
/**
* 前置通知
*
* @param jp
*/
public void doBefore(JoinPoint jp) {
System.out.println("===========进入before advice============ \\n");
System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");
System.out.print(jp.getSignature().getName() + "方法进行对 \'");
System.out.print(jp.getArgs()[0] + "\'进行删除!\\n\\n");
System.out.println("要进入切入点方法了 \\n");
}
/**
* 后置通知
*
* @param jp
* 连接点
* @param result
* 返回值
*/
public void doAfter(JoinPoint jp, String result) {
System.out.println("==========进入after advice=========== \\n");
System.out.println("切入点方法执行完了 \\n");
System.out.print(jp.getArgs()[0] + "在");
System.out.print(jp.getTarget().getClass() + "对象上被");
System.out.print(jp.getSignature().getName() + "方法删除了");
System.out.print("只留下:" + result + "\\n\\n");
}
/**
* 环绕通知
*
* @param pjp
* 连接点
*/
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("===========进入around环绕方法!=========== \\n");
// 调用目标方法之前执行的动作
System.out.println("调用方法之前: 执行!\\n");
// 调用方法的参数
Object[] args = pjp.getArgs();
// 调用的方法名
String method = pjp.getSignature().getName();
// 获取目标对象
Object target = pjp.getTarget();
// 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
Object result = pjp.proceed();
System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + result + "\\n");
System.out.println("调用方法结束:之后执行!\\n");
}
/**
* 异常通知
*
* @param jp
* @param e
*/
public void doThrow(JoinPoint jp, Throwable e) {
System.out.println("删除出错啦");
}
}
c、配置文件:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<!-- ==============================利用spring 利用aspectj来配置AOP================================ -->
<!-- 声明一个业务类 -->
<bean id="aspectBusiness" class="aop.schema.AspectBusiness" />
<!-- 声明通知类 -->
<bean id="aspectAdvice" class="aop.schema.advice.AspectAdvice" />
<aop:config>
<aop:aspect id="businessAspect" ref="aspectAdvice">
<!-- 配置指定切入的对象 -->
<aop:pointcut id="point_cut" expression="execution(* aop.schema.*.*(..))" />
<!-- 只匹配add方法作为切入点
<aop:pointcut id="except_add" expression="execution(* aop.schema.*.add(..))" />
-->
<!-- 前置通知 -->
<aop:before method="doBefore" pointcut-ref="point_cut" />
<!-- 后置通知 returning指定返回参数 -->
<aop:after-returning method="doAfter"
pointcut-ref="point_cut" returning="result" />
<aop:around method="doAround" pointcut-ref="point_cut"/>
<aop:after-throwing method="doThrow" pointcut-ref="point_cut" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
d、测试类:
public class Debug {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("aop/schema_aop.xml");
AspectBusiness business = (AspectBusiness) context.getBean("aspectBusiness");
business.delete("猫");
}
}
5、方式三:aspectj注解
注解在项目中已经到处都是了,撇开一些优劣不提,开发的便利性和可读性是非常的方便的。用来配置Spring AOP也非常简单便利
a、业务类:
/**
* 业务类
*
* @author yanbin
*
*/
@Component
public class Business {
/**
* 切入点
*/
public String delete(String obj) {
System.out.println("==========调用切入点:" + obj + "说:你敢删除我!===========\\n");
return obj + ":瞄~";
}
public String add(String obj) {
System.out.println("================这个方法不能被切。。。============== \\n");
return obj + ":瞄~ 嘿嘿!";
}
public String modify(String obj) {
System.out.println("=================这个也设置加入切吧====================\\n");
return obj + ":瞄改瞄啊!";
}
}
b、切面类:
/**
* 定义切面
*
* @Aspect : 标记为切面类
* @Pointcut : 指定匹配切点
* @Before : 指定前置通知,value中指定切入点匹配
* @AfterReturning :后置通知,具有可以指定返回值
* @AfterThrowing :异常通知
*
* @author yanbin
*
*/
@Component
@Aspect
public class AspectAdvice {
/**
* 指定切入点匹配表达式,注意它是以方法的形式进行声明的。
*/
@Pointcut("execution(* aop.annotation.*.*(..))")
public void anyMethod() {
}
/**
* 前置通知
*
* @param jp
*/
@Before(value = "execution(* aop.annotation.*.*(..))")
public void doBefore(JoinPoint jp) {
System.out.println("===========进入before advice============ \\n");
System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");
System.out.print(jp.getSignature().getName() + "方法进行对 \'");
System.out.print(jp.getArgs()[0] + "\'进行删除!\\n\\n");
System.out.println("要进入切入点方法了 \\n");
}
/**
* 后置通知
*
* @param jp
* 连接点
* @param result
* 返回值
*/
@AfterReturning(value = "anyMethod()", returning = "result")
public void doAfter(JoinPoint jp, String result) {
System.out.println("==========进入after advice=========== \\n");
System.out.println("切入点方法执行完了 \\n");
System.out.print(jp.getArgs()[0] + "在");
System.out.print(jp.getTarget().getClass() + "对象上被");
System.out.print(jp.getSignature().getName() + "方法删除了");
System.out.print("只留下:" + result + "\\n\\n");
}
/**
* 环绕通知
*
* @param pjp
* 连接点
*/
@Around(value = "execution(* aop.annotation.*.*(..))")
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("===========进入around环绕方法!=========== \\n");
// 调用目标方法之前执行的动作
System.out.println("调用方法之前: 执行!\\n");
// 调用方法的参数
Object[] args = pjp.getArgs();
// 调用的方法名
String method = pjp.getSignature().getName();
// 获取目标对象
Object target = pjp.getTarget();
// 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
Object result = pjp.proceed();
System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + result + "\\n");
System.out.println("调用方法结束:之后执行!\\n");
}
/**
* 异常通知
*
* @param jp
* @param e
*/
@AfterThrowing(value = "execution(* aop.annotation.*.*(..))", throwing = "e")
public void doThrow(JoinPoint jp, Throwable e) {
System.out.println("删除出错啦");
}
}
c、配置:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="aop.annotation" />
<!-- 打开aop 注解 -->
<aop:aspectj-autoproxy />
</beans>
d、测试类:
/**
* 测试类
*
* @author yanbin
*
*/
public class Debug {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation_aop.xml");
Business business = (Business) context.getBean("business");
business.delete("猫");
}
}
以上是关于(转)spring aop(下)的主要内容,如果未能解决你的问题,请参考以下文章