AI智能
改变未来

基于AspectJ的SpringAOP开发

AspectJ是一个基于Java语言的aop框架
spring2.0以后新增对AspectJ切点表达式的支持
@AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在bean类中定义切面
使用AspectJ需要导入SpringAOP和AspectJ的相关jar包
spring-aop-4.2.4.RELEASE.jar
com.apringsource.org.aopalliance-1.0.0.jar
spring-aspects-4.2.4.RELEASE.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

在maven工程的pom文件中配置依赖

<dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>4.2.4.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>4.2.4.RELEASE</version></dependency>

一、AspectJ注解开发

1、AspectJ支持的增强类型

Before 前置增强/通知,相当于BeforeAdvice
AfterReturning 后置增强/通知,相当于AfterReturningAdvice
Around 环绕增强/通知,相当于MethodInterceptor
AfterThrowing抛出增强/通知,相当于ThrowAdvice
After 最终finally增强/通知,不管是否异常,该通知都会执行

2、定义切入点

通过execution函数语法定义切入点
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
例如
execution(public * *(…))匹配所有类public方法
execution( * com.zqh.dao. * (…))匹配指定包下所有类方法,不包含子包
execution( * com.zqh.dao. . * (…)) 匹配指定包和子包下所有类方法
execution( * com.zqh.dao.UserDao . * (…)) 匹配指定类下所有方法
execution( * com.zqh.dao.UserDao+ . * (…))匹配实现特定接口所有类方法
execution( * insert * (. .)) 匹配所有insert开头的方法

3、案例

目标类

public class ProductDao {public void save(){System.out.println(\"保存商品...\");}public String update(){System.out.println(\"修改商品...\");return \"hello\";}public void delete(){System.out.println(\"删除商品...\");}public void findOne(){System.out.println(\"查询一个商品...\");//int i = 1/0;}public void findAll(){System.out.println(\"查询所有商品...\");//        int j = 1/0;}}

使用@Aspect注解定义此类为切面类

/*** 切面类* 通过通知注解定义切面方法*/@Aspectpublic class MyAspectAnno {//通过通知的value属性定义切点@Before(value=\"myPointcut1()\")//@Before 前置增强/通知,可以在方法中传入JoinPoint对象,用来获取切点信息public void before(JoinPoint joinPoint){System.out.println(\"前置通知==================\"+joinPoint);}//通过通知的value属性定义切点@AfterReturning(value=\"myPointcut2()\",returning = \"result\")//@AfterReturning 后置增强/通知,通过returning属性定义方法返回值,作为参数public void afterReturing(Object result){System.out.println(\"后置通知==================\"+result);}//通过通知的value属性定义切点@Around(value=\"myPointcut3()\")//Around 环绕增强/通知,方法的返回值就是目标代理方法执行返回值,参数ProceedingJoinPoint可以拦截目标方法执行,public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println(\"环绕前通知================\");//如果不调用ProceedingJoinPoint的proceed方法,目标方法会被拦截而不执行Object obj = joinPoint.proceed(); // 执行目标方法System.out.println(\"环绕后通知================\");return obj;}//通过通知的value属性定义切点@AfterThrowing(value=\"myPointcut4()\",throwing = \"e\")//AfterThrowing抛出增强/通知,设置throwing属性,可以设置发生异常对象的参数public void afterThrowing(Throwable e){System.out.println(\"异常抛出通知==============\"+e.getMessage());}//通过通知的value属性定义切点@After(value=\"myPointcut5()\")//After 最终finally增强/通知,不管是否异常,该通知都会执行public void after(){System.out.println(\"最终通知==================\");}/*在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点可以使用@Pointcut进行定义切点方法 private void 无参方法,方法名作为切点名当通知有多个切点时。可以使用||连接*/@Pointcut(value=\"execution(* com.zqh.ProductDao.save(..))\")private void myPointcut1(){}@Pointcut(value=\"execution(* com.zqh.ProductDao.update(..))\")private void myPointcut2(){}@Pointcut(value=\"execution(* com.zqh.ProductDao.delete(..))\")private void myPointcut3(){}@Pointcut(value=\"execution(* com.zqh.ProductDao.findOne(..))\")private void myPointcut4(){}@Pointcut(value=\"execution(* com.zqh.ProductDao.findAll(..))\")private void myPointcut5(){}}

xml配置

<?xml version=\"1.0\" encoding=\"UTF-8\"?><beans xmlns=\"ASP/\"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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd\"><!--开启AspectJ的注解开发,自动代理=====================--><aop:aspectj-autoproxy/><!--目标类===================--><bean id=\"productDao\" class=\"com.zqh.ProductDao\"/><!--定义切面--><bean class=\"com.zqh.MyAspectAnno\"/></beans>

二、AspectJXML开发

目标类

public class CustomerDaoImpl implements CustomerDao {public void save() {System.out.println(\"保存客户...\");}public String update() {System.out.println(\"修改客户...\");return \"spring\";}public void delete() {System.out.println(\"删除客户...\");}public void findOne() {System.out.println(\"查询一个客户...\");//       int a = 1/ 0;}public void findAll() {System.out.println(\"查询多个客户...\");//        int b = 1/0;}}

切面类

public class MyAspectXml {// 前置通知public void before(JoinPoint joinPoint){System.out.println(\"XML方式的前置通知==============\"+joinPoint);}// 后置通知public void afterReturing(Object result){System.out.println(\"XML方式的后置通知==============\"+result);}// 环绕通知public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println(\"XML方式的环绕前通知==============\");Object obj = joinPoint.proceed();System.out.println(\"XML方式的环绕后通知==============\");return obj;}// 异常抛出通知public void afterThrowing(Throwable e){System.out.println(\"XML方式的异常抛出通知=============\"+e.getMessage());}// 最终通知public void after(){System.out.println(\"XML方式的最终通知=================\");}}

xml配置

<?xml version=\"1.0\" encoding=\"UTF-8\"?><beans xmlns=\"ASP/\"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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd\"><!--XML的配置方式完成AOP的开发===============--><!--配置目标类=================--><bean id=\"customerDao\" class=\"com.zqh.CustomerDaoImpl\"/><!--配置切面类--><bean id=\"myAspectXml\" class=\"com.zqh.MyAspectXml\"/><!--aop的相关配置=================--><aop:config><!--配置切入点--><aop:pointcut id=\"pointcut1\" expression=\"execution(* com.zqh.CustomerDao.save(..))\"/><aop:pointcut id=\"pointcut2\" expression=\"execution(* com.zqh.CustomerDao.update(..))\"/><aop:pointcut id=\"pointcut3\" expression=\"execution(* com.zqh.CustomerDao.delete(..))\"/><aop:pointcut id=\"pointcut4\" expression=\"execution(* com.zqh.CustomerDao.findOne(..))\"/><aop:pointcut id=\"pointcut5\" expression=\"execution(* com.zqh.CustomerDao.findAll(..))\"/><!--配置AOP的切面 method属性为切面类中对应的增强方法 pointcut-ref为上面定义的切入点--><aop:aspect ref=\"myAspectXml\"><!--配置前置通知--><aop:before method=\"before\" pointcut-ref=\"pointcut1\"/><!--配置后置通知--><aop:after-returning method=\"afterReturing\" pointcut-ref=\"pointcut2\" returning=\"result\"/><!--配置环绕通知--><aop:around method=\"around\" pointcut-ref=\"pointcut3\"/><!--配置异常抛出通知--><aop:after-throwing method=\"afterThrowing\" pointcut-ref=\"pointcut4\" throwing=\"e\"/><!--配置最终通知--><aop:after method=\"after\" pointcut-ref=\"pointcut5\"/></aop:aspect></aop:config></beans>
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 基于AspectJ的SpringAOP开发