4.113 Spring的核心-面向切面编程AOP

 

  1. 什么是AOP?

    1. OOP(Object-Oriented Programming)面向对象编程,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用
    2. AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。
    3. AOP相关术语
      1. Aop,  aspect object programming  面向切面编程  让关注点代码与业务代码分离
      2. 关注点,重复代码就叫做关注点
      3. 切面,关注点形成的类,就叫切面(类)!
      4.  面向切面编程,就是指 对很多功能都有的重复的代码抽取,再在运行的时候网业务方法上动态植入“切面类代码”
      5. 切入点,执行目标对象方法,动态植入切面代码。可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。
  2. Spring AOP中的动态代理主要有两种方式,JDK动态代理CGLIB动态代理

      1. 代理(Proxy)是一种设计模式, 提供了对目标对象另外的访问方式;即通过代理访问目标对象。 这样好处: 可以在目标对象实现的基础上,增强额外的功能操作。(扩展目标对象的功能)。
        1. 举例:张学友明星(目标)<---经纪人(代理)<-------电视台
        2. 代理模式的关键点: 代理对象与目标对象
      2. 静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
        1. 静态代理要实现目标对象一样的接口
        2. 可以做到在不修改目标对象的功能前提下,对目标对象功能扩展
        3. 缺点:(代理工厂?  可以使用动态代理弥补缺点。)
          1. 因为代理对象,需要与目标对象实现一样的接口。所以会有很多代理类,类太多
          2. 一旦接口增加方法,目标对象与代理对象都要维护。
      3. JDK动态代理:只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
        1. 代理对象,不需要实现接口
        2. 代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建 代理对象/目标对象 实现的接口的类型
        3. 动态代理, JDK代理, 接口代理
        4. 总结:代理对象不需要实现接口,但是目标对象一定要实现接口;否则不能用动态代理
        5. 缺点(以子类的方式实现(cglib代理)弥补)
          1.  有一个目标对象,想要功能扩展,但目标对象没有实现接口,怎样功能扩展?
      4. CGLIB来动态代理:如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
        1. JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
        2.  CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
        3. CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
        4. Cglib子类代理实现具体:
          1. 需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
          2. 引入功能包后,就可以在内存中动态构建子类
          3. 代理的类不能为final, 否则报错。
          4.  目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法
      5. 代理在Spring的AOP编程中
        1. 如果加入容器的目标对象有实现接口,用JDK代理;
        2.  如果目标对象没有实现接口,用Cglib代理
      6. AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。
        1. AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
        2. Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
  3. 实现方式

    1. 注解的切面实现:在这种情况下(基于@AspectJ的实现),涉及到的切面声明的风格与带有java5标注的普通java类一致。<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  开启事物注解权限
      1. @Aspect                                                    指定一个类为切面类
      2. @Pointcut("execution(* com.itmayiedu.service.UserService.add(..))")  指定切入点表达式
      3. @Before("pointCut_()")                                前置通知: 目标方法之前执行
      4. @After("pointCut_()")                                  后置通知:目标方法之后执行(始终执行)
      5. @AfterReturning("pointCut_()")             返回后通知: 执行方法结束前执行(异常不执行)
      6. @AfterThrowing("pointCut_()")                  异常通知:  出现异常时候执行
      7. @Around("pointCut_()")                              环绕通知: 环绕目标方法执行
    2. 基于XML Schema方式的切面实现:在这种情况下,切面由常规类以及基于XML的配置实现
      1. 引入jar文件  【aop 相关jar, 4个】
      2. 引入aop名称空间
      3. aop 配置
posted @ 2020-10-09 18:21  Smileing  阅读(73)  评论(0编辑  收藏  举报