转载

Spring学习——Aop

Aop简介

AOP是面向切面编程,Aop的主要作用就是可以动态的向运行程序中插入代码段。Aop的最主要作用就是日志文件的编写。Aop的底层思想就是动态代理,而动态代理运用了Java底层的反射机制。动态代理用代理对象代替原始对象。在JDK原始动态代理中有一个缺陷就是他们一定要实现同一个接口,如果原始对象没有实现接口就无法使用动态代理。Aop的主要对象就是切面,使用Aop可以使业务模块更加简洁、日志代码集中便于维护管理。

Spring中的Aop

目前Spring使用的Aop框架是AspectJ,它既可以支持注解模式添加Aop也支持利用配置XMl的方式添加Aop。一般比较重要的业务代码建议用配置xml的方式添加,普通业务代码可以使用注解模式添加更加方便。在Spring中使用Aop一个是使用了jdk原生的动态代理(需要实现接口)另一个就是使用了cglib(无需实现接口)。但要在Spring中使用Aop总的步骤如下:

1.需要导入jar包

commons-logging-1.1.3.jar
spring-aop-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
以及强化版AOP 即没有实现同一接口也可以实现AOP
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

2.需要引入aop名称空间

3.在xml文件中写下配置语句 <aop:aspectj-autoproxy>

4.在IOC容器中配置需要添加Aop的bean实例

5.在切面类上添加@Aspect注解和五大通知注解或Xml配置切面和五大通知

@Before:在方法执行前通知

@After:在方法执行之后通知

@AfterReturning:返回通知,在方法返回后执行

@AfterThrowing:在方法抛出异常后执行

@Around(最强大的功能,相当于直接执行了动态代理):围绕方法执行

6.为以上五个通知注解配置切入点,配置切入点后,Aop就会在切入点方法执行前后执行!

切入点编写之通配符:

1. * 匹配一个或者多个字符和一个参数但只能配置一层路径!
       2. ..任意多个参数,匹配任意多个路径
       3. &&和||与日常代码使用相同

切入点编写之返回值:

returning=""(正常返回的结果) 
       throwing="" (执行异常时返回异常信息)

切入点示例:

@AfterReturning(value="execution(public String com.AopTest..MyMethod*.*(..))",returning="name")
public static void ReturnAlert(JoinPoint joinPoint,Object name)
//如果不希望每次都填写切入点可以使用@Pointcut注解,即可重复使用切入点。
//该切入点访问权限值为public,返回值类型为String,Com.MyAopTest.后缀.Mymethod下的所有任意参数的任意方法!执行成功的返回值是name。
//注意JoinPoint是Aop方法对象,里面封装了Aop切面的信息,其中最重要的是Signature signature=jointPoint.getSignature();用来获取方法信息。
//其他还有JointPoint.getArgs[]获取方法参数,
//jointPoint.getTarget();获取被代理对象
//jointPoint.getThis();获取代理对象

Aop的Xml配置

<bean id="Mymethod" class="com.AopTest.MyMethod"></bean>
<bean id="AopMethod" class="com.logs.MyMethod"></bean>
<!--将切面和需要执行切面的类加入IOC容器-->
<aop:config>
        <aop:pointcut expression="execution(public String com.AopTest..MyMethod*.*(..))" id="AllPoint"/>
  <!-- 配置pointcut-->
    
    
        <aop:aspect ref="AopMethod">
            <aop:around method="Aroundlog" pointcut-ref="AllPoint"/>
            <aop:before method="Startlog" pointcut-ref="AopMethod"/>
            <aop:after-returning method="Returnlog" pointcut-ref="AopMethod" returning="result"/>
            <aop:after-throwing method="Exceptionlog" pointcut-ref="AopMethod" throwing="exception"/>
            <aop:after method="Endlog~" pointcut-ref="AopMethod"/>
        </aop:aspect>
</aop:config>

使用Aop的注意点

1.通知方法的执行顺序一般是:

try{
           @Before
           方法();
           @AfterReturning
        }catch()
        {
            @AfterThrowing
        }finally
        {
            @After
        }

正常返回:@Before->@After->@AfterReturning

异常返回:@Before->@After->@AfterThrowing

  1. Aop底层实现还是动态代理,因此IOC容器中使用Aop的组件实际都是一个代理对象而不是本类对象。实现了Aop的接口和实现类Class都应该为com.sun.proxy.$Proxy12
  2. 环绕通知和其他通知一起执行时,环绕通知永远优于普通通知执行。
@Before
  {
  try{
    环绕前置~~~~
    方法执行
    环绕返回
    }
    catch()
    {
    环绕异常
    }finally{
    环绕后置
    }
  }
  @After
  @AfterReturning

正常情况:环绕前置通知->-前置通知>方法执行->环绕返回通知->环绕后置通知->后置通知->后置返回通知

异常情况:环绕前置通知->前置通知->环绕通知异常->环绕后置通知->后置通知->后置通知正常返回结果 (此处后置通知能正常返回,因为环绕通知已经把异常处理,后置通知无法发现错误)

3.多个切面一起执行时,先进来的切面后出去。先进后出原则!例如有A,B两个切面。

正常情况:A前置通知->B前置通知->方法执行->B后置通知->B后置返回通知->A后置通知->A后置返回通知

异常情况:同上

原文  https://segmentfault.com/a/1190000022101238
正文到此结束
Loading...