Spring aop

介绍spring aop 的使用方式,使用的框架是spring-boot

核心概念

Aspect:即切面,切面一般定义为一个 Java 类, 每个切面侧重于特定的跨领域功能,比如,事务管理或者日志打印等。
Joinpoint:即连接点,程序执行的某个点,比如方法执行。构造函数调用或者字段赋值等。在 Spring AOP 中,连接点只会有 方法调用 (Method execution)。
Advice:即通知,在连接点要的代码。
Pointcut:即切点,一个匹配连接点的正则表达式。当一个连接点匹配到切点时,一个关联到这个切点的特定的 通知 (Advice) 会被执行。
Weaving:即编织,负责将切面和目标对象链接,以创建通知对象,在 Spring AOP 中没有这个东西。

代码

废话不多说,我们查看下代码

pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

服务类

下面我们测试aop 的各种情况都在一个类中体现

@Service

public class AppService {


    @CaculateExecuteTime // 这个是自定义的注解,用来计算方法的执行时间
    public void share(String articleUrl){
	// 这个方法是我们的核心测试方法
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("share  article"+articleUrl);
    }


    public void onebyone(){

        System.out.println("拥有全部的拦截器");
    }

}

切面类

@Component
@Aspect //标记为一个切面
public class ServiceAspect {


    /**
     * execution 该指示器用来匹配方法执行连接点,即匹配哪个方法执行
     * within     如果要匹配一个类中所有方法的调用,便可以使用 within 指示器 还可以匹配某个包下面的所有类的所有方法调用
     * target 如果目标对象实现了任何接口,Spring AOP 会创建基于CGLIB 的动态代理,这时候需要使用 target 指示器
     * this  如果目标对象没有实现任何接口,Spring AOP 会创建基于JDK的动态代理,这时候需要使用 this 指示器
     * @target 该指示器用于匹配连接点所在的类是否拥有指定类型的注解,注意是所在类
     * @annotation 匹配连接点的某个方法是否有某个注解
     */

    @Pointcut("execution(public void WeiXinService.share(String))") //定义切点 在指定方法上拦截
    public void shareCut(){

    }


    @Pointcut("within(com.zhibinwang.WeiXinService)") //定义切点  拦截这个类的所有方法
    public void shareCutAll(){

    }

    @Pointcut("@annotation(CaculateExecuteTime)") // 拦截自定义的注解,这个是方法上的,用于确认方法的执行时间
    public void shareAnntion(){}


    /**
     * @AfterReturing:该 Advice 会在方法正常返回以后执行
     * @AfterThrowing: 该 Advice 会在方法抛出异常以后执行
     * @After: 该 Advice 无论如何,在方法执行以后都会执行
     * @param joinPoint
     */

    @AfterReturning("shareCut()") //在业务返回后执行
    public void log(JoinPoint joinPoint){

        System.out.println(joinPoint.getSignature()+" executed");

    }

    @Before("shareCutAll()") // 在方法执行前执行
    public void log2(JoinPoint joinPoint){
        System.out.println(WeiXinService.class.getName()+"这个类的方法执行前全部被拦截");
    }


    @Around("shareAnntion()") // 在方法执行前后执行
    public void arround(ProceedingJoinPoint joinPoint){
        long l = System.currentTimeMillis();
        try{        Object proceed = joinPoint.proceed();}catch (Exception e){} catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        System.out.println("消耗时间="+(System.currentTimeMillis() - l));
    }

}

自定义注解


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CaculateExecuteTime {
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {AppAspect.class})
public class TestBoot {


    @Autowired
    ApplicationContext context;



    @Test
    public void test(){
        AppService bean = context.getBean(AppService.class);
        bean.share("baidu");
    }

}

执行结果

com.zhibinwang.WeiXinService这个类的方法执行前全部被拦截  # 方法执行前
share  articlebaidu   #方法执行
消耗时间=3004 # 方法执行前后
void com.zhibinwang.WeiXinService.share(String) executed # 方法返回以后

执行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值