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. 原生态JDBC

    原生态JDBC JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API.JDBC是java访问数据库的标准规范,可以为不同的关系 ...

  2. appJar 界面效果

    appJar from appJar import gui app = gui() def main(): app.setLocation(200, 200) app.addLabel('2333', ...

  3. Docker学习笔记之docker volume 容器卷的那些事(一)

    预览目录 volume 方式 相关用例 使用方式 使用 volume driver bind mount 方式 相关用例 使用方式 配置selinux标签 配置macOS的安装一致性 tmpfs 方式 ...

  4. Centos7.3+uwsgi+Nginx部署Django程序

    1. 安装Python,这里我用的是阿里云的centos7.3,自带python2,所以,此步略过,具体安装Python可Google. 2. 安装uwsgi,如果安装失败的话首先,我的Python解 ...

  5. MQ选型对比RabbitMQ RocketMQ ActiveMQ Kafka(外加redis对比及其实现)

    rocketmq 4.3开始支持事务https://www.cnblogs.com/hzmark/p/rocket_txn.html 参考:rabbitMQ.activeMQ.zeroMQ.Kafka ...

  6. 10: VMware中扩展根分区

    1.1 添加一块硬盘 1.先给VMware添加一块60G硬盘 2.必须重启虚拟机才能识别到新加磁盘 fdisk -l        # 查看刚刚添加的硬盘 3.查看当前磁盘使用情况 df -hl   ...

  7. 程序连接oracle数据库问题Cannot create PoolableConnectionFactory ...

    报错: [ERROR] -- :: com.ipi.caee.InitServlet - 初始化数据加载异常 org.springframework.transaction.CannotCreateT ...

  8. oracle基础——内存管理、优化

    内存图解: 自动管理:11g:AMM   10g:ASMM SGA(system global area):由所有服务进程和后台进程共享 PGA(program global area): 由每个服务 ...

  9. alloc_skb申请函数分析

    alloc_skb()用于分配缓冲区的函数.由于"数据缓冲区"和"缓冲区的描述结构"(sk_buff结构)是两种不同的实体,这就意味着,在分配一个缓冲区时,需要 ...

  10. 今日头条 CEO 张一鸣:面试了 2000 个年轻人,混得好的都有这 5 种特质

    https://blog.csdn.net/qq_35246620/article/details/72801285 博主说:多了解了解总是好的. 正文 张一鸣算是 80 后中绝对的佼佼者.1983 ...