1. 界面应用场景
    1. 日志、声明式事务、安全、缓存
  2. AOP功能演化图
    1.   
    2. 图片引用地址:https://www.cnblogs.com/best/p/5679656.html
  3. AOP设计模式-代理模式
    1. 静态代理:手动编写代理类,手动编写代码拦截每个方法。工作量极大。
    2. JDK代理:利用反射,实现InvocationHandler接口。 业务类需要实现“业务接口”,利用反射技术代理该“业务接口”
    3. 动态代理:利用cglib。cglib是一种动态代码生成器,可以在运行期动态生成代理类
  4. AOP术语
    1. 关注点:重复代码就叫做关注点;
    2. 切面: 关注点形成的类,就叫切面(类)!是通知和节点的集合,这个集合决定了切面:是什么,在何时和何处完成其功能。
    3. 通知(advice):切面类函数。切面要完成的工作(切面类中的方法)。通知定义了切面是什么以及何时使用。Spring的通知有5种类型:before、after、after-returning、after-throwing和around这五种类型。
    4. 连接点(joinpoint):程序事件。连接点表示在何种操作发生时应用切面。比如方法调用时、修改字段时和抛出异常时等。我们的应用可能有数以千计的时机,这些时机被称为连接点。连接点是应用执行过程中能够插入切面的一个点。
    5. 切点(拦截的作用)(pointcut): 执行目标对象方法,动态植入切面代码。可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。切点有助于缩小切面所通知的连接点的范围。如果说通知定义了切面“是什么”、“何时”,那么切点就定义了“何处”。
      1. 可能应用有很多事件(连接点)可以用来对外提供“触角”,但通过某种方式选定的连接点与通知发生作用,这个连接点成为切点。
  5. Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截
  6. Spring 项目与AspectJ项目 之间有大量的合作;Spring 使用 AspectJ项目的注解语法,实现Spring自己基于代理的AOP。也就是Spring与AspectJ在注解的语法上是相同的,但底层实现是不同的,Spring底层只支持方法拦截,无法在bean创建时应用通知将;,AspectJ却支持构造器、属性、方法拦截。
    1. Spring AOP的切面类的编写使用纯java语法;
    2. AspectJ AOP的切面类编写使用java语言扩展,自成一套新的语法。
    3. Spring在运行时才创建AOP代理对象。
  7. 联合使用@Component@Aspect,将切面类以一个普通的全局单实例bean的形式注入到容器中,;可以在其他业务类型的bean中使用@Autowired注解 将切面类bean注入到普通业务bean中,获取其运行时状态值。
  8. Spring使用AsjpectJ定义切点表达式
    1. 明确具体方法  execution( * cn.jt.ClassA.run(..))
    2. 限定切点所属的包  execution(* cn.jt.ClassA.run(..)) within(cn.*)
    3. 限定切点所在bean  execution(* cn.jt.ClassA.run(..)) and bean(‘beanID’)
  9. 使用AOP,为已封装好的Java类,添加新的方法,实现类似Ruby的动态类的概念。但实际上,Spring将一个bean分拆到多个类中:原有类方法在一个类中,新添加的方法在一个类中。
  10. XML方式实现AOP编程 :在没有源码,或者不想把AspectJ注解污染到代码之中的情况下使用
    1. 步骤
      1. 1) 引入jar文件  【aop 相关jar, 4个】

        2) 引入aop名称空间

        3)aop 配置

        * 配置切面类 (重复执行代码形成的类)

        * aop配置

        拦截哪些方法 / 拦截到方法后应用通知代

    2. 示例
      1.   

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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"> <!-- dao 实例 在这里配置后就不用在类中使用注解 -->
        <bean id="aDao" class="xx"></bean>
        <bean id="bDao" class="yy"></bean> <!-- 切面类 -->
        <bean id="aop" class="aopClass1"></bean> <!-- Aop配置 -->
        <aop:config>
        <!-- 定义一个切入点表达式: 拦截哪些方法 -->
        <aop:pointcut expression="execution(* aopClass1.*.*(..))" id="pt"/>
        <!-- 切面 -->
        <aop:aspect ref="aop">
        <!-- 环绕通知 -->
        <aop:around method="around" pointcut-ref="pt"/>
        <!-- 前置通知: 在目标方法调用前执行 -->
        <aop:before method="begin" pointcut-ref="pt"/>
        <!-- 后置通知: -->
        <aop:after method="after" pointcut-ref="pt"/>
        <!-- 返回后通知 -->
        <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
        <!-- 异常通知 -->
        <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/> </aop:aspect>
        </aop:config>
        </beans>
  11. 注解方式实现AOP编程
    1. 先引入aop相关jar文件

      spring-aop-3.2.5.RELEASE.jar

          aopalliance.jar

            aspectjweaver.jar

          aspectjrt.jar

    2. bean.xml中引入aop名称空间

    3. 开启aop注解

    4. 使用注解
      1.   

        @Aspect                                                              指定一个类为切面类

        @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))")  指定切入点表达式

        @Before("pointCut_()")                                    前置通知: 目标方法之前执行

        @After("pointCut_()")                                         后置通知:目标方法之后执行(始终执行)

        @AfterReturning("pointCut_()")                         返回后通知: 执行方法结束前执行(异常不执行)

        @AfterThrowing("pointCut_()")                            异常通知:  出现异常时候执行

        @Around("pointCut_()")                                      环绕通知: 环绕目标方法执行

    5. 关于@Pointcut注解
      1. 是一个节点表达式,通过在一个空函数run()上使用@Pointcut注解,我们实际上扩展了切点表达式语言,这样就可以在任何切点表达式中使用run(),否则,需要在每个切点表达式使用那个更长的表达式。例如:
      2.     @AspectJ
        public class Audience{
        @Pointcut("execution(** cn.jt.run(..))")
        public void run(){} @Before("run()")
        public void beforeRun(ProceedingJoinPoint jp){
        System.out.println("berfor");
        jp.proceed();
        System.out.println("after");
        } @Around("run()")
        public void watchRun(ProceedingJoinPoint jp){
        System.out.println("berfor");
        jp.proceed();
        System.out.println("after");
        } }

        相当于:

      3.     @AspectJ
        public class Audience{
        @Before("execution(** cn.jt.run(..))")
        public void beforeRun(){
        System.out.println("berfor");
        } @Around("execution(** cn.jt.run(..))")
        public void watchRun(ProceedingJoinPoint jp){
        System.out.println("berfor");
        jp.proceed();
        System.out.println("after");
        } }
    6. 关于环绕通知:
      1. 环绕通知需要额外的ProceedingJoinPoint类型参数
      2. 如果不调用jp.proceed()方法,那么通知会阻塞对被通知方法的调用;或者调用多次,类似与“失败后重试”这样的业务逻辑。
    7. 将业务类方法中的参数,传递到通知(切面类方法)中。(使用 args 表达式)
      1. @Component
        @Aspect
        public class Audience { private Map<Integer, Integer> trackCounts = new HashMap<>(); @Pointcut("execution(** concert.JayPerform.playTrack(int)) && args(trackNum)") //<1>
        public void track(int trackNum) {} //<2> @AfterReturning("track(trackNum)") //<3>
        public void countTrack(int trackNum) //<4>
        { int currentCount = getPlayCount(trackNum);
        trackCounts.put(trackNum, currentCount+);
        System.out.println("------- 这首歌播放了"+(currentCount+)+"次");
        } public int getPlayCount(int trackNumber)
        {
        return trackCounts.containsKey(trackNumber)?trackCounts.get(trackNumber):;
        }
        }
      2. 代码中 <1>、<2>、<3>、<4> 处,int型参数的名称都是trackNum,这样保证了从命名切点到通知方法的参数转移。并且,这里的参数trackNum与concert.JayPerform.playTrack(int trackNum) 的参数命名相同。
        经过实验,发现这4处的参数名称与concert.JayPerform.playTrack(int trackNum)中的参数名称不必相同,只要<1>与<2>处参数名称相同、<3>与<4>处参数名称相同即可
    8. 示例
      1. bean.xml
        1.   

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:p="http://www.springframework.org/schema/p"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:aop="http://www.springframework.org/schema/aop"
          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"> <!-- 使用注解时要开启注解扫描 要扫描的包 -->
          <context:component-scan base-package="cn.jt"></context:component-scan> <!-- 开启aop注解方式 -->
          <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
          </beans>
      2. Java代码
        @Component  //加入IOC容器
        @Aspect // 指定当前类为切面类
        public class Aop { // 指定切入点表达式: 拦截哪些方法; 即为哪些类生成代理对象
          //解释@Pointcut("execution(* cn.jt.*.*(..))")
          //@Pointcut("execution(* 切入点表达式固定写法, cn.itcast.e_aop_anno表示包.类名(可以用*表示包下所有的类).方法名(可以用*表示类下所有的方法)(..)表示参数可以用..
        @Pointcut("execution(* cn.jt.*.*(..))")
        public void pointCut_(){
        }   //@Before("execution(* cn.jt.*.*(..))")每个方法需要写相同的引用,所以将相同的部分抽取到一个空的方法中pointCut_(),
        // 前置通知 : 在执行目标方法之前执行
        @Before("pointCut_()")
        public void begin(){
        System.out.println("开始事务/异常");
        } // 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】
        @After("pointCut_()")
        public void after(){
        System.out.println("提交事务/关闭");
        } // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
        @AfterReturning("pointCut_()")
        public void afterReturning() {
        System.out.println("afterReturning()");
        } // 异常通知: 当目标方法执行异常时候执行此关注点代码
        @AfterThrowing("pointCut_()")
        public void afterThrowing(){
        System.out.println("afterThrowing()");
        } // 环绕通知:环绕目标方式执行
        @Around("pointCut_()")
        public void around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("环绕前....");
        pjp.proceed(); // 执行目标方法
        System.out.println("环绕后....");
        } }

        测试类

        public class App {
        
            ApplicationContext ac =
        new ClassPathXmlApplicationContext("cn/jt/bean.xml"); // 目标对象有实现接口,spring会自动选择“JDK代理”
        @Test
        public void testApp() {
        IUserDao userDao = (IUserDao) ac.getBean("userDao");
        System.out.println(userDao.getClass());
        userDao.save();
        } // 目标对象没有实现接口, spring会用“cglib代理”
        @Test
        public void testCglib() {
        OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
        System.out.println(orderDao.getClass());
        orderDao.save();
        }
          1.     

Spring 梳理-AOP的更多相关文章

  1. Spring 梳理 - AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)

    Spring  AOP那些学术概念—通知.增强处理连接点(JoinPoint)切面(Aspect)   1.我所知道的AOP 初看起来,上来就是一大堆的术语,而且还有个拉风的名字,面向切面编程,都说是 ...

  2. Spring系列.AOP原理简析

    Spring AOP使用简介 Spring的两大核心功能是IOC和AOP.当我们使用Spring的AOP功能时是很方便的.只需要进行下面的配置即可. @Component @Aspect public ...

  3. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  4. Spring实现AOP的4种方式

    了解AOP的相关术语:1.通知(Advice):通知定义了切面是什么以及何时使用.描述了切面要完成的工作和何时需要执行这个工作.2.连接点(Joinpoint):程序能够应用通知的一个“时机”,这些“ ...

  5. spring的AOP

    最近公司项目中需要添加一个日志记录功能,就是可以清楚的看到谁在什么时间做了什么事情,因为项目已经运行很长时间,这个最初没有开来进来,所以就用spring的面向切面编程来实现这个功能.在做的时候对spr ...

  6. Spring(五)AOP简述

    一.AOP简述 AOP全称是:aspect-oriented programming,它是面向切面编号的思想核心, AOP和OOP既面向对象的编程语言,不相冲突,它们是两个相辅相成的设计模式型 AOP ...

  7. Spring中AOP原理,源码学习笔记

    一.AOP(面向切面编程):通过预编译和运行期动态代理的方式在不改变代码的情况下给程序动态的添加一些功能.利用AOP可以对应用程序的各个部分进行隔离,在Spring中AOP主要用来分离业务逻辑和系统级 ...

  8. Spring之AOP面向切片

       一.理论基础: AOP(Aspectoriented programming)面向切片/服务的编程,在Spring中使用最多的是对事物的处理.而AOP这种思想在程序中很多地方可以使用的,比如说, ...

  9. 利用CGLib实现动态代理实现Spring的AOP

    当我们用Proxy 实现Spring的AOP的时候, 我们的代理类必须实现了委托类的接口才能实现. 而如果代理类没有实现委托类的接口怎么办? 那么我们就可以通过CGLib来实现 package cn. ...

随机推荐

  1. 一个手写的Vue放大镜,复制即可使用

    一个手写的vue放大镜 组件使用less,请确保已安装loader 本组件为放大镜组件,传参列表为: width: 必传,设置放大镜的宽高(正方形),放大区域等同,放大倍数为2倍 picList:必传 ...

  2. CF - 1131 C Birthday

    题目传送门 显然可以发现: 我们sort之后,把奇数位的先按顺序拿出来,然后再把偶数位的按照反顺序拿出来,这样就可以保证答案最小. 代码: /* code by: zstu wxk time: 201 ...

  3. 杭电第六场 hdu6362 oval-and-rectangle 积分求期望

    oval-and-rectangle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  4. codeforces 812 E. Sagheer and Apple Tree(树+尼姆博弈)

    题目链接:http://codeforces.com/contest/812/problem/E 题意:有一颗苹果树,这个苹果树所有叶子节点的深度要不全是奇数,要不全是偶数,并且包括根在内的所有节点上 ...

  5. poj 1797Heavy Transportation(dijkstra变形)

    题目链接:http://poj.org/problem?id=1797 题意:有n个城市,m条道路,在每条道路上有一个承载量,现在要求从1到n城市最大承载量,而最大承载量就是从城市1到城市n所有通路上 ...

  6. Go pprof性能调优

    在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling 的库,这篇文章 ...

  7. FreeSql (二十三)分组、聚合

    IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, "Data ...

  8. Winform中设置DevExpress的RadioGroup的items从配置文件中加载

    场景 DevExpress的RadioGroup的items选项如果是不确定的话,需要其从配置文件中加载. 实现 在项目目录下新建Config文件夹,文件夹下新建xml配置文件. <?xml v ...

  9. IntelliJ IDEA远程连接tomcat,实现单步调试

    web项目部署到tomcat上之后,有时需要打断点单步调试,如果用的是Intellij idea,可以通过如下方法实现: 开启debug端口,启动tomcat 以tomcat7.0.75为例,打开bi ...

  10. Python基础(十)

    今日主要内容 补充:传参与参数分配区别 动态传参 函数注释 名称空间 函数名的使用 函数嵌套 global和nonlocal 补充:传参与参数分配区分 先看一个函数定义和函数调用 def func(a ...