(1)使用配置文件方式
1.业务类,用来被横切
public class AspectBusiness
{
/**
* 切入点
*/
public String delete(String obj)
{
System.out.println(obj + "说:你敢删除我!===========\n");
return obj + ":处理完毕";
}
}
2.切面类,里面包含了所有通知
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("删除出错啦");
}
}
3.配置文件
<?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">
<!-- 声明一个业务类 -->
<bean id="aspectBusiness" class="spring.AspectBusiness" />
<!-- 声明通知类 -->
<bean id="aspectAdvice" class="spring.AspectAdvice" />
<aop:config>
<aop:aspect id="businessAspect" ref="aspectAdvice">
<!-- 配置指定切入的对象 -->
<aop:pointcut id="point_cut" expression="execution(* spring.*.*(..))" />
<!-- 只匹配add方法作为切入点
<aop:pointcut id="except_add" expression="execution(* spring.*.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>
4.测试类
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");//读取bean.xml中的内容
AspectBusiness business = (AspectBusiness) ctx.getBean("aspectBusiness");
business.delete("猫");
结果为:
===========进入before advice============
准备在class spring.AspectBusiness对象上用delete方法进行对 '猫'进行删除!
要进入切入点方法了
===========进入around环绕方法!===========
调用方法之前: 执行!
猫说:你敢删除我!===========
输出:猫;delete;spring.AspectBusiness@349471;猫:处理完毕
调用方法结束:之后执行!
==========进入after advice===========
切入点方法执行完了
猫在class spring.AspectBusiness对象上被delete方法删除了只留下:null
注:配置文件中execution的定义:
(2)使用注解方式
实际上和使用xml配置方式一样,只不过在类上加入@Aspect,声明这是一个切面
@Aspect
public class AspectAdvice
{
//指定切入点表达式,它是以方法的方式进行声明的
@Pointcut("execution(* spring.*.*(..))")
public void anyMethod()
{
}
//指定前置通知,value中指定切入点匹配
@Before(value = "execution(* spring.*.*(..))")
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");
}
//后置通知,获得返回值
@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");
}
@Around(value = "execution(* spring.*.*(..))")
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");
}
@AfterThrowing(value = "execution(* spring.*.*(..))", throwing = "e")
public void doThrow(JoinPoint jp, Throwable e)
{
System.out.println("删除出错啦");
}
}
配置文件:
<!-- 声明一个业务类 -->
<bean id="aspectBusiness" class="spring.AspectBusiness" />
<!-- 声明通知类 -->
<bean id="aspectAdvice" class="spring.AspectAdvice" />
<aop:aspectj-autoproxy />