跟着刚哥学习Spring框架--AOP(五)
AOP
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
基于Spring的AOP简单实现
1、通过配置文件实现AOP
首先需要额外上网下载两个jar包:
① aspectjrt.jar
② aspectjweaver.jar
先定义一个接口IHelloWorld:
1 public interface IHelloWorld { 2 void printHelloWorld(String name); 3 }
定义一个实现类HelloWorld
1 public class HelloWorld implements IHelloWorld { 2 3 @Override 4 public void printHelloWorld(String name) { 5 System.out.println("Print HelloWorld :" + name); 6 } 7 }
实现了两个切面(一个日志切面和一个时间切面)
1 public class LogAspect { 2 public void beforeLog(JoinPoint joinPoint){ 3 System.out.println("log before method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 4 } 5 public void afterLog(JoinPoint joinPoint){ 6 System.out.println("log after method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 7 } 8 }
1 public class TimeAspect { 2 public void beforeTime(JoinPoint joinPoint){ 3 System.out.println("time before method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 4 } 5 public void afterTime(JoinPoint joinPoint){ 6 System.out.println("time after method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 7 } 8 }
定义一个配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 7 8 <!-- 核心业务Bean --> 9 <bean id="helloworld" class="com.hzg.HelloWorld"></bean> 10 11 <!-- 切面Bean(日志切面) --> 12 <bean id="logAspect" class="com.hzg.LogAspect"></bean> 13 14 <!-- 切面Bean(时间切面) --> 15 <bean id="timeAspect" class="com.hzg.TimeAspect"></bean> 16 17 <!-- AOP配置 --> 18 <aop:config> 19 <!-- 配置切点 --> 20 <aop:pointcut id="pointcut" expression="execution(* com.hzg.IHelloWorld.*(..))"></aop:pointcut> 21 <!-- 配置切面(日志切面)切面的优先级需要通过order定义 --> 22 <aop:aspect id="log" ref="logAspect" order="1"> 23 <!-- 配置通知(前置通知、后置通知、返回通知、异常通知、环绕通知) --> 24 <aop:before method="beforeLog" pointcut-ref="pointcut"></aop:before> 25 <aop:after method="afterLog" pointcut-ref="pointcut"></aop:after> 26 </aop:aspect> 27 <!-- 配置切面(时间切面)切面的优先级需要通过order定义 --> 28 <aop:aspect id="time" ref="timeAspect" order="2"> 29 <!-- 配置通知(前置通知、后置通知、后置返回通知、异常通知、环绕通知) --> 30 <aop:before method="beforeTime" pointcut-ref="pointcut"></aop:before> 31 <aop:after method="afterTime" pointcut-ref="pointcut"></aop:after> 32 </aop:aspect> 33 </aop:config> 34 35 </beans>
定义Main主方法
1 public static void main(String[] args) { 2 //由于ApplicationContext没有close方法,所以要使用它下面接口ConfigurableApplicationContext 3 ApplicationContext ctx = new ClassPathXmlApplicationContext("configaop.xml"); 4 IHelloWorld helloworld = (IHelloWorld) ctx.getBean("helloworld"); 5 helloworld.printHelloWorld("gangge"); 6 }
输出结果:
log before method printHelloWorld参数 :[gangge] time before method printHelloWorld参数 :[gangge] Print HelloWorld :gangge time after method printHelloWorld参数 :[gangge] log after method printHelloWorld参数 :[gangge]
2、通过注解实现AOP
实现配置文件方式同样的功能
先定义一个接口文件(没区别)
1 public interface IHelloWorld { 2 void printHelloWorld(String name); 3 }
定义实现类(区别:加了一个注解@Component)
1 @Component 2 public class HelloWorld implements IHelloWorld { 3 4 @Override 5 public void printHelloWorld(String name) { 6 System.out.println("Print HelloWorld :" + name); 7 } 8 }
定义两个切面(一个日志切面和一个时间切面 区别:增加了@Component、@Aspect和@Order注解)
1 @Component 2 @Aspect 3 @Order(1) 4 public class LogAspect { 5 public void beforeLog(JoinPoint joinPoint){ 6 System.out.println("log before method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 7 } 8 public void afterLog(JoinPoint joinPoint){ 9 System.out.println("log after method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 10 } 11 }
1 @Component 2 @Aspect 3 @Order(2) 4 public class TimeAspect { 5 @Before("execution(* com.hzg.HelloWorld.*(..))") 6 public void beforeTime(JoinPoint joinPoint){ 7 System.out.println("time before method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 8 } 9 @After("execution(* com.hzg.HelloWorld.*(..))") 10 public void afterTime(JoinPoint joinPoint){ 11 System.out.println("time after method " + joinPoint.getSignature().getName() + "参数 :" + Arrays.asList(joinPoint.getArgs())); 12 } 13 }
定义配置文件(区别:Spring自动扫描包和aop自动代理)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 7 8 <context:component-scan base-package="com.hzg"></context:component-scan> 9 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 10 11 </beans>
定义Main主方法(无区别)
1 public static void main(String[] args) { 2 //由于ApplicationContext没有close方法,所以要使用它下面接口ConfigurableApplicationContext 3 ApplicationContext ctx = new ClassPathXmlApplicationContext("configaop.xml"); 4 IHelloWorld helloworld = (IHelloWorld) ctx.getBean("helloworld"); 5 helloworld.printHelloWorld("gangge"); 6 }
输出结果和配置文件一样
五种通知:
1、前置通知
上面已经有了,不再说明
2、后置通知
上面已经有了,不再说明
3、返回通知
1 /** 2 * 返回通知: 方法正常执行完后调用,如果有异常,则不调用 3 * 可以访问到方法的返回值 4 * @param joinPoint 5 * @param result 方法的返回值 6 */ 7 @AfterReturning(value="execution(* com.hzg.*(..))",returning="result") 8 public void afterReturning(JoinPoint joinPoint,Object result){ 9 //方法名 10 String methodName = joinPoint.getSignature().getName(); 11 System.out.println("method "+methodName+" end:"+result); 12 }
4、异常通知
1 /** 2 * 异常通知: 当方法出现异常时 3 * 可以指定出现哪些异常时才执行: 如何指定?通过入参指定,如: 4 * 如果入参为NullPointException ex,那么只有在发生空指针异常时才执行 5 * @param joinPoint 6 * @param ex 7 */ 8 @AfterThrowing(value="execution(* com.hzg.*(..))",throwing="ex") 9 public void afterThrowing(JoinPoint joinPoint,Exception ex){ 10 //方法名 11 String methodName = joinPoint.getSignature().getName(); 12 System.out.println("method "+methodName+" occurs:"+ex); 13 }
5、环绕通知
环绕通知类似于动态代理的全过程,可以使用环绕通知实现前置通知,后置通知,返回通知,异常通知的功能,十分强大,但并不常用
1 /** 2 * 环绕通知需要携带ProceedingJoinPoint类型的参数 3 * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint这个类型的参数可以决定是否执行目标方法 4 * 且环绕通知必须有返回值,返回值即为目标方法的返回值 5 * @param pjd 6 */ 7 @Around("execution(* com.hzg.*(..))") 8 public Object around(ProceedingJoinPoint pjd){ 9 Object result = null; 10 String methodName = pjd.getSignature().getName(); 11 12 try { 13 //前置通知 14 System.out.println("method:"+methodName+" begins with "+Arrays.asList(pjd.getArgs())); 15 //执行目标方法 16 result = pjd.proceed(); 17 //返回通知 18 System.out.println("method:"+methodName+" end with "+result); 19 } catch (Throwable e) { 20 // 异常通知 21 System.out.println("method:"+methodName+" occurs exception "+e); 22 } 23 //后置通知 24 System.out.println("method ends"); 25 return result; 26 }
-------------------------------------------------------------------------------------------------------------------------
跟着刚哥学习Spring框架系列:
跟着刚哥学习Spring框架--创建HelloWorld项目(一)
跟着刚哥学习Spring框架--Spring容器(二)
跟着刚哥学习Spring框架--通过XML方式配置Bean(三)
跟着刚哥学习Spring框架--通过注解方式配置Bean(四)
跟着刚哥学习Spring框架--AOP(五)
跟着刚哥学习Spring框架--JDBC(六)
跟着刚哥学习Spring框架--事务配置(七)
转载于:https://www.cnblogs.com/hzg110/p/6794465.html
跟着刚哥学习Spring框架--AOP(五)相关推荐
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- Spring框架(五):Spring事务简述(注解方式)
一.Spring事务的概述 事务的作用是什么? 简单来说,就是在数据层保障一系列的数据库操作同成功同失败(提交和回滚) Spring事务作用︰在数据层或[业务层]保障一系列的数据库操作同成功同失败. ...
- Spring框架AOP源码剖析
今天我要和大家分享的是 AOP(Aspect-Oriented Programming)这个东西的源码剖析,作为多年的开发者,想必大家在面试的时候都被问过,你知道Spring框架AOP的底层实现机制吗 ...
- 每天一点儿时间学习Spring框架系列—IOC(2)
每天一点儿时间学习Spring框架--Ioc(2) 前篇简单入门了Spring的结构,这次就来开始讨论其中的控制反转的思想和自己的一些编写实例分享.(编写不一定能够完美的实现,建议大家了解其中的基本步 ...
- Spring框架 AOP面向切面编程(转)
一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...
- Spring框架----AOP的概念及术语
1.什么是AOP AOP:全称是 Aspect Oriented Programming 即:面向切面编程 简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源 ...
- 深入学习Spring框架(二)- 注解配置
1.为什么要学习Spring的注解配置? 基于注解配置的方式也已经逐渐代替xml.所以我们必须要掌握使用注解的方式配置Spring. 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯 ...
- Spring框架——AOP入门笔记以及个人总结
注:作者本人也是初学者,所以本文有些总结性见解可能存在问题,但是多数问题都是在上网查询过资料后总结的,如果有逻辑或者原理上的错误,或者见解不同,欢迎在评论区讨论!!! 目录 Spring的AOP 1. ...
- Spring框架-AOP
1.什么是AOP? 面向切面编程,可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率 通过不修改源代码方式,在主干功能里面添加新功能 2 ...
- 学习Spring框架有这一篇就够了
目录 一.Spring框架 1.什么是Spring 2. 为什么使用spring 3.程序的耦合 4.解决办法IOC控制反转 二. 如何使用spring 1.Spring程序开发步骤 2.使用spri ...
最新文章
- sql2005中的简单分页方法
- Hadoop集群datanode磁盘不均衡的解决方案
- hdu 4983(欧拉函数)
- 《Python》进程收尾线程初识
- 老司机学习MyBatis之如何通过select返回Map
- (二)ngxin设置用户认证
- Android Studio导入项目遇到的问题
- java quartz DateBuilder
- Castle的自定义类型转换
- 利用matlab进行Vissim二次开发,史上最详细
- 用html设计logo,网页设计中的logo设计方法
- 手机成像技术简谈(测光篇)
- 考拉情书---一片道歉叶
- 我的ROS学习之路——动起来的小海龟
- realsense中IMU的简单使用与学习
- MEDLINE与PubMed有什么区别?检索范围包含哪些?
- gcc连接脚本 ld.info
- 一对一培训之视频免费分享-2018-03-19-第 04 阶段-部署-基础-环境
- mysql数据库巡检工作内容_数据库巡检
- 关于寝室熄灯问题调研的思考
热门文章
- 梧桐那时雨http://blog.csdn.net/fuchaosz/article/details/51882935?readlog
- 一家服装定制公司从创立到上市,所有步骤及背后的商业模式分享!
- 国际项目投标那些事(九)海外工程投标时价格高超预算会怎样
- 使用Spring 3构建RESTful Web服务
- 编程题:实现一个 LazyMan 方法
- 《2022上半年游戏安全洞察报告》发布:外挂肆虐,内容安全问题依旧严峻
- c#生成静态库_C语言学习篇(30)——ARM Keil制作静态链接库
- 生活随记-遇到的不可思议的事情
- 爱奇艺首页导航轮播特效
- 换季掌握3点技巧想不白都难