spring学习(二) ———— AOP之AspectJ框架的使用

前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么。而今天要学习spring的第二个重点,AOP。一篇讲解不完,所以这篇文章主要介绍一下什么是AOP,如何去理解AOP。理解完之后,在spring中如何使用AspectJ AOP框架的。看得懂,写的出spring配置的那么就学的差不多了。加油。建议都自己手动实现一遍,这样才能更好的理解。

                              --WH

一、什么是AOP?

      AOP:面向切面编程,采用横向抽取机制,取代了传统的纵向继承

      IOC:控制反转     

        跟IOC一样,我也不知道,这么高大上的名称,被吓坏了,MD,但是通过前面一节的学习,IOC不就是让spring给我们new对象吗,而不需要我们自己创建,

        而AOP是一种面向切面的思想,但是我们平常说的spring使用了AOP,实际上说的是spring实现AOP思想的底层原理,而底层原理就是使用动态代理来增强某个方法。所以平常说AOP技术实际上就是指通过动态代理来对方法进行增强。

        比如:我们需要对一个已经写好的类中的方法进行增强,在不改动该类方法的代码的情况下,如何做呢?

        传统纵向继承

          编写一个类,继承该类,重写该类中的这种需要增强的方法,这样确实可以达到我们的目的,但是一旦需要修改的方法所属的类不是一个类,那么就需要在多写很多子类,增加很多方法,编程量就是一个很大的问题,并且后期要修改,工作量也很大。

                

        横向抽取机制,将要增强所用到的代码提取到一个类中,然后对需要增强的方法通过代理类去将其增强即可。

                

              

二、动态代理的两个方式

      JDK动态代理。接口+实现类

      cglib字节码增强。 实现类

      为了更好的理解spring的AOP技术,我们应该手动编写以上两种实现动态代理的方法,然后才能体会到spring实现AOP技术所带来的便利。

      2.1、JDK动态代理。

          要使用JDK动态代理的类,必须要有接口。这是前提条件。

                

          编写UserService接口和UserServiceImpl。

                  

          创建代理类的工厂proxyFactory

                  

            增强代码的类

                  

            测试testApp

                  

            测试结果 成功增强了userServiceImpl对象的add方法。如果别的类有需要被增强的方法,那么同样通过创建工厂代理就可以拿到对应的代理对象。然后进行加强

                  

                  

                  

        2.2、cglib动态代理。

            被代理的对象不需要在实现接口,要求就放松了很多。很多时候都采用cglib来进行动态代理。

            需要导入两个jar包

                  

            spring已经将cglib和asm整合到了spring-core-3.2.0.jar中,所以我们导入spring的jar包就不需要在重复导这两个包了。

            跟JDK动态代理的编写流程是一样的

            UserServiceImpl。没有接口了

                  

            增强方法的类

                    

          

            创建代理的工厂(和jdk动态代理有区别)

                      

              测试

                   成功增强方法。

              注意:CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,所以                 说被代理的类不能有final关键字 

三、spring中使用AOP的相关术语

         3.1、Target:目标类,需要被增强的类,也就是上面我们写的UserServiceImpl。

         3.2、JointPoint:连接点,目标类上需要被增强的方法,(这些方法可以被增强,也可以不增强,也就是说目标类中所有的方法都可以称为是连接点)

         3.3、PointCut:切入点,被增强的方法(已经确定这个方法要被增强),切入点就是一个连接点的子集

         3.4、Advice:增强/通知,增强的代码,也就是上面将增强的代码凑成的一个类。类中的每个方法都代表一个增强的功能代码,这个类中的方法就被称为通知

         3.5、weaving:织入,将切入点和通知结合,从没被增强到已经增强的过程

         3.6、Aspect:切面,切入点和通知结合,切入点 和 通知点 多点形成面  特殊情况:一个切入点 和 一个通知

                画张图就可以理解了。

                

          3.7、Introduction(引介) 特殊的通知,可以对类增强,添加方法或字段。(知道)

四、spring如何帮我们实现AOP技术(初级版)

       spring创建代理工厂bean,属于半自动,思路跟我们用JDK动态代理和cglib动态代理是一样的,只是spring通过ioc帮我们创建这些对象,工厂也是由spring提供。唯一的不同是,我们编写的通知类(之后将其叫成切面类,也就是放增强的代码方法的类) 必须实现MethodInterceptor(注意导包时的问题,这个名称跟cglib中的那个一样,不要导错了)接口,并实现invoke方法,这里就是编写如何增强切入点,好比上面jdk动态代理和cglib代理中的匿名内部类中的方法一样。具体下面讲解。

       导入jar包

            

          spring : 4个核心 + 1个依赖

          spring aop联盟:

          spring aop 实现:

       UserServiceImpl

          

         MySpect 切面类,

            

        applicationcontext.xml。

              

          这里注意,如果没有接口,那么其中必须使用3.4的代码也就是34行的代码,必须告诉spring,使用cglib进行代理,否则出错。

         测试

             

    

          总结:这种方式属性半自动的,需要配置工厂bean,并且目标类的确定太小了,每次只能指定一个目标类,如果我们想对别的类也进行加强,那么就需要在工厂bean中又配置一个目标类,这就体现不出spring的优势了。不推荐使用这种。了解整个发展过程即可

五、spring实现AOP技术(中级 掌握)

      全自动过程。直接覆盖很多目标类,不需要在一个个对目标类进行编写通知和工厂了。

            其他都一样,配置文件不一样。切入点就不单单是一个目标类了。而是一个范围。

              

             切面类还是跟上面一样

              

            测试: 成功

              

          

            总结:相比初级的aop实现,好的地方在不用在自己设置工厂bean了,还在直接大范围的指定代理目标类,而不是一个类只能被指定一次。这就是全自动,不用我们配置工厂bean

,spring帮我们都做好了。我们只需要关注切面类,也就是通知和切入点的结合即可。

  

六、使用AspectJ框架(xml方式)实现aop(高级,推荐)

        使用这个的好处在于,我们都不需要在切面类中实现什么通知类型接口了,通知类型接口也在配置文件中编写,而切面类只要关注增强的方法代码即可。并且不管业务类是否实现接口,编写的代码都是一样的,如果实现了接口。AspectJ框架会使用jdk代理,如果没有实现接口,则使用cglib代理,这两者之间相互转换。而spring内置的aop技术则需要自己手动去设置,默认是jdk,如果没有接口,不会自动帮我们转换。

        导包:新增两个aspect支持的jar包

             aop联盟:com.springsource.org.aopalliance-1.0.0.jar

           spring aop支持:spring-aop-3.2.0.RELEASE.jar

           aspect 规范:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

          spring aspect 支持:spring-aspects-3.2.0.RELEASE.jar

              

        AspectJ规定通知类型

          6个,知道5个,掌握一个

            1.before:前置通知(应用:各种校验)

            在方法执行前执行,如果通知抛出异常,阻止方法运行

            2.afterReturning:后置通知(应用:常规数据处理)

                   方法正常返回后执行,如果方法中抛出异常,通知无法执行

                   必须在方法执行后才执行,所以可以获得方法的返回值。

            3.around:环绕通知(应用:十分强大,可以做任何事情) 【掌握】

                 方法执行前后分别执行,可以阻止方法的执行。要求必须手动的执行目标方法。

            4.afterThrowing:抛出异常通知(应用:包装异常信息)

                  方法抛出异常后执行,如果方法没有抛出异常,无法执行

            5.after:最终通知(应用:清理现场)

                方法执行完毕后执行,无论方法中是否出现异常

        配置文件

            

        通知类型的详解

            

            

         切面类

            

          测试:

              

        总结:使用AspectJ框架实现AOP,好处很多,关注的点只有切面类(不需要实现通知类型接口),切入点范围,还有通知类型。所以在配置文件中,也只需要配置这三个关键的东西即可,具体看上面的配置文件

七、使用AspectJ框架(注解方式)实现aop(高级,推荐)

         使用注解的话,很简单,就是把xml方式用注解给替代,其中也就做6件事

        1、将切面类配置给spring,相当于<bean id="" class="切面类全限定类名">

           @component

        2、将切面类申明为切面

           @Aspect

            

        3、将目标类配置给spring

           @component  如何不编写名称的话,那么要获取该对象,则使用userServiceImpl进行获取。

            

        4、申明目标类切入点范围

            1.方法必须private,没有返回值,没有参数

            2.之后使用将其当成方法调用。例如:@After("myPointcut()") 

           @Pointcut("execution(* com.wuhao.aspectj.annotation.*.*(..))")

            

        5、编写相应的通知           

          @Before 前置

          @AfterReturning  后置,可以获得返回值,必须在注解中确定返回值参数名称。

          @AfterThrowing 抛出异常,可以获得具体异常信息,必须在注解确定第二个参数名称

          @Around 环绕[]

          @After 最终  

            

        

         6:必须在xml中扫描注解和启用aop

            

        7、测试

            

        总结;注解的编写也很简单,要会写注解,首先的知道xml是如何实现的,然后一步步用注解来替代xml的内容即可。并且要知道使用AspectJ框架需要配置哪些内容,就三个点,

           xml:

              目标类bean

              切面类bean   

              <aop:config>

                  <aop:aspect ref="myAspectId">      //切面

                  <aop:pointcut expression="execution(* com.wuhao.aspectj.*.*(..))" id="myPointCutId"/>   //切入点范围:<aop:pointcut/>   

                  <aop:around method="myAround" pointcut-ref="myPointCutId"/>       //通知类型:<aop:around/>

              </aop:config>

           

              

八、总结

      基本上把spring中使用AOP的技术讲清楚了,可能一开始很不习惯,用多了自然就习惯了,并且建议手写你jdk代理和cglib代理,这样一步步来,就更容易理解在spring中应用AOP的技术的编写代码了。下一篇还会对spring中使用AOP的技术进一步讲解,这一篇相等于写一个aop的helloworld一样。

原文地址:https://www.cnblogs.com/surfcater/p/10225635.html

时间: 2024-10-14 11:49:13

spring学习(二) ———— AOP之AspectJ框架的使用的相关文章

Android Afinal框架学习(二) FinalActivity 一个IOC框架

框架地址:https://github.com/yangfuhai/afinal 对应的源码: net.tsz.afinal.annotation.view.* FinalActivity FinalActivity是一个基础类,结合注解实现了,依赖注入(view的资源id,常用的监听器), 利用set方式注入 完全注解方式就可以进行UI绑定和事件绑定,无需findViewById和set event Listener 这个过程:initInjectedView>findViewById.set

Spring学习之Aop的各种增强方法

AspectJ允许使用注解用于定义切面.切入点和增强处理,而Spring框架则可以识别并根据这些注解来生成AOP代理.Spring只是使用了和AspectJ 5一样的注解,但并没有使用AspectJ的编译器或者织入器,底层依然使用SpringAOP来实现,依然是在运行时动态生成AOP代理,因此不需要增加额外的编译,也不需要AspectJ的织入器支持.而AspectJ采用编译时增强,所以AspectJ需要使用自己的编译器来编译Java文件,还需要织入器. 为了启用Spring对@AspectJ切面

spring学习二:根据spring原理自己写个spring

请先看我另一篇文章:"Spring学习一:IOC(控制反转)和AOP(面向切面)的xml配置和注解方式"中大概知道他的简单用法 那我自己想写一个简单sping,注解的方式以后再写 方式:1.解析xml配置 2.使用java的反射机制生产动态代理对象 3.扫描类上的注解,再用反射(没写) 代码如下(简单实现,重原理轻代码,不喜勿喷) xml配置我就直接用我上一篇spring-test的配置了,代码也用上一篇的,但解析的时候是用自己写的,没有用调用任何spring API代码 <?x

Spring学习笔记AOP(二)

鲁春利的工作笔记,好记性不如烂笔头 要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间: 引入后AOP命名空间并启动对@AspectJ注解的支持(spring-context-aop-annotation.xml): <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&q

Spring学习之AOP

一.概述 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 简而言之,aop的作用就是在不修改源码的情况下对程序进行增强,如权限校验,日志记录,性

Spring学习之Aop的基本概念

转自:http://my.oschina.net/itblog/blog/209067 AOP的基本概念 AOP从运行的角度考虑程序的流程,提取业务处理过程的切面.AOP面向的是程序运行中的各个步骤,希望以更好的方式来组合业务逻辑的各个步骤.AOP框架并不与特定的代码耦合,AOP框架能处理程序执行中特定切入点,而不与具体某个类耦合(即在不污染某个类的情况下,处理这个类相关的切点).下面是一些AOP的一些术语: 切面(Aspect):业务流程运行的某个特定步骤,也就是应用运行过程的关注点,关注点通

spring学习 注解AOP 通知传递参数

我们在对切点进行增强时,不建议对切点进行任何修改,因此不加以使用@PointCut注解打在切点上,尽量只在Advice上打注解(Before,After等),如果要在通知中接受切点的参数,可以使用JoinPoint或者ProceedingJoinPoint 在Spring AOP中可以通过两种方式传递参数给Advice(通知) (1)通过接受JoinPoint(非环绕通知)或ProceedingJoinPoint(环绕通知)参数,其实ProceedingJoinPoint是JointPoint的

Spring学习笔记----AOP编程

先用代码讲一下什么是传统的AOP(面向切面编程)编程 需求:实现一个简单的计算器,在每一步的运算前添加日志.最传统的方式如下: Calculator.java package cn.limbo.spring.aop.calculator; /** * Created by Limbo on 16/7/14. */ public interface Calculator { int add(int i , int j); int sub(int i , int j); int mul(int i

Spring学习笔记AOP(四)

鲁春利的工作笔记,好记性不如烂笔头 基于XML配置方式声明切面 Spring使用org.springframework.aop.Advisor接口表示切面的概念,Advisor表示只有一个通知(org.aopalliance.aop.Advice)和一个切入点(org.springframework.aop.Pointcut)的切面.Advisor可以使用<aop:config>标签下的<aop:advisor>标签定义. <aop:advisor id="标识&q