相信大家通过上一篇的Spring AOP 编程入门对AOP 的术语已经有了一定的认知,概念看起来总是有点懵,所以需要慢慢在应用中理解,今天主要是通过一些小例子加深一下aop在实际应用中到底能干嘛。 AOP 框架有很多种, Spring 中的 AOP 是通过动态代理实现的。不同的 AOP 框架支持的连接点也有所区别,例如,AspectJ 和 JBoss,除了支持方法切点,它们还支持字段和构造器的连接点。而 Spring AOP 不能拦截对对象字段的修改,也不支持构造器连接点,我们无法在 Bean 创建时应用通知。 上一篇博客我们也新建了一个小demo,主要是为了弄清楚advice(通知)执行的顺序。 首先先创建一个接口TakeawayService.java: 在创建两个类实现TakeawayService.java; 测试方法TakeController.java: 运行结果: 然后隔了一段时间,产品经理觉得我们可不可以在用户点餐之前整点提示性语言比如,阿里阿塞哟、刷我滴卡、亚麻带类似的,当然其它的暂时也没想到了。那么这个我们怎么办?要么是新定义一个方法,要么就在原来的点餐方法里重写各自的方法,照这样的进度下去东京热不热我不清楚,反正上海今天是真的热。如果用aop 来解决的话就没上面这种难以维护了,让我们先加一个亚麻带。 然后在运行看下结果: 这样就可以完全没有去更改之前的代码,通过aop实现了这个“阿里阿塞哟”。 然后又隔了几天,这个产品经理啊又开始搞事了,说什么今天天气不错,或者今年是张san的本命年,更有甚者是说zs最近心情不好,所以咱们要临时取消zs的‘阿里阿塞哟’,只通知wmz,这个时候不要慌,Spring AOP 所支持的 AspectJ 切点指示器完全能实现这个变态要求。 网上找了一张图,大家伙讲究看下,更详细的说明可以自己再找找博文资料之类。 修改OrderAop.java: 此时,切面只会对 ZSServiceImpl. 切面就是这么社会,所以我以后再也不怕产品经理让我改亚麻带了。 上一篇博客已经有描述过具体是那五种通知,以及各自的执行顺序这里就不再加以描述了,就只贴一张网图当做复习了。 图看着像是有重影,但是碍于本人比较懒,所以就懒得找别的图了。 再次修改切面类OrderAop.java: 修改ZSServiceImpl.java: 修改 WMZServiceImpl.java: 运行结果如下: @Around的作用 既可以在目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作; 切面类OrderAop.java新增以下方法: 运行结果: 结果显而易见,值得注意的是 所以,如果不调用该对象的 proceed() 方法,表示原目标方法被阻塞调用。 上面的例子,我们要进行增强处理的目标方法没有参数,在有参数的情况,并且在增强处理中使用该参数。 代码修改如下: TakeController.java 运行结果: 我们 可以看到,结果和预想的一致。因时间关系本人临时有事处理,决定吧原本今天 的XML 配置文件声明切面,放在明天另写一篇。 spring aop 的简单运用今天就到这儿了,下次再见铁汁们! 一、初步认识 Spring AOP
1. Spring AOP 的特点
2. Spring AOP 的简单例子
package com.example.demo.service; import com.sun.org.apache.xpath.internal.objects.XString; public interface TakeawayService { /** * 点餐接口 * @return */ public String Order(); }
ZSServiceImpl.java:
package com.example.demo.service.impl; import org.springframework.stereotype.Service; import com.example.demo.service.TakeawayService; @Service public class ZSServiceImpl implements TakeawayService { @Override public String Order() { return "张三点了一份爆浆牛丸"; } }
WMZServiceImpl.java:
package com.example.demo.service.impl; import com.example.demo.service.TakeawayService; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class WMZServiceImpl implements TakeawayService { @Override public String Order() { return "王麻子点了一份瓜皮香锅"; } }
package com.example.demo.controller; import com.example.demo.entity.Response; import com.example.demo.entity.ResponseResult; import jdk.internal.org.objectweb.asm.tree.analysis.Value; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.demo.service.TakeawayService; @RestController @RequestMapping("/api") public class TakeController { /** *此处@Autowired 也可替换为 @Resource(name="") name:中填写你想注入的bean对象名称 * 如:@Resource("WMZServiceImpl") * private TakeawayService wmzService; */ @Qualifier("WMZServiceImpl")//指定注入的bean对象名称 @Autowired private TakeawayService wmzService; @Qualifier("ZSServiceImpl") @Autowired private TakeawayService zsService; @RequestMapping("/order") public ResponseResult Orde() { String wmz= wmzService.Order(); String zs=zsService.Order(); System.out.println(wmz); System.out.println(zs); return Response.makeOKRsp(wmz+";"+zs); } }
2.1.引用依赖:
<!--引入AOP依赖--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency>
2.2.新建切面类
按照上一篇通知执行的顺序可知在此场景我们需要用到@Before,新建切面类OrderAop.java:
package com.example.demo.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect // 表示它是一个切面。 @Component //表明它将作为一个Spring Bean 被装配 public class OrderAop { /** * @description 在连接点执行之前执行的通知 */ @Before("execution(public * com.example.demo.service.TakeawayService.*(..)))") public void doBefore(){ System.out.println("阿里阿塞哟!"); } }
2.3. Spring AOP 所支持的 AspectJ 切点指示器
package com.example.demo.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect // 表示它是一个切面。 @Component //表明它将作为一个Spring Bean 被装配 public class OrderAop { /** * @description 在连接点执行之前执行的通知 * 全匹配 * execution(public * com.example.demo.service.TakeawayService.*(..))) * 只匹配zs within 限定该切点仅匹配的包 bean 在切点中选择 * execution(public * com.example.demo.service.TakeawayService.Order(..)) && within(com.example.demo.service.impl.*) && bean(ZSServiceImpl) */ @Before("execution(public * com.example.demo.service.TakeawayService.Order(..)) && within(com.example.demo.service.impl.*) && bean(ZSServiceImpl)") public void doBefore(){ System.out.println("阿里阿塞哟!"); } }
java
这个类生效,执行结果:3. Spring AOP 中5 种通知类型
3.1. 通知执行顺序
package com.example.demo.aop; import org.aspectj.lang.annotation.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * 饿鸟嘛配送 **/ @Aspect @Component public class EatAop { /** *@description 定义切入点,切入点为com.example.demo.controller.AopController中的所有函数 *@description 通过@Pointcut注解声明频繁使用的切点表达式 * */ @Pointcut("execution(public * com.example.demo.controller.AopController.*(..)))") public void EatAop() { } /** * @description 在连接点执行之前执行的通知 */ @Before("EatAop()") public void doBeforeEat(){ System.out.println("饿鸟嘛配送员登录接单系统为接单做准备!"); } /** * @description 在连接点执行之后执行的通知(返回通知和异常通知的异常) */ @After("EatAop()") public void doAfterEat(){ System.out.println("饿鸟嘛配送员为今天的外卖单量感到异常吃惊!"); } /** * @description 在连接点执行之后执行的通知(返回通知) */ @AfterReturning("EatAop()") public void doAfterReturningEat(){ System.out.println("返回的通知:饿鸟嘛配送员接单完毕,并会心一笑百媚生!"); } /** * @description 在连接点执行之后执行的通知(异常通知) */ @AfterThrowing("EatAop()") public void doAfterThrowingGame(){ System.out.println("异常通知:服务错误,请联系饿鸟嘛系统管理员!"); } }
package com.example.demo.service.impl; import org.springframework.stereotype.Service; import com.example.demo.service.TakeawayService; @Service public class ZSServiceImpl implements TakeawayService { @Override public String Order() { System.out.println("zs爆浆牛丸"); return "张三点了一份爆浆牛丸"; } }
package com.example.demo.service.impl; import com.example.demo.service.TakeawayService; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class WMZServiceImpl implements TakeawayService { @Override public String Order() { System.out.println("wmz瓜皮香锅"); return "王麻子点了一份瓜皮香锅"; } }
3.2. SpringAOP增强处理 @around
可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;
可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值; 当需要改变目标方法的返回值时,只能使用Around方法;
/** * @description 定义增强 * @param pj */ @Around("point()") public void doAround(ProceedingJoinPoint pj) { try { System.out.println("Around 调用方法前 "); pj.proceed(); System.out.println("Around 调用方法后"); } catch (Throwable throwable) { throwable.printStackTrace(); } }
@Around
修饰的环绕通知类型,是将整个目标方法封装起来了,在使用时,我们需要调用 ProceedingJoinPoint
的 proceed()
方法。 如果没有调用 该方法,执行结果为 :3.3 通过注解处理通知中的参数
下面我们给接口增加一个参数,表示购买所花的金钱。通过AOP 增强处理,如果sz下单超过了了 4396元,就可以赠送一份鲜果饮汇源牌饮料。
TakeawayService.java
package com.example.demo.service; import com.sun.org.apache.xpath.internal.objects.XString; public interface TakeawayService { /** * 点餐接口 * @return */ public String Order(double price); }
ZSServiceImpl.java
package com.example.demo.service.impl; import org.springframework.stereotype.Service; import com.example.demo.service.TakeawayService; @Service public class ZSServiceImpl implements TakeawayService { @Override public String Order(double price) { System.out.println("zs爆浆牛丸:"+price); return "张三点了一份爆浆牛丸"; } }
WMZServiceImpl.java
package com.example.demo.service.impl; import com.example.demo.service.TakeawayService; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class WMZServiceImpl implements TakeawayService { @Override public String Order(double price) { System.out.println("wmz瓜皮香锅:"+price); return "王麻子点了一份瓜皮香锅"; } }
package com.example.demo.controller; import com.example.demo.entity.Response; import com.example.demo.entity.ResponseResult; import jdk.internal.org.objectweb.asm.tree.analysis.Value; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.demo.service.TakeawayService; @RestController @RequestMapping("/api") public class TakeController { /** *此处@Autowired 也可替换为 @Resource(name="") name:中填写你想注入的bean对象名称 * 如:@Resource("WMZServiceImpl") * private TakeawayService wmzService; */ @Qualifier("WMZServiceImpl")//指定注入的bean对象名称 @Autowired private TakeawayService wmzService; @Qualifier("ZSServiceImpl") @Autowired private TakeawayService zsService; @RequestMapping("/order") public ResponseResult Orde() { String wmz= wmzService.Order(12); System.out.println(wmz); String zs=zsService.Order(4396); System.out.println(zs); return Response.makeOKRsp(wmz+";"+zs); } }
OrderAop.java
package com.example.demo.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Aspect // 表示它是一个切面。 @Component //表明它将作为一个Spring Bean 被装配 public class OrderAop { /** *@description 定义切入点,切入点为execution(public * com.example.demo.service.TakeawayService.*(..)))中的所有函数 *@description 通过@Pointcut注解声明频繁使用的切点表达式 * */ @Pointcut("execution(public * com.example.demo.service.TakeawayService.Order(double)) && args(price) && bean(ZSServiceImpl)") public void point(double price) { } /** * @description 在连接点执行之前执行的通知 * 全匹配 * execution(public * com.example.demo.service.TakeawayService.*(..))) * 只匹配zs within 限定该切点仅匹配的包 bean 在切点中选择 * execution(public * com.example.demo.service.TakeawayService.Order(..)) && within(com.example.demo.service.impl.*) && bean(ZSServiceImpl) */ /* @Before("point()") public void doBefore(){ System.out.println("阿里阿塞哟!"); } */ /** * @description 在连接点执行之后执行的通知(返回通知和异常通知的异常) */ /* @After("point()") public void doAfter(){ System.out.println("after!"); } */ /** * @description 在连接点执行之后执行的通知(返回通知) */ // @AfterReturning("point()") // public void doAfterReturning(){ // System.out.println("返回通知:AfterReturning"); // } /** * @description 在连接点执行之后执行的通知(异常通知) */ //@AfterThrowing("point()") //public void doAfterThrowing(){ // System.out.println("异常通知:AfterThrowing"); // } /** * @description 定义增强 * @param pj */ @Around("point(price)") public String doAround(ProceedingJoinPoint pj,double price) { try { System.out.println("Around 调用方法前 "); pj.proceed(); if(price>=4396) { System.out.println("zs下单超过了4399,赠送一份鲜果饮汇源牌饮料"); return "爆浆牛丸和饮料"; } System.out.println("Around 调用方法后"); } catch (Throwable throwable) { throwable.printStackTrace(); } return "爆浆牛丸"; } }
小结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算