美文网首页
spring-2-AOP

spring-2-AOP

作者: blank_white | 来源:发表于2020-06-22 19:28 被阅读0次

一、AOP

Aspect Oriented Programming:面向切面编程
如果一个类的多个方法的,在开始前/结束后,都需要执行相同的操作,就会需要到这种技术

这种技术可以 通过动态代理(jdk proxy)实现,也可以通过继承方式(cglib)实现

Spring 集成了两种 AOP 开发工具
Spring-aop 不如 aspectJ 好用,一般使用 aspectJ
aspectJ 支持动态代理实现,也支持继承方式实现

二、添加依赖

pom.xml 中添加依赖

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
  </dependencies>

三、通过注解方式使用

spring.xml 中,设置自动代理,并为声明你的代理类和目标类

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="serverAspect" class="com.spyouth.service.AspectServer"></bean>
<bean id="server" class="com.spyouth.service.SomeServerImpl" scope="prototype"></bean>

切入点:在那个类的哪个方法切入
切入时间:在方法执行前,执行后,还是什么时间切入?

  • @Before 在方法执行前
  • @Around 在方法执行前后
  • @AfterReturning 在方法返回后
  • @After 无论是否出现异常,在方法执行后(finally)
  • @AfterThrowing 在方法出现异常时(catch)
//表明此类是一个注解类
@Aspect
public class AspectServer {

    // value 值为切入点,用 execution 表达式表示,
    // execution 写法搜索 execution 表达式

    //以方法名标记一种切入点
    @Pointcut(value = "execution(* com..*.do*(..))")
    public void cutPoint(){}

    //方法的名字自定义,参数列表自定义
    @Before(value = "execution(* com..*.do*(..))")
    public void before(JoinPoint jp){
        System.out.println("Aspect before");

        //方法的参数如果设置了 JoinPoint ,则可以通过此变量获取关于切入点的一些属性
        jp.getSignature();
        jp.getSignature().getName();
        jp.getArgs();
    }
    
    //在方法执行前后都可以,和 jdk 动态代理的 invoke 方法相似
    //
    @Around(value = "execution(* com..*.do*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("Aspect around before");
        //执行切入点方法,和 invoke 方法中的 method.invoke 类似
        //若果不加这句话,就不会执行切入点了
        Object o=pjp.proceed();
        System.out.println("Aspect around after");

        // o= "改变了";
        // 能更改切入点的返回值

        return o;
    }

    //在切入点返回后执行
    //切入点也可以用函数名,前提是前面的那个把函数名作为切入点 id 了
    @AfterReturning(value = "cutPoint()",returning = "result")
    public void afterReturn(Object result){
        System.out.println("Aspect after returning");

        //是把切入点的返回值赋给了 Object result
        //所以修改 result 并不能修改 切入点的返回值
        //但如果 result 引用类型,result 和 切入点返回值,都指向的是相同的对象
        //则可以通过如 result.setName() result.name="xxxx" 改变对象的成员值
    }

    //在切入点执行后,及时切入点 执行时出现异常,相当于 finally 中
    @After(value = "cutPoint()")
    public void after(){
        System.out.println("Aspect after ");
    }

    //在切入点执行出现异常时,相当于 catch 中
    @AfterThrowing(value = "cutPoint()",throwing = "ex")
    public void afterThrowing(Throwable ex){
        System.out.println("Aspect afterThrowing "+ex.getMessage());
    }
}

无异常时执行结果

Aspect around before
Aspect before
SomeServerImpl->>>>>doSome(int a, String b)
Aspect around after
Aspect after 
Aspect after returning

出现异常时执行结果
注意:这里 after 是在 afterThrowing之前执行的,并没有完全和 try catch finally 顺序相同

Aspect around before
Aspect before
SomeServerImpl->>>>>doSome(int a, String b)
Aspect after 
Aspect afterThrowing / by zero

通过标签方式使用

把上面那个 AspectServer 中的注解去掉

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <bean id="serverAspect" class="com.spyouth.service.AspectServer"></bean>
    <aop:config proxy-target-class="true" >
        <aop:aspect id="myAspect自己起名" ref="serverAspect">
            <aop:pointcut id="doSome" expression="execution(* com..*.do*(..))"/>
            <aop:before method="before" pointcut-ref="doSome" ></aop:before>
            <aop:around method="around" pointcut-ref="doSome"></aop:around>
            <aop:after-returning method="afterReturn" pointcut-ref="doSome" returning="result"></aop:after-returning>
            <aop:after method="after" pointcut-ref="doSome" ></aop:after>
            <aop:after-throwing method="afterThrowing" pointcut-ref="doSome" throwing="ex"></aop:after-throwing>
        </aop:aspect>
    </aop:config>

相关文章

  • spring-2-AOP

    一、AOP Aspect Oriented Programming:面向切面编程如果一个类的多个方法的,在开始前/...

网友评论

      本文标题:spring-2-AOP

      本文链接:https://www.haomeiwen.com/subject/hrpiihtx.html