Spring基于AspectJ的AOP开发案例解析(spring aop与aspectj)

网友投稿 338 2022-07-30


目录AspectJ简介注解开发环境准备不同的通知类型最通知中通过value属性定义切点入门案列@Before前置通知@AfterReturning后置通知@Around环绕通知@AfterThrowing 异常抛出通知@After 最终通知通过@Pointcut为切点命名AspectJ的XML方式的AOP开发

使用AspectJ实现AOP注解方式XML方式

AspectJ简介

AspectJ是一个基于java语言的AOP框架Spring2.0以后新增了对AspectJ切点表达式支持@AspectJ是AspectJ1.5新增的功能,通过JDK5注解技术,允许直接在Bean类中定义切面新版本Spring框架,建议使用AspectJ方式来开发AOP使用AspectJ需要导入Spring AOP和AspectJ相关jar包

Spring-aopspringsource.org.aopalliancespring-aspectsspringsource.org.aspectj.weaver

注解开发

环境准备

应入相关的jar包junit,javax.annotation-api,spring-core,spring-beans,spring-context,spring-expression,aopalliance,spring-aop(Spring基础包)aspectjweaver,spring-aspects(AspectJ使用的)spring-test(测试使用)XML引入相应配置

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:aop="http://springframework.org/schema/aop" xsi:schemaLocation="

http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop.xsd">

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:aop="http://springframework.org/schema/aop" xsi:schemaLocation="

http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop.xsd">

不同的通知类型

@Before前置通知,相当于BeforeAdvice@AfterReturning后置通知,相当于AfterReturningAdvice@Around环绕通知,相当于MethodInterceptor(可以阻止方法的进行,功能最强。列:事务管理)@AfterThrowing异常抛出通知,相当于ThrowAdvice@After最终final通知,不管是否异常,该通知都会执行@DeclarwParents引介通知,相当于IntroductionInterceptor(不要求掌握)

最通知中通过value属性定义切点

通过execution函数,可以定义切点的方法切入语法: --execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)(访问修饰符可以省略)列如

--匹配所有类public方法 execution(publice * * (..))---第一个*:任意返回值 第二个*:任意名称 (..):任意参数 相当于所有以public开头的方法加了一个前置通知的话都会执行 --匹配指定包下所有类方法 execution(* top.odliken.demo.(..)) 不包含子包 .:包 --execution(* top.odliken.demo..(..)) ..便是包、子酸包下所有类 --匹配指定类所有方法 execution( top.odlien.demo.UserService.(..)) 第一个*:任意返回值 UserService.:UserService类下面的所有方法 --匹配实现特定接口所有方法 execution( top.odliken.demo.GenericDao+.(..)) +:子类 .:方法名 --匹配所有save开头的方法 execution(* save*(..))

入门案列

============XML==========

===========ProductDao===========

public class ProductDao {

public void save() {

System.out.println("保存商品.....");

}

public void findOne() {

System.out.println("查找一个商品.....");

}

public void findAll() {

System.out.println("查找所有商品.....");

}

public void update() {

System.out.println("修改商品.....");

}

public void delete() {

System.out.println("删除商品.....");

}

}

===========MyAspectAnno===========

@Aspect

public class MyAspectAnno {

@Before(value = "execution(* top.odliken.aspectJ.demo1.ProductDao.save(..))")

public void before(){

System.out.println("=========前置通知=========");

}

}

===========Springdemo1===========

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:afterglow.xml")

public class Springdemo1 {

@Resource(name = "productDao")

private ProductDao productDao;

@Test

public void demo1(){

productDao.save();

productDao.findOne();

productDao.findAll();

productDao.update();

productDao.delete();

}

}

@Before前置通知

可以在方法中传入JoinPoint对象,用来获取切点信息

public void before(JoinPoint joinPoint){

System.out.println("=========前置通知========="+joinPoint);

}

@AfterReturning后置通知

通过returning属性可以定义返回值,作为参数

@AfterReturning(value = "execution(* top.odliken.aspectJ.demo1.ProductDao.update(..))",returning = "result")

public void afterReturing(Object result){

System.out.println("==========后置通知=========="+result);

}

@Around环绕通知

Around方法的返回值就是目标代理方法执行返回值参数ProceedingJoinPoint 可以调用拦截目标方法执行如果不调用 ProceedingJoinPoint的 proceed方法,那么目标方法就背拦截了

@Around(value = "execution(* top.odliken.aspectJ.demo1.ProductDao.delete(..)))")

public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

System.out.println("环绕通知======前");

Object obj = joinPoint.proceed();//执行目标方法 不调用就不执行

System.out.println("环绕通知======后");

return obj;

}

@AfterThrowing 异常抛出通知

通过设置throwing属性,可以设置发生异常对象参数

@AfterThrowing(value = "execution(* top.odliken.aspectJ.demo1.ProductDao.findOne(..)))",throwing = "e")

public void afterThrowing(Throwable e){

System.out.println("==========异常通知=========="+e.getMessage());

}

@After 最终通知

无论是否出现异常,最终通知总是会被执行的。就像Java异常中的 finall块一样

@After(value = "execution(* top.odliken.aspectJ.demo1.ProductDao.findAll(..))")

public void after(){

System.out.println("==========最终通知==========");

}

通过@Pointcut为切点命名

在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点,可以使用@Pointcut进行定义切点方法:private void 无参方法,方法名为切点名当通知多个切点是,可以使用||连接

@Before(value = "myPointcut1()")

public void before(JoinPoint joinPoint){

System.out.println("=========前置通知========="+joinPoint);

}

@Pointcut(value = "execution(* top.odliken.aspectJ.demo1.ProductDao.save(..))")

private void myPointcut1(){}

AspectJ的XML方式的AOP开发

==========CustomerDao==========

public interface CustomerDao {

public void save();

public String update();

public void delete();

public void findOne();

public void findAll();

}

==========CustomerDaoImpl==========

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;

}

}

==========MyAspectXml==========

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方式的最终通知=================");

}

}

==========SpringDemo2==========

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(value="classpath:applicationContext2.xml")

public class SpringDemo2 {

@Resource(name="customerDao")

private CustomerDao customerDao;

@Test

public void demo1(){

customerDao.save();

customerDao.update();

customerDao.delete();

customerDao.findOne();

customerDao.findAll();

}

}

==========XML==========

&lghVZRpt;aop:pointcut id="pointcut5" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.findAll(..))"/>

&lghVZRpt;aop:pointcut id="pointcut5" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.findAll(..))"/>


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java实现简单的五子棋游戏示例代码(java小游戏编程源代码五子棋)
下一篇:Java全面深入探究SpringBoot拦截器与文件上传
相关文章

 发表评论

暂时没有评论,来抢沙发吧~