1、概念
(1)AspectJ是一个基于Java语言的AOP框架
(2)Spring2.0以后新增了对AspectJ切入点表达式的支持
(3)AspectJ是AspectJ1.5的新增功能,通过JDK5注解技术,允许在Bean类中定义切面。新版本的Spring框架建议使用AspectJ方式来开发AOP
2、切入点表达式
(1)execution():用语描述方法
语法:execution(修饰符、返回值、包、类、方法(参数)、异常)
修饰符:一般省略
public:公共方法
*:任意
返回值
void:没有返回值
String:返回值为字符串
*:返回值任意
方法:不能省略
参数
(..)参数任意
(2)案例:
<aop:pointcut id="myPointCut" expression="execution(* pers.zhb.proxy.*.*(..))">aop:pointcut>
(3)其他表达式
within:匹配包或者子包中的方法
this:匹配接口中代理对象中的方法
target:匹配实现接口的目标对象的方法
args:匹配参数格式符合标准的方法
bean:对指定bean所有的方法
2、AspectJ通知类型
(1)aop联盟定义通知类型:具有特性接口,必须实现,从而确定方法名称。
(2)aspectj通知类型:只定义类型名称。已经方法格式。
before:前置通知(应用:各种校验)
在方法执行前执行,如果通知抛出异常,阻止方法运行
afterRetuming:后置通知(应用:常规数据处理)
方法正常返回后执行,如果方法中抛出异常,通知无法执行
必须在方法执行后才执行,所以可以获得方法的返回值
around:环统通知(应用:十分强大,可以做任何事情)
方法执行前后分别执行,可以阻止方法的执行。
必须手动执行目标方法
afterThrowing:抛出异常通知(应用:包装异常信息)
方法抛出异常后执行,如果方法没有抛出异常,无法执行
after最终通知(应用:清理现场)
方法执行完毕后执行,无论方法中是否出现异常
3、导入jar包(四个)
aop联盟规范
spring aop实现
aspect规范
spring aspect实现
4、源码
(1)AspectJAfterThrowingAdvice
(2)AspectJAfterAdvice
5、基于XML文件的配置(前置通知)
(1)目标类的接口和实现类:
public interface StudentService { void addStudent(); void updateStudent(); void deleteStudent(); }
public class StudentServiceImpl implements StudentService { @Override public void addStudent() { System.out.println("addStudent"); } @Override public void updateStudent() { System.out.println("updateStudent"); } @Override public void deleteStudent() { System.out.println("deleteStudent"); } }
(2)切面类(含有通知):
public class MyAspect { public void before(JoinPoint joinPoint){ System.out.println("前置通知:"+ joinPoint.getSignature().getName()); } }
(3)配置文件:
xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans" 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="studentService" class="pers.zhb.aspectxml.StudentServiceImpl">bean> <bean id="myAspect" class="pers.zhb.aspectxml.MyAspect">bean> <aop:config> <aop:aspect ref="myAspect"> <aop:pointcut id="myPointCut" expression="execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))">aop:pointcut> <aop:before method="before" pointcut-ref="myPointCut">aop:before> aop:aspect> aop:config> beans>
(4)测试类:
public class TestAspectXml { public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); //获得目标类 pers.zhb.aspectxml.StudentService studentService= (StudentService) applicationContext.getBean("studentService"); studentService.addStudent(); studentService.deleteStudent(); studentService.updateStudent(); } }
前置通知:addStudent
addStudent
前置通知:deleteStudent
deleteStudent
前置通知:updateStudent
updateStudent
6、基于XML文件的配置(后置通知)
(1)定义接口和接口的实现类:
public interface StudentService { void addStudent(); void updateStudent(); String deleteStudent(); }
public class StudentServiceImpl implements StudentService { @Override public void addStudent() { System.out.println("addStudent"); } @Override public void updateStudent() { System.out.println("updateStudent"); } @Override public String deleteStudent() { System.out.println("deleteStudent"); return "nihao"; } }
(2)切面类:
public class MyAspect { public void before(JoinPoint joinPoint){ System.out.println("前置通知:"+ joinPoint.getSignature().getName()); } public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述 //参数二:类型Object,参数名returning配置的 System.out.println("后置通知:"+ joinPoint.getSignature().getName()+" "+ret); } }
(3)配置文件:
xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans" 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="studentService" class="pers.zhb.aspectxml.StudentServiceImpl">bean> <bean id="myAspect" class="pers.zhb.aspectxml.MyAspect">bean> <aop:config> <aop:aspect ref="myAspect"> <aop:pointcut id="myPointCut" expression="execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))">aop:pointcut> <aop:before method="before" pointcut-ref="myPointCut">aop:before> <aop:after-returning method="after" pointcut-ref="myPointCut" returning="ret">aop:after-returning> aop:aspect> aop:config> beans>
(4)测试类:
public class TestAspectXml { public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); //获得目标类 pers.zhb.aspectxml.StudentService studentService= (StudentService) applicationContext.getBean("studentService"); studentService.addStudent(); studentService.deleteStudent(); studentService.updateStudent(); } }
前置通知:addStudent addStudent 后置通知:addStudent null 前置通知:deleteStudent deleteStudent 后置通知:deleteStudent nihao 前置通知:updateStudent updateStudent 后置通知:updateStudent null
7、基于XML文件的配置(环绕通知)
(1)切面类:
public class MyAspect { public void before(JoinPoint joinPoint){ System.out.println("前置通知:"+ joinPoint.getSignature().getName()); } public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述 //参数二:类型Object,参数名returning配置的 System.out.println("后置通知:"+ joinPoint.getSignature().getName()+" "+ret); } public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ //手动执行目标方法 System.out.println("前"); Object object=proceedingJoinPoint.proceed(); System.out.println("后"); return null; } }
(2)配置文件:
<aop:around method="around" pointcut-ref="myPointCut">aop:around>
(3)测试结果:
前置通知:addStudent
前
addStudent
后
后置通知:addStudent null
前置通知:deleteStudent
前
deleteStudent
后
后置通知:deleteStudent null
前置通知:updateStudent
前
updateStudent
后
后置通知:updateStudent null
8、基于XML文件的配置(抛出异常)
(1)定义目标类的接口和接口的实现类:
public interface StudentService { void addStudent(); void updateStudent(); String deleteStudent(); }
在方法中制造异常:
public class StudentServiceImpl implements StudentService { @Override public void addStudent() { System.out.println("addStudent"); } @Override public void updateStudent() { int num=9/0; System.out.println("updateStudent"); } @Override public String deleteStudent() { System.out.println("deleteStudent"); return "nihao"; } }
(2)切面类:
public class MyAspect { public void before(JoinPoint joinPoint){ System.out.println("前置通知:"+ joinPoint.getSignature().getName()); } public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述 //参数二:类型Object,参数名returning配置的 System.out.println("后置通知:"+ joinPoint.getSignature().getName()+" "+ret); } public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ //手动执行目标方法 System.out.println("前"); Object object=proceedingJoinPoint.proceed(); System.out.println("后"); return null; } public void AfterThrowing(JoinPoint joinPoint,Throwable throwable){ System.out.println("抛出异常的通知:"+throwable.getMessage()); } }
(3)配置文件:
<aop:after-throwing method="AfterThrowing" pointcut-ref="myPointCut" throwing="throwable">aop:after-throwing>
(4)测试:
前置通知:addStudent
前
addStudent
后
后置通知:addStudent null
前置通知:deleteStudent
前
deleteStudent
后
后置通知:deleteStudent null
前置通知:updateStudent
前
抛出异常的通知:/ by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
9、基于XML文件的配置(最终通知)
(1)目标类的接口和接口的实现类:
public interface StudentService { void addStudent(); void updateStudent(); String deleteStudent(); }
public class StudentServiceImpl implements StudentService { @Override public void addStudent() { System.out.println("addStudent"); } @Override public void updateStudent() { int num=9/0; System.out.println("updateStudent"); } @Override public String deleteStudent() { System.out.println("deleteStudent"); return "nihao"; } }
(2)切面类:
public class MyAspect { public void before(JoinPoint joinPoint){ System.out.println("前置通知:"+ joinPoint.getSignature().getName()); } public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述 //参数二:类型Object,参数名returning配置的 System.out.println("后置通知:"+ joinPoint.getSignature().getName()+" "+ret); } public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ //手动执行目标方法 System.out.println("前"); Object object=proceedingJoinPoint.proceed(); System.out.println("后"); return null; } public void AfterThrowing(JoinPoint joinPoint,Throwable throwable){ System.out.println("抛出异常的通知:"+throwable.getMessage()); } public void myafter(JoinPoint joinPoint){ System.out.println("最终通知"); } }
(3)配置文件:
<aop:after method="myafter" pointcut-ref="myPointCut">aop:after>
(4)测试结果:
前置通知:addStudent 前 addStudent 最终通知 后
后置通知:addStudent null 前置通知:deleteStudent 前 deleteStudent 最终通知 后
后置通知:deleteStudent null 前置通知:updateStudent 前 最终通知 抛出异常的通知:/ by zero Exception in thread "main" java.lang.ArithmeticException: / by zero
不管有没有异常都会执行最终通知。
10、基于注解的配置
(1)目标类的接口和接口的实现类:
public interface StudentService { void addStudent(); void updateStudent(); String deleteStudent(); }
import org.springframework.stereotype.Service; @Service("studentService") public class StudentServiceImpl implements StudentService { @Override public void addStudent() { System.out.println("addStudent"); } @Override public void updateStudent() { int num=9/0; System.out.println("updateStudent"); } @Override public String deleteStudent() { System.out.println("deleteStudent"); return "nihao"; } }
(2)配置文件:
xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns="http://www.springframework.org/schema/beans" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="pers.zhb.aspectxml">context:component-scan> <aop:aspectj-autoproxy>aop:aspectj-autoproxy> beans>
(3)切面:
@Component @Aspect//声明切面 public class MyAspect { @Before("execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))") public void before(JoinPoint joinPoint){ System.out.println("前置通知:"+ joinPoint.getSignature().getName()); } //声明公共切入点 @Pointcut("execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))") private void myPointCut(){ } @AfterReturning(value = "myPointCut()",returning = "ret") public void after(JoinPoint joinPoint,Object ret){//参数一:连接点描述 //参数二:类型Object,参数名returning配置的 System.out.println("后置通知:"+ joinPoint.getSignature().getName()+" "+ret); } @Around(value = "myPointCut()") public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ //手动执行目标方法 System.out.println("前"); Object object=proceedingJoinPoint.proceed(); System.out.println("后"); return null; } @AfterThrowing(value = "execution(* pers.zhb.aspectxml.StudentServiceImpl.*(..))",throwing = "throwable") public void AfterThrowing(JoinPoint joinPoint,Throwable throwable){ System.out.println("抛出异常的通知:"+throwable.getMessage()); } @After(value = "myPointCut()") public void myafter(JoinPoint joinPoint){ System.out.println("最终通知"); } }
(4)测试:
public class TestAspectXml { public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); //获得目标类 pers.zhb.aspectxml.StudentService studentService= (StudentService) applicationContext.getBean("studentService"); studentService.addStudent(); studentService.deleteStudent(); studentService.updateStudent(); } }
前 前置通知:addStudent addStudent 后 最终通知 后置通知:addStudent null 前 前置通知:deleteStudent deleteStudent 后 最终通知 后置通知:deleteStudent null 前 前置通知:updateStudent 最终通知 抛出异常的通知:/ by zero Exception in thread "main" java.lang.ArithmeticException: / by zero