AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。

  一 AOP的基本概念

  (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

  (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

  (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

  (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

  (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

  如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  二 Spring AOP

  Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。

  三 基于注解的AOP配置方式

  1.启用@AsjectJ支持

  在applicationContext.xml中配置下面一句:

  

  2.通知类型介绍

  (1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可

  (2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值

  (3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名

  来访问目标方法中所抛出的异常对象

  (4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

  (5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint

  3.例子:

  spring框架 AOP核心详解

  (1)Operator.java -- 切面类

  @Componentbr/@Aspect

  public class Operator {

  @Pointcut(execution( com.aijava.springcode.service...*(..)))

  public void pointCut(){}

  @Before(pointCut())

  public void doBefore(JoinPoint joinPoint){

  System.out.println(AOP Before Advice...);

  }

  @After(pointCut())

  public void doAfter(JoinPoint joinPoint){

  System.out.println(AOP After Advice...);

  }

  @AfterReturning(pointcut=pointCut(),returning=returnVal)

  public void afterReturn(JoinPoint joinPoint,Object returnVal){

  System.out.println(AOP AfterReturning Advice: + returnVal);

  }

  @AfterThrowing(pointcut=pointCut(),throwing=error)

  public void afterThrowing(JoinPoint joinPoint,Throwable error){

  System.out.println(AOP AfterThrowing Advice... + error);

  System.out.println(AfterThrowing...);

  }

  @Around(pointCut())

  public void around(ProceedingJoinPoint pjp){

  System.out.println(AOP Aronud before...);

  try {

  pjp.proceed();

  } catch (Throwable e) {

  e.printStackTrace();

  }

  System.out.println(AOP Aronud after...);

  }

  }

  (2)UserService.java -- 定义一些目标方法

  @Service

  public class UserService {

  public void add(){

  System.out.println(UserService add());

  }

  public boolean delete(){

  System.out.println(UserService delete());

  return true;

  }

  public void edit(){

  System.out.println(UserService edit());

  int i = 5/0;

  }

  }

  (3).applicationContext.xml

  

  

  (4).Test.java

  public class Test {

  public static void main(String[] args) {

  ApplicationContext ctx = new ClassPathXmlApplicationContext(classpath:applicationContext.xml);

  UserService userService = (UserService) ctx.getBean(userService);

  userService.add();

  }

  }

  上面是一个比较简单的测试,基本涵盖了各种增强定义。注意:做环绕通知的时候,调用ProceedingJoinPoint的proceed()方法才会执行目标方法。

  4.通知执行的优先级

  进入目标方法时,先织入Around,再织入Before,退出目标方法时,先织入Around,再织入AfterReturning,最后才织入After。

  注意:Spring AOP的环绕通知会影响到AfterThrowing通知的运行,不要同时使用!同时使用也没啥意义。

  如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  5.切入点的定义和表达式

  切入点表达式的定义算是整个AOP中的核心,有一套自己的规范

  Spring AOP支持的切入点指示符:

  (1)execution:用来匹配执行方法的连接点

  A:@Pointcut(execution( com.aijava.springcode.service...*(..)))

  第一个表示匹配任意的方法返回值,..(两个点)表示零个或多个,上面的第一个..表示service包及其子包,第二个表示所有类,第三个*表示所有方法,第二个..表示

  方法的任意参数个数

  B:@Pointcut(within(com.aijava.springcode.service.*))

  within限定匹配方法的连接点,上面的就是表示匹配service包下的任意连接点

  C:@Pointcut(this(com.aijava.springcode.service.UserService))

  this用来限定AOP代理必须是指定类型的实例,如上,指定了一个特定的实例,就是UserService

  D:@Pointcut(bean(userService))

  bean也是非常常用的,bean可以指定IOC容器中的bean的名称

  后言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别:

  1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。

  2) 环绕通知可以控制返回对象,即你可以返回一个与目标对象完全不同的返回值,虽然这很危险,但是你却可以办到。而后置方法是无法办到的,因为他是在目标方法返回值后调用

  6.基于XML形式的配置方式

  开发中如果选用XML配置方式,通常就是POJO+XML来开发AOP,大同小异,无非就是在XML文件中写切入点表达式和通知类型

  例子:

  (1)Log.java

  public class Log {

  private Integer id;

  //操作名称,方法名

  private String operName;

  //操作人

  private String operator;

  //操作参数

  private String operParams;

  //操作结果 成功/失败

  private String operResult;

  //结果消息

  private String resultMsg;

  //操作时间

  private Date operTime = new Date();

  setter,getter

  }

  (2).Logger.java

  /**

  日志记录器 (AOP日志通知)

  */

  public class Logger {

  @Resource

  private LogService logService;

  public Object record(ProceedingJoinPoint pjp){

  Log log = new Log();

  try {

  log.setOperator(admin);

  String mname = pjp.getSignature().getName();

  log.setOperName(mname);

  //方法参数,本例中是User user

  Object[] args = pjp.getArgs();

  log.setOperParams(Arrays.toString(args));

  //执行目标方法,返回的是目标方法的返回值,本例中 void

  Object obj = pjp.proceed();

  if(obj != null){

  log.setResultMsg(obj.toString());

  }else{

  log.setResultMsg(null);

  }

  log.setOperResult(success);

  log.setOperTime(new Date());

  return obj;

  } catch (Throwable e) {

  log.setOperResult(failure);

  log.setResultMsg(e.getMessage());

  } finally{

  logService.saveLog(log);

  }

  return null;

  }

  }

  (3).applicationContext.xml

  

  

  

  

  

  注意切入点表达式,!bean(logService) 做日志通知的时候,不要给日志本身做日志,否则会造成无限循环!

  如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  有关更详细的Spring AOP知识,可以查看Spring官方文档第9章Aspect Oriented Programming with Spring

  7.JDK动态代理介绍

  例子:

  (1)UserService.java

  public interface UserService {

  public void add();

  }

  (2)UserServiceImpl.java

  public class UserServiceImpl implements UserService{

  public void add() {

  System.out.println(User add()...);

  }

  }

  (3)ProxyUtils.java

  public class ProxyUtils implements InvocationHandler{

  private Object target;

  public ProxyUtils(Object target){

  this.target = target;

  }

  public Object getTarget() {

  return target;

  }

  public void setTarget(Object target) {

  this.target = target;

  }

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

  System.out.println(do sth before...);

  method.invoke(target, args);

  System.out.println(do sth after...);

  return null;

  }

  }

  (4)Test.java

  public class Test {

  public static void main(String[] args) {

  UserService userService = new UserServiceImpl();

  ProxyUtils proxyUtils = new ProxyUtils(userService);

  UserService proxyObject = (UserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),UserServiceImpl.class.getInterfaces(), proxyUtils);

  proxyObject.add();

  }

  }

  JDK动态代理核心还是一个InvocationHandler,记住这个就行了。

spring框架 AOP核心详解的更多相关文章

  1. Spring框架学习-Spring的AOP概念详解

    一.SpringAOP的概述. AOP(Aspect Oriented Programming),面向切面编程,通过预编译方式和运行期间动态代理实现程序的功能的统一维护的技术.AOP是OOP(面向对象 ...

  2. Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计

    在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...

  3. Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程

    上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...

  4. Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...

  5. Spring框架的核心功能之AOP技术

     技术分析之Spring框架的核心功能之AOP技术 AOP的概述        1. 什么是AOP的技术?        * 在软件业,AOP为Aspect Oriented Programming的 ...

  6. Spring各个jar包详解

    Spring各jar包详解 spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar,aspects.jar, spring-portlet.jar, and sprin ...

  7. Spring Batch(4): Job详解

    Spring Batch(4): Job详解 2016-03-26 18:46 870人阅读 评论(1) 收藏 举报  分类: Spring(6)  版权声明:本文为博主原创文章,未经博主允许不得转载 ...

  8. 跟着刚哥学习Spring框架--AOP(五)

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  9. RPC框架调用过程详解

    RPC框架调用过程详解 2017年09月16日 21:14:08 荷叶清泉 阅读数 6275   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...

随机推荐

  1. PKUWC2018 5/6

    总结: D1T1T2的思路较为好想,D1T3考试时估计是战略放弃的对象,D2T1思路容易卡在优化状态上(虽然明显3n的状态中有很多无用状态,从而想到子集最优,选择子集最优容易发现反例,从而考虑连带周边 ...

  2. ssh 工具

    ssh 使用 rsa key 实现无密码访问 server A 要用 rsa key 验证的方式访问 server B 在A上创建/root/.ssh/目录 > chmod -R 700 /ro ...

  3. spring boot @Scheduled未生效原因以及相关坑、及相对其他定时任务架构的优势

    在spring boot中,支持多种定时执行模式(cron, fixRate, fixDelay),在Application或者其他Autoconfig上增加@EnableScheduling注解开启 ...

  4. windows 7/10 安装u盘制作

    今天,在拷贝数据时,发现那台丢在那两三年的pc密码忘了,故计划重装,因为从来都是公司信息中心管这事,至少都七八年没有自己装机了,故整理过程如下: 1.从itellyou.cn下载原版镜像: 2.准备一 ...

  5. Python 使用 face_recognition 人脸识别

    Python 使用 face_recognition 人脸识别 官方说明:https://face-recognition.readthedocs.io/en/latest/readme.html 人 ...

  6. python简说(十八)导入模块

    1.import xx import 一个模块的实质就是把这个python文件从头到尾执行一遍 2.import模块的查找模块的顺序 1).从当前目录下找 2).sys.path python的安装目 ...

  7. mint-ui之tabbar使用

    <template> <div> <!-- tabcontainer --> <mt-tab-container class="page-tabba ...

  8. 使SourceInsight支持Python语言的方法

    刚用家里的电脑看Python代码,发现py的文件在SI不显示,才意识到还没有安装Python.CLF插件.正好把这个方法在这分享一下,毕竟so easy~ 下载点这里–>Python.CLF h ...

  9. error C4996: Function call with parameters that may be unsafe – this call relies on the caller to ch

    在加入QCustomplot时有如题的错误 1>c:\program files (x86)\microsoft visual studio11.0\vc\include\xutility(21 ...

  10. eclipse启动时发生的Initializing Java Tooling错误

    eclipse在启动发生An internal error occurred during: "Initializing Java Tooling". java.lang.Null ...