业务bean:
package com.chris.aop;
import org.springframework.stereotype.Service;
@Service("testService")
public class TestServiceBean {
public void save(){
System.out.println("save...");
}
public String update(String string){
System.out.println("update...");
return string;
}
public void add(String name){
System.out.println("add..." +name);
}
}
在spring3中,没有提供实现AOP注解以及cglib的jar包,因此需要自己手动下载以下jar包:
aspectjrt.jar、aspectjweaver.jar、aopalliance.jar、cglib-nop.jar
一.首先在spring配置文件中配置AOP功能
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- 加入 aop 命名空间 --> xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd <!-- 加入 aop schema 文件 --> http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.chris"/> <!-- 打开 AOP 功能 --> <aop:aspectj-autoproxy/> </beans>
二.编写切面类:
package com.chris.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect//声明该类为一个切面
@Component//一定要将该类交给spring容器管理
public class InterceptorDemo {
//定义切入点(该切入点针对TestServiceBean中的所有方法进行拦截)
//execution(返回值 包名.类名.方法名(参数))
@Pointcut("execution(* com.chris.aop.TestServiceBean.*(..))")
private void allMethod(){};//切入点的名称就是方法名
@Before("allMethod()")//定义切入点allMethod()的前置通知
public void doSomethingBefore(){
System.out.println("前置通知...");
}
@After("allMethod()")//定义切入点allMethod()的后置通知
public void doSomethingAfter(){
System.out.println("后置通知...");
}
@AfterReturning("allMethod()")//定义切入点allMethod()的最终通知
public void doSomethingFinally(){
System.out.println("最终通知...");
}
@AfterThrowing("allMethod()")//定义切入点allMethod()的异常通知
public void doSomethingInEx(){
System.out.println("异常通知...");
}
@Around("allMethod()")//定义切入点allMethod()的环绕通知,环绕通知方法一定要按照下面的形式定义(只可以修改方法名和参数名)
public Object doSomethingAround(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("进入环绕通知...");
Object result = pjp.proceed();//这里就是执行目标对象的业务方法了
System.out.println("退出环绕通知...");
return result;
}
}
这样我们在从容器中取得TestServiceBean并执行其中的方法,我们的切面就会工作了,测试代码:
public class TestDemo {
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
TestServiceBean personService = (TestServiceBean) applicationContext.getBean("testService");
personService.save();
}
}
/********程序的输出循序为***********/
前置通知...
进入环绕通知...
save...
后置通知...
最终通知...
退出环绕通知...