SpringAOP技术学习---Day3

本篇博客知识点
学习SpringAOP第三种技术—利用注解完成拦截

AOP技术的本质为一个公式

切面 = 切点 + 通知

四种技术都只是通过不同形式完成这个公式而言,第三种是通过注解

第一步:写一个类 就是我们的切面
类名任意但是类前面必须加一个注解 @Aspect
这里写图片描述

底层Spring可以通过这个注解知道这个类就是我们的切面。

第二步:写切点 :字符内容为 切点语言 AspectJ
切点有两种形式写法,第一种是通过类成员变量
这里写图片描述
第二种形式:写在一个成员方法上,
这里写图片描述
第三步:写通知,通知有多种
通过注解写到成员方法名字上,方法内的 就是切面执行函数。
两种对应前面两个切点的使用方法
这里写图片描述

这里写图片描述

下面是对几种常用的拦截方法介绍
@Before :原型对象执行前拦截,
@After:原型对象执行后拦截
@Around: 可以原型对象执行前后拦截
@AfterReturning:原型对象执行时正常返回结果未出错时候 触发
@AfterThrowing:原型对象执行时未正常返回结果出错时候 触发

下面是两个切面的代码

package cn.hncu2.v3;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

//切面= 切点  + 通知
//@Aspect = @Pointcut + (@Before | @After | Around | @AfterReturning | @AfterThrowing 等当中至少有1种)

@Aspect
public class MyAdvisor {

     @Pointcut(value="execution( * cn..Cat.*(..) )")  //@Pointcut中的value属性来指定切点的表达式----用aspectj切点语言
     public void aa(){ //该方法没别的功能,就是为了让@Pointcut有个寄居的地方,同时也用于标识该注解
     }

     @Pointcut(value="execution( * cn..Person.*(..) ) ") 
     public void bb(){ 
     }

     @Before(value="aa()")  //由@Before通知的value属性指定PointCut(本例为aa()方法上的切点)
     public void bf(){
         System.out.println("前面拦拦......");
     }

     @After(value="aa()")
     public void after1(){
         System.out.println("后面拦拦1.....");
     }

     //下面的方法可以采用空参,但通过手动注入一个JoinPoint类型的参数,可以获得拦截"连接点"的信息如: 是否为方法执行、被拦截方法的名字、方法的对象等
     @After(value="bb()")
     public void after2(JoinPoint jp){//通过手动注入 jp参数 ---缺点:依赖JoinPoint类,因此如果没必要的话,就不加这个参数
         System.out.println("后面拦拦2.....:"+ jp.getKind()+","+jp.getSignature().getName()+","+jp.getTarget() );
     }

     @Around(value="aa()") //Around通知的拦截方法必须依赖一个ProceedingJoinPoint参数,否则无法放行, 同时方法要返回Object(被放行方法的返回值)
     public Object around(ProceedingJoinPoint p) throws Throwable{  //ProceedingJoinPoint 是 JoinPoint 的子类
         System.out.println("前前前拦拦.....:"+ p.getKind()+","+p.getSignature().getName()+","+p.getTarget() );
         Object res = p.proceed(); //放行
         System.out.println("后后后拦拦....");
         return res;
     }

     @AfterReturning(value="aa()")
     public void afterReturn(){ //该方法可以注入JoinPoint参数,也可以不注入
         System.out.println("方法正常返回之后......");
     }
     @AfterThrowing(value="aa()")
     public void afterThrow(){ //该方法可以注入JoinPoint参数,也可以不注入
        System.out.println("方法抛出异常之后....."); 
     }

}
package cn.hncu2.v3;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//切面= 切点  + 通知
//@Aspect = @Pointcut + (@Before | @After | Around | @AfterReturning | @AfterThrowing 等当中至少有1种)

@Aspect
public class MyAdvisor2 {

    //用表达式字符串来代替切点
    private final String CUT="execution( * cn..Person.*(..) )";

     @Before(CUT)
     public void bf(){
         System.out.println("前面拦拦......");
     }

     @Around(CUT)
     public Object around(ProceedingJoinPoint p) throws Throwable{  //ProceedingJoinPoint 是 JoinPoint 的子类
         System.out.println("前前前2拦拦.....:"+ p.getKind()+","+p.getSignature().getName()+","+p.getTarget() );
         Object res = p.proceed(); //放行
         System.out.println("后后后2拦拦....");
         return res;
     }

}

vvv.xml容器代码

<?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: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 
        ">

    <!-- 自动代理  , 低版Spring可以用该自动代理类  替代 下面的自动代理标签
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
      -->

    <!-- 自动代理的标签 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

     <!-- 基于注解的切面 -->
    <!-- <bean class="cn.hncu.v3.MyAdvisor"></bean> -->
    <bean class="cn.hncu.v3.MyAdvisor2"></bean>

    <bean id="p" class="cn.hncu.v3.Person"></bean>
    <bean id="cat" class="cn.hncu.v3.Cat"></bean>

</beans>
package cn.hncu.v3;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {
    @Test
    public void t1(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/v3/vvv.xml");

        Person p = ctx.getBean("p",Person.class);
        p.run();
        p.fun("lalala");
        p.ok("hncu", 66);

        Cat c = ctx.getBean("cat", Cat.class);
        c.run();

    }
}

执行结果
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值