咨询热线:15320666453 联系人:许华仟 地址:大陆沿海地区
Spring系列(四) 面向切面的Spring
来源:12bet主页 发布时间:2019-11-17 点击量:265
除了IOC外, AOP是Spring的另一个核心. Spring利用AOP解决应用横切关注点(cross-cutting concern)与业务逻辑的分离, 目的是解耦合. 横切关注点是指散布于代码多处的同一种功能, 比如日志, 事务, 安全, 缓存等.
AOP编程的基本概念
在OOP中, 如果要复用同一功能, 一般的做法是使用继承或委托. 继承容易导致脆弱的对象体系, 而委托实现起来比较麻烦, 需要对委托对象进行复杂调用. AOP提供了另外一种思路, 使用AOP我们仍然可以在一个地方定义功能, 并通过声明的方式告知何处以哪种方式使用这个功能. 这样我们既可以对功能做统一管理和维护, 同时也简化了业务逻辑模块, 使其更关注自身的业务逻辑. 此外, AOP还可以将新的功能行为添加到现有对象.
Spring中AOP的术语
切面(Aspect): 切面定义了横切关注点的功能以及使用该功能的声明. 它包含了另外两个术语, 通知(Advice, 功能逻辑代码)和切点(Pointcut,声明). 切面定义了它是什么(what), 以及在何时何处(when,where)完成其功能.通知(Advice): 通知定义了切面的具体功能, 以及何时使用.when,何时使用? 前置(Before), 后置(After), 返回(After-returning), 异常(After-throwing), 环绕(Around)
切点(Pointcut): 定义了切面定义的功能在哪里(Where)发生作用, 看起来就像从某个点把切面插入进去一样. 切点应该属于连接点中的一个或多个.连接点(Join point): 定义了程序执行过程中可以应用切面的具体时机, 比如方法调用前, 调用后, 结果返回时, 异常抛出时等, 通常某个具体切面只会选择其中一个或几个连接点作为切点.引入(Introduction): 为现有的类添加新的方法或属性叫引入.织入(Weaving): 织入是把切面应用到目标对象并创建新代理对象的过程.织入的方式有三种:
- 编译期: 需要特殊的编译器支持, 如AspectJ的织入编译器类加载期: 需要特殊的类加载器ClassLoader运行时: Spring AOP 使用该方式织入. AOP容器为对象动态创建一个代理对象.
Spring 对 AOP的支持
Spring对AOP的支持很多借鉴了AspectJ的方式.
Spring支持四种方式的织入:
- 基于代理的经典AOP; (方式太老旧, 不建议使用)纯POJO切面;(需要XML配置)@AspectJ 注解驱动的切面; (没啥说的,很好用)注入式AspectJ切面;
通过切点来选择连接点
Spring 借鉴了AspectJ的切点表达式语言. 如前所述, Spring基于动态代理,只能在方法上拦截, 所以Spring只支持这个层面的表达式来定义.
spring支持的AspectJ指示器如下, 其中execution来执行匹配, 其他均为限制匹配的.
切点表达式更多使用可以参考官方文档
spring新增了个bean()指示器使用注解创建切面
一. 定义切面类, 并用 @Aspect
注解, 该注释用来标记这个类是个切面
二. 定义切面的方法(what), 并使用注解标记方法(when), 可用的注解: @Before
,@After
,@AfterReturning
,@AfterThrowing
,@Around
(功能最强大,后面将单独使用这种通知)
一,二步完成后的代码:
@Aspectpublic class Audience{ @Before("execution(** com.xlx.Performance.perform(...))") public void silencephone(){ System.out.println("silencephone"); } @Before("execution(** com.xlx.Performance.perform(...))") public void takeSeats(){ System.out.println("takeSeats"); } @AfterReturning("execution(** com.xlx.Performance.perform(...))") public void applause(){ System.out.println("applause"); } @AfterThrowing("execution(** com.xlx.Performance.perform(...))") public void refund(){ System.out.println("refund"); }}
上面的代码中切面表达式被重复定义了四次, 无论如何这已经是重复代码了, 下一步优化一下.
三. 使用注解@Pointcut
定义切点
@Aspectpublic class Audience{ //定义切点并修改其他方法重用该切点 @Pointcut("execution(** com.xlx.Performance.perform(...))") public void performance(){ } @Before("performance()") public void silencephone(){ System.out.println("silencephone"); } @Before("performance()") public void takeSeats(){ System.out.println("takeSeats"); } @AfterReturning("performance()") public void applause(){ System.out.println("applause"); } @AfterThrowing("performance()") public void refund(){ System.out.println("refund"); }}
@Aspect
注解的类依然是个普通java类, 它可以被装配为bean
@Beanpublic Audience getAudience(){ return new Audience();}
四. 使用@EnableAspectJAutoProxy
注解启用自动代理功能, 如果是XML Config ,对应的节点是<aop:aspectj-autoproxy />
@Configuration@ComponentScan // 包扫描@EnableAspenctJAutoProxy // 启动自动代理public class MyConfig{ // 如果Audience上加了@Component就不需要这个代码了 @Bean public Audience getAudience(){ return new Audience(); }}
五. 使用环绕通知@Around
, 环绕通知同时兼具了@Before
,@After
... 等注解的方法的功能, 下面代码演示了这种能力. 如可以使用它记录方法执行时长.
@Aspectpublic class Audience{ //定义切点并修改其他方法重用该切点 @Pointcut("execution(** com.xlx.Performance.perform(...))") public void performance(){ } @Around("performance()") public void silencephone(ProcdedingJoinPoint jp){ System.out.println("silencephone"); System.out.println("takeSeats"); try{ // 如果不是刻意为之, 一定要记得调用jp.proceed();否则实际的方法Performance.perform()将会阻塞 jp.proceed(); System.out.println("applause"); }catch(Exception e){ System.out.println("refund"); } }}
六. 参数传递 , 在切点表达式中使用args(paramName)
结合切点方法可以为切面方法传递参数
@Aspectpublic class Audience{ //定义切点并修改其他方法重用该切点 @Pointcut("execution(** com.xlx.Performance.perform(int) && args(actornum)))") public void performance(int actornum){ } @Before("performance(actornum)") public void countActor(int actornum){ System.out.println("countActor"+actornum); }}
通过注解引用新功能
除了拦截对象已有的方法调用, 还可以使用AOP来为对象添加新的属性和行为(引入). 其实现就是通过动态代理生成代理类来实现.
一. 定义要添加的功能接口
public interface Encoreable{}
二. 定义切面(引入) @Aspect
注解切面类. @DeclareParents
注解功能接口静态变量
@Aspectpublic class EncoreableIntroducer{ // 可以解释为: 为Performace的所有子类引入接口Encoreable, 并使用默认实现类DefaultEncoreableImpl @DeclareParents(value="xlx.Performace+",defaultImpl=DefaultEncoreableImpl.class) public static Encoreable encoreable;}
基于XML配置的切面
如果没有办法为类添加注解, 比如没有源代码, 那就不得不使用xml来配置了.
示例1<aop:config> <aop:aspect ref="aspectBean"> <aop:pointcut id="pcId" expression="execution(** com.xlx.Performance.perform(int) and args(actornum)))" /> <aop:before pointcut-ref="pcId" method="count" /> </aop:aspect></aop:config>
示例2
<aop:config> <aop:aspect> <aop:declare-parents type-matching="xlx.Performace+" implement-interface="xlx.Encoreable" delegate-ref="defaultImpl" /> </aop:aspect></aop:config>
AspectJ 注入
使用AspectJ注入的方式可以解决使用动态代理无法解决的问题(应该比较少见,大多应用使用Spring AOP就可以实现了), 但需要使用AspectJ的特殊语法. 定义好的类需要用xml配置为bean, 使用factory-method="aspectOf"
属性来制定bean的产生方式.
<bean factory-method="aspectOf" > <property name="other" ref="otherref"/></bean>
相关产品
-
会议强调,2018年将结合外汇领域违法犯罪活动新特点,加强形势分析和情报共享,提高合力打击成效;紧盯市场动向,在支持金融创新的同时,严打以创新为名的各类外汇违法犯罪行为,及时捕捉和处置风险苗头;循线追踪非法资金交易的上下游犯罪,深挖细查犯罪网络,形成深度打击态势;刑事追责和行政处罚“两手抓”,使地下钱庄经营者和参与地下钱庄交易的“客户”受到应有的惩处,形成震慑,根除地下钱庄等外汇违法犯罪活动滋生土壤,维护国家经济与金融安全。
-
此次新增CVT车型在外观方面与现款车型差异不大,配备双前/后雾灯、车顶行李架、运动越野大包围,内饰部分的变化主要体现在挡杆部分,座椅为皮质包覆,采用2+3+2的七座布局,其中第二排座椅可4/6分割折叠翻转、第三排座椅可折叠,并且全车座椅带有头枕(上下可调)。
-
日本的原油的85%来自于中东地区,伊朗在过去是日本的第二大石油进口国。安倍还在计划以经济援助的方式,帮助伊朗加强基础设施建设。
-
类似的情景正发生在棋盘外的许多地方,人与机器之间的竞争与合作,恐怕是21世纪最醒目和持久的课题。正如机器拟人领域中的“恐怖谷理论”一样,当人们忽然发现AI的棋力高不可攀,棋手这个职业的意义和必然性就会产生波动;而从心理学的角度看,一旦人的“意义感”受到冲击,就注定会产生大范围的群体焦虑。当棋手们忽然发现自己多年的悬梁刺股竟然还比不上一个小小的AI程序,巨大的心理落差势必会造成许多不理智的过激反应和行为。
-
按照宪法和有关法律的规定,十二届全国人大到2018年3月任期届满,十三届全国人大代表于2018年1月选出。十二届全国人大五次会议通过了关于十三届全国人大代表名额和选举问题的决定。据此,全国人大常委会委员长会议拟订了十三届全国人大代表名额分配方案草案、十三届全国人大少数民族代表名额分配方案草案、台湾省出席十三届全国人大代表协商选举方案草案,建议十二届全国人大常委会第二十七次会议予以审议。
-
埃及当地时间19日凌晨,一架由巴黎飞往开罗的埃航MS804航班在地中海海域“从雷达上消失”,该航班由空客A320执飞,机身编号SU-GCC,机龄13年,机上共有66人,其中56名乘客,10名机组人员。飞机失联后,埃及与希腊方面调查团队随后前往客机失联海域进行搜救。
-
她说,已经有一批华文作家的作品在海外出版,欧美文坛对于华文文学的需求已经越来越大。以前可能一年只翻译中文作品八九本,如今这个数字已经不知翻了多少倍。
-
亚洲国家开展这项运动时间较晚,中国引入足球高尔夫只有短短一年时间,却成为本届世界杯各队瞩目的焦点,不是因为成绩,而是因为这支四人队伍对这项运动的热爱、付出、执着和雄心。在阿根廷世界杯迈出中国足球高尔夫历史上的第一步之后,中国将于今年夏天首次举办亚太杯赛事,韩国、日本、澳大利亚和新西兰队已表示,“将派最强队伍参赛。”此外,法国亦向中国伸出橄榄枝,“欢迎来参加5月的法国锦标赛。”而新科世界杯冠军奥特罗表示:“未来希望去中国、去观澜湖打比赛。”
热点资讯
- 小米MIX3手持超级夜景拍摄样张展示2019-10-29
- 从爆品到精品,小米产品模式的新逻辑2019-11-06
- 三星天津手机工厂被曝12月31日停产2019-11-12
- 扫黄打非办等两部门约谈腾讯:要求清理淫秽低俗内容微信公众号2019-11-13
- 小米计划在英国发布首款手机年底登陆美国2019-11-14
- 一线|《剑侠情缘2:剑歌行》手游明年春上线2019-10-29
- 诺基亚7.1香港、澳门开卖:价格直逼诺基亚X72019-10-29
- 怎样炒大虾好吃又简单?2019-11-10