范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

javaSpring之AOP

  什么是AOP?
  AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。  为什么需要AOP?
  实际开发中我们应该都遇到过类似这样的场景:在多个模块间有某段重复的代码,我们通常是怎么处理的?
  在传统的面向过程编程中,我们也会将这段代码,抽象成一个方法,然后在需要的地方分别调用这个方法,这样当这段代码需要修改时,我们只需要改变这个方法就可以了。然而需求总是变化的,有一天,新增了一个需求,需要再多出做修改,我们需要再抽象出一个方法,然后再在需要的地方分别调用这个方法,又或者我们不需要这个方法了,我们还是得删除掉每一处调用该方法的地方。实际上涉及到多个地方具有相同的修改的问题我们都可以通过 AOP 来解决。  AOP的本质
  AOP 的本质是   由 AOP 框架修改业务组件的多个方法的源代码   ,看到这其实应该明白了,AOP 其实就是代理模式的典型应用。 按照 AOP 框架修改源代码的时机,可以将其分为两类:  静态 AOP 实现, AOP 框架在编译阶段对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ。  动态 AOP 实现, AOP 框架在运行阶段对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP。  AOP术语
  AOP 领域中的术语:  通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。  连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。  切点(PointCut): 可以插入增强处理的连接点。  切面(Aspect): 切面是通知和切点的结合。  引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。  织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。
  这些术语不同书籍翻译有区别,关键要结合程序理解之后,就明白各个术语的意思了。  第一个Spring AOP项目新建module
  名字随着各位心情来,我这里是   sping-aop  配置
  在   pom.xml   文件中增加下面两个依赖:      org.springframework     spring-context     5.3.14         org.springframework     spring-aspects     5.3.14 模拟业务
  1、新建包   service   ,提供如下接口 public interface SomeService {      void doSome();      void doSome(String name,Integer num); }
  2、在该包下,新建子包   impl   ,并提供实现类如下 public class SomeServiceImpl implements SomeService {      @Override     public void doSome() {         System.out.println("原来的业务方法,在实现类中");     }      @Override     public void doSome(String name, Integer num) {         System.out.println("原来的业务方法,在实现类中,有两个参数:" + name + "->" + num);     }  }
  3、再单独新建一个包,名字随意,我这里名为   handle   ,其下有一个名为  MyAspect   的类,代码如下: @Aspect public class MyAspect {      /**      * execution() 这个叫 切点表达式      * 

* 语法依次是:方法修饰符(可省略)、方法返回类型、方法所在包名全路径+方法名+方法参数类型列表 */ @Before(value = "execution(public void com.javafirst.service.impl.SomeServiceImpl.doSome(java.lang.String, java.lang.Integer))") public void aop_before() { System.out.println("在原有业务方法之前执行逻辑,这里自动代理功能要执行的代码."); } }   这里使用了注解 @Aspect ,这就是我们在前面添加的依赖,也就是 Spring 提供的注解。这里大家需要知道一个概念: 切点表达式   4、Spring核心配置文件 applicationConext.xml 代码如下: <?xml version="1.0" encoding="UTF-8"?>   这里会接触到一个新标签 ,代理生成器,系统自动在内存中生成代理类,无需我们手动显示写代理类。   5、和我们上一节学习一样,本节的测试代码基本不会变 /** * @Before 在目标方法之前执行 */ @Test public void testBefore() { String config = "applicationContext.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(config); SomeService someService = (SomeService) context.getBean("someService"); someService.doSome(); someService.doSome("无崖子", 87); }   6、结果展示: 在原有业务方法之前执行逻辑,这里自动代理功能要执行的代码. 原来的业务方法,在实现类中,有两个参数:无崖子->87小结   通过上面这个流程,我们简单掌握一下通过注解来实现代理功能的神奇,当然了前面提到的 切点表达式 也是有语法的,且Spring AOP中的通知注解也不止 @Before 这一种,这两点就是本文的重点。   接着往下看 Spring AOP 5 种通知注解   在学习通知注解前,我们先看下前面提到的 切点表达式 ,以上面的例子,做几个变形,各位可以测试一下结果,方便理解,这并不难。 execution(public void com.javafirst.service.impl.SomeServiceImpl.doSome(java.lang.String, java.lang.Integer)) :这表示注解功能代码在一个修饰符为 public 、返回值为 void 、在这个 com.javafirst.service.impl 路径下的 SomeServiceImpl 类中的 doSome(java.lang.String, java.lang.Integer) 方法之前执行。 execution(void com.javafirst.service.impl.SomeServiceImpl.doSome(java.lang.String, java.lang.Integer)) :方法修饰符可省略 execution(void com.javafirst.service.impl.*.doSome(java.lang.String, java.lang.Integer)) :指定包下所有类的 doSome(java.lang.String, java.lang.Integer) 方法 execution(void com.javafirst.service.impl.*.*(java.lang.String, java.lang.Integer)) :指定包下所有类中带有两个参数 (java.lang.String, java.lang.Integer) 的方法 execution(* com.javafirst.service.*.*(java.lang.String, java.lang.Integer)) :指定包下及其子包下所有方法,不区分方法返回类型(各位可以在接口中多写一个方法做测试) execution(void com.javafirst.service.*.*(..)) :指定包下及其子包下所有方法,不区分是否有参数。(这个可以测试出我们前面接口中定义的另一个方法在执行前是否也会执行代理方法中的内容)   多个匹配之间我们可以使用链接符 && 、 || 、 ! 来表示 "且"、"或"、"非"的关系。但是在使用 XML 文件配置时,这些符号有特殊的含义,所以我们使用 "and"、"or"、"not"来表示。这里就不举例了,下面看 通知注解 @Before   前置通知:通知方法在目标方法之前调用。   使用我们已经学习过了,这里再了解一下该注解的参数,方法名字可以自定义,那么系统的一个参数是 JoinPoint 要使用的话,必须是该方法的形参列表第一个,功能类似于Java反射中的 Method 类,可以获取方法名、方法参数等,用于做不同的逻辑处理。   比如我们将前面的代码做个变形,就可以验证结果: @Before(value = "execution(void com.javafirst.service.*.*(..))") public void aop_before(JoinPoint point) { System.out.println(); System.out.println("指定包下及其子包下所有方法,不区分是否有参数-在原有业务方法之前执行逻辑,这里自动代理功能要执行的代码."); System.out.println("方法名:" + point.getSignature().getName()); System.out.println("方法参数:" + point.getArgs().length + " 个参数"); if (point.getArgs().length == 2) { System.out.println("要执行 两个参数的方法"); } else { System.out.println("要执行 无参数的方法"); } }@AfterReturning   后置通知:在目标方法执行完之后再执行。从该方法的参数也可以接收到目标方法的返回结果,推荐使用 Object 类型接收。   1、在原来的接口类基础上新增一个方法: String returnPrice(double price,float discount);   我们要测试后置通知,就要在执行代理方法之前拿到目标方法的返回值,所以这里定义的是有返回值并且带参数的方法。   2、实现类中的实现逻辑(实际开发根据业务来)示例: @Override public String returnPrice(double price, float discount) { if (discount > 0.0f && price > 0.0) { return "折扣价:" + (price * discount); } return "原价:" + price; }   3、切面类中定义后置通知方法 /** * 后置通知 * * @param res 参数名必须和 returning 值保持一致,表示目标方法的返回值 */ @AfterReturning(value = "execution(java.lang.String com.javafirst.service.impl.*.return*(..))", returning = "res") public void aop_afterReturning(Object res) { System.out.println(); System.out.println("目标方法执行结果:" + res); System.out.println("在目标方法执行后 输出."); }   这里的切入点表达式和之前的一样,重点是这里的 returning 的值和方法的形参名之间的关系,这两者必须保持一致,否则拿不到目标方法的返回结果。   4、测试代码就不贴了,各位自己测试 @Around   将目标方法封装起来,简单理解:可以在目标方法之前和只有都执行相关代码逻辑。下面看示例:   1、定义接口方法 String doWork(String name);   2、接口实现类中代码: @Override public String doWork(String name) { System.out.println("正在撸码的工程师:" + name); return "员工姓名:" + name; }   注意这里的返回值执行时机。   3、切面类中定义的注解通知代码: /** * 环绕通知 *

* 方法的定义: * - 必须是public * - 必须有返回值,推荐是Object * - 参数必须有且是 ProceedingJoinPoint * * @param joinPoint * @return */ @Around(value = "execution(public java.lang.String com.javafirst.service.impl.SomeServiceImpl.doWork(java.lang.String))") public Object aop_around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println(); System.out.println("我是@Around 方法里面的输出"); // 通过参数 ProceedJoinPoint 控制目标方法是否可以被执行 Object args[] = joinPoint.getArgs(); if (null != args && args.length > 0) { // 执行目标方法 if (null != args[0]) { joinPoint.proceed(); return "您传入的参数是:" + args[0]; } } return "我是@Around 方法return的内容"; }   这里如果不通过参数 ProceedingJoinPoint 处理执行目标方法,默认目标方法是不会执行的;注意这里的输出语句和返回值执行逻辑,从而理解环绕通知。   4、测试代码 /** * @Around 在目标方法之前之后都可以执行相关代码 */ @Test public void testAround() { String config = "applicationContext.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(config); SomeService someService = (SomeService) context.getBean("someService"); String result = someService.doWork("李淳罡"); //String result = someService.doWork(null); System.out.println("测试结果输出:"+result); }   结果大家亲自体验,通过改变参数观察我们的通知代码执行逻辑,环绕通知并不等于 @Before + @AfterReturning ,环绕通知是可以修改目标方法的返回值的。 @AfterThrowing(了解)   目标方法抛出异常后执行,不抛异常则不执行(也就是说**如果目标方法自己 try-catch 了异常,则通知方法是不会执行的)。下面是示例:   1、定义接口方法 void doOrder(Integer num);   为了验证结果,我们就要通过参数来制造异常,为了方便简单,容易理解,这里就在目标方法内采用 200/num ,如果参数为0,异常就出现了。   2、实现类,也就是目标类实现代码如下: @Override public void doOrder(Integer num) { System.out.println("目标方法内输出,如果参数为0,则计算(2022/num)会抛出异常"); num = 2022 / num; }   3、切面类,定义通知方法代码: /** * 异常通知:目标方法抛出异常后调用,不抛出异常,则不调用 *

* 作用:起到监控目标方法的作用,如果有异常了,方便开发人员定位问题,修复bug * * @param ex */ @AfterThrowing(value = "execution(public void com.javafirst.service.impl.SomeServiceImpl.doOrder(java.lang.Integer))", throwing = "ex") public void aop_afterThrowing(Exception ex) { System.out.println("目标方法出现异常了,才会输出这句! 异常信息:" + ex.getMessage()); }   以上就是核心代码了,结果各位自行测试哈。 @After(了解)   最终通知:目标方法返回或异常后调用,该通知方法始终会被调用到,适合做一些收尾工作,比如:清楚缓存、删除某些数据等。   1、定义接口方法 void payMoney(String address);   同上,我们通过方法的参数来"制造异常"。   2、实现类中代码: @Override public void payMoney(String address) { System.out.println("目标方法第一句内容,输出参数:" + address); System.out.println("截取地址的前三个字:" + (address.substring(0, 3))); //try { // System.out.println("截取地址的前三个字:" + (address.substring(0, 3))); //}catch (Exception ex){ // System.out.println("目标方法有try-catch"); //} System.out.println("目标方法异常后的输出语句."); }   3、切面类中定义通知代码: /** * 最终通知:一定会被执行到,且在目标方法之后 */ @After(value = "execution(* *..SomeServiceImpl.payMoney(..))") public void aop_after() { System.out.println(" 切面类中的输出内容!"); }   结果各位自己验证哈,这个不难理解,类似于Java中的 try-catch-finally 中的 finally{} 代码块,总是会被执行到。 @Pointcut解决什么问题:我们在定义通知时,会在每个方法上面加注解,注解中有切入点表达式,而当我们定义的方法多了之后,需要改动路径或者方法名等其他时,就比较繁琐,还容易出错,那么 @Pointcut 注解就解决了这个问题。 使用方式:定义一个方法,方法体内无需内容,在该方法上面加 @Pointcut 注解,你应该都想到了,该注解也是有 value 属性的,那么表达式就写在这里,以后要改就只改这个地方;而原来加注解通知方法的地方只需把切入点表达水的值改为这里定义的方法名即可(要带括号)   我们来演示一下,就以我们本文最后学的一个注解代码为例: @After(value = "aop_pointcut()") public void aop_after() { System.out.println(" aop_after() 后置通知:切面类中的输出内容!"); } /** * 前置通知,为了测试 @Pointcut */ @Before(value = "aop_pointcut()") public void aop_before_pointcut() { System.out.println("aop_before_pointcut() 前置通知:切面类中的输出内容! "); } /** * 定义 @Pointcut 注解 */ @Pointcut(value = "execution(* *..SomeServiceImpl.payMoney(..))") private void aop_pointcut() { }   测试代码无需修改,看结果就行,这个其实没什么难度,和我们之前学习动态SQL的时候,用到的 include 标签是一样的功能。 总结   看到这里,关于 Spring 的两大核心内容我们就学习结束了,后面还会学习两大内容: Spring 集成 MyBatis 和 Spring 事务。 Spring面向切面编程是一种编程思想,其实理解起来没有想象中那么难,尤其在你有java编程基础时。 记住本文演示的 5 种通知注解,和其用法,以及代码执行流程,和那个阶段我们应该处理什么业务逻辑,这在以后会用到。


非法!外挂软件破坏钉钉系统实现远程打卡收取7000用户近60万会员费通过使用外挂定位软件,即可远程使用钉钉考勤打卡。近日,开发该软件的北京得牛科技有限公司(下称得牛科技)CEO张某杰的一审刑事判决书于北京法院公布,张某杰获有期徒刑五年六个月。判决书iPhone13创最长等待期,深圳富士康急招20万人赶工你国庆野外露营,我流水线上拧螺丝本文来源时代财经作者徐晓倩图源视觉中国这次iPhone13创下了苹果最长等待期,半个月前下单iPhone13Pro的张可盈迟迟没等到订单变动的消息。她在社交媒体上写道,发货发不出来AppleWatchSeries7今日开始接受预订,你准备好了吗?今天,2021年10月8日晚8点,AppleWatchSeries7即将在官网接受预订,并将于10月15日正式开售。之前我曾发文说过,苹果将AppleWatch7称之为最耐用的苹果iPadmini6槽点出炉,mini5跌至白菜价,买早的果粉直呼感人这次iPadmini6开售后,翻车的画面依旧,先是之前的果冻屏问题,然后是画面失真,这也引起了用户的非常不满。一些用户在他们的新iPadmini设备上遇到了所谓的屏幕变色和失真问题以下是所有支持Windows11TPM的主板目录,你的主板是否位列其中微软对Windows11的可信平台模块(TPM)2。0要求引起了很多混乱。TPM通常是主板上的专用芯片,为WindowsHello和BitLocker等功能提供硬件加密。大多数可以性能再度封顶?华为Mate50Pro或全靠iPhone13成全华为P50已经成功发布,很显然华为高端手机业务仍旧在努力布局中,接下来就要开始期待华为Mate50Pro了。原本没有意外的话,这款产品应该是和iPhone13前后脚亮相,并狙击苹果网上Python爬虫教程这么多,但是做爬虫的这么少呢?网上教程多,是因为入门简单,容易获得成就感,容易忽悠小白爬虫就是因为太有技术含量,所以会的人少,可能看起来做的人就少了爬虫远比我们想的复杂大多数人会的,只是造一颗螺丝钉,而整个爬虫美团被罚款今天国家正式对美团的罚款落地了,34亿多点,对于这样一个体量的企业来说,没什么问题,对于普通人来说很多,对于这种大企业,不值一提的。之前听说美团要被罚款10亿美金,估计,国家考虑到科技创新2025年将成为主流的五项顶尖技术一(虚拟增强)混合现实在虚拟现实中,整个现实世界被一个模拟的世界所取代,给你一个接近生活的环境体验,无论是密林的虚拟之旅政治集会还是骑车穿越崎岖的地形山脉。增强现实是指现实世界的元苹果计划在洛杉矶地区建新园区加大流媒体内容创作投资财联社(上海,编辑周玲)讯,美东时间周五(8日),苹果公司表示,将在美国洛杉矶和卡尔弗城(CulverCity)交界处建立一个新的区域总部,这表明苹果公司将继续加大投资,专注流媒体中国5G商用两周年应用规模化挑战待解本报记者谭伦北京报道9月27日,2021年中国信息通信博览会(以下简称通信展)在北京召开。这是自2019年通信展上三大运营商官宣启动5G商用后,中国5G产业迎来的两周年标志性时刻。
iphone13的演示竟然用了原神,玩家苹果的续航始终是大问题大家好,我是戒戒,专注于分享游戏心得和趣事的戒戒!号称史上最强性能的iphone13终于在凌晨举办的苹果秋季新品发布会上公布了,处理器方面iPhone13全系将搭载苹果A15仿生芯价格与逼格。15万的小鹏P5,真正打响新能源走向普通大众的第一枪新能源汽车风风火火了这么多年,市场情况一直处于极度撕裂的状态。一边是逼格满满的新势力造车,价格也高高在上,比如特斯拉蔚来理想,单价都在20万往上。当然也不缺尝新的用户,但这个价格还适合大众人群使用的电视盒子有哪些,教育电视盒子让孩子乐趣无穷电视盒子的出现,能够让我们的生活变得更丰富多彩,毕竟电视现在是我们下班之后回到家能够进行放松的一款神器,现在市面上的电视盒子非常多,适合大众人使用的电视盒子的款式也有很多,下面的这盘点9月份即将上市的机型,iPhone13热度最高,华为nova9引期待原本以为九月份可能只有苹果会举行秋季新品发布会,而国内手机厂商应该会避而远之,但没有想到,九月份竟成为各大厂商发布新机最频繁的月份,难道大家都想要狙击iPhone13?所以今天我们红米NOTE11系列最快下周预热,加持120W快充,采用新版系统眼瞅着蓝厂,绿厂已经开启了机海轰炸,红米和小米一点声音都没有。双十一将至,小米没有动作肯定就是在憋大招。此前大家都在期待红米将推出K40S系列,根据王腾的回应是红米K40S因为缺芯网络不断连,冲浪更轻松,蒲公英4G无线路由器体验随着新时代的人们对于网络的需求的不断增强,不管我们无论是走到哪里,都已经实现了网络全覆盖,上班期间有公司的网络,回到家里有家里的网络可用,这些都在一定程度上满足了我们日常用网需求。面临缺芯挑战?传iPhone13可能要减产,苹果第四季度营收或下调近几年随着全球大环境影响,不少显卡汽车都因为芯片短缺问题出现过减产甚至停产的情况,虽然智能手机遭受的影响同样不小,不过好在各家手机产商都有一定的库存和计划安排,整体表现没有太多挫折宽带网速慢?路由器是关键!潍坊移动教你使用小妙招大众报业半岛网讯近几年宽带高速发展,WiFi几乎填满了生活每个角落,不少用户发现自家宽带网速没有想象的快,甚至出现卡顿和掉线,这其中路由器起到关键作用。1路由器怎么放?路由器的原理小米手机是否拉低了手机市场的价格?是否清扫了国产山寨机?我是小米第一代的手机用户,对小米手机我是看好的,先不说性价比,小米第一代第二代的手机质量那是没得说,在手机界中绝对是良心作品。小米手机的出世具有智能手机划时代的意义,记得当时智能手关怀长者科技助老OPPO手机培训课走进社区来源人民网中过诈骗的招,蒙受很大损失。这样的活动给我们解决了一些使用手机的实际问题,还了解到了防诈骗的知识,这类活动以后希望能多多举办。要保持学习,我们不能被时代落下!10月13日希望买一个电池超过4000毫安,功耗地,续航强,具有三防功能,价格在1500以下?到目前为止,能满足你要求的手机,还没有哪个厂家能够生产出来。建议考虑二手旗舰手机或者高档老年机。考虑老人机多赚点钱就什么都防,不单止手机三防,还防老。手机进水就换,或者买一个手机防