spring AOP

一、Spring AOP

1.什么是aop?

Aspect Oriented Programing面向切面编程,相比较oop面向对象编程来说,Aop关注的不再是程序代码中某个类,某些方法,而aop考虑的更多的是一种面到面的切入, 即层与层之间的一种切入,所以称之为切面。

2.aop能做什么?

主要应用于日志记录,性能统计,安全控制,事物处理等方面,实现公共功能性的重复使用。

3.aop的特点

(1)降低模块与模块之间的耦合度,提高业务代码的聚合度。(高内聚低耦合 )
(2)提高了代码的复用性。
(3)提高系统的扩展性。(高版本兼容低版本)
(4)可以在不影响原有的功能基础上添加新的功能

4.aop的底层实现

动态代理(JDK+CGLIB)

二、AOP基本概念

1.Joinpoint(连接点)

被拦截到的每个点,spring中指被拦截到的每一个方法, spring aop一个连接点即代表一个方法的执行。

2.Pointcut(切入点)

对连接点进行拦截的定义(匹配规则定义规定拦截哪些方法,对哪些方法进行处理), spring 有专门的表达式语言定义。

3.Advice(通知)

拦截到每一一个连接点即(每一 个方法)后所要做的操作
(1)前置通知(前置增强) - before() 执行方法前通知
(2)返回通知(返回增强) - afterReturn 方法正常结束返回后的通知
(3)异常抛出通知(异常抛出增强) - afetrThrow()
(4)最终通知- after无论方法是否发生异常,均会执行该通知。
(5)环绕通知- around包围一-个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

4.Aspect(切面)

切入点与通知的结合,决定了切面的定义,切入点定义了要拦截哪些类的哪些方法,通知则定义了拦截过方法后要做什么,切面则是横切关注点的抽象,与类相似,类是对物体特征的抽象,切面则是横切关注点抽象。

三、AOP实现

1.引入依赖
<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9.1</version>
<!--            <scope>runtime</scope>-->
</dependency>

注意:一定要将标签<scope>这一行注释掉,不然在编译阶段无法得到这个包,也无法用里面的注解。

如果加上<scope>runtime</scope>表明被依赖的项目不参与项目的编译。

2.代码实现

(1)定义一个切面类,在类上加上@Component,表明被spring接管。同时在该类上加上另一个注解@Aspect,表明这个类是一个切面。

@Component
@Aspect
public class LogCut {

}

(2)切面是由切入点和通知组成的。所以这时候添加一个方法,方法名上加注解@Pointcut("execution(* com.rqt.spring.service.*.*(..))")表明这是个切入点,

@Pointcut("execution(* com.rqt.spring.service.*.*(..))")
    public void cut(){

    }

括号里面的内容是spring的匹配规则,execution后面括号中的内容常用的有以下几种:

  • 执行所有的公共方法——execution(public *(..))
  • 执行任意的set方法——execution(* set*(..))
  • 设置指定包下面的任意类的任意方法——execution(* com.xxx.service.*.*(..))
  • 设置指定包及其子包下面的任意类的任意方法——execution(* com.xxx.service..*.*(..))

(3)设置通知。

//目标方法执行前通知
//value的值是定义的切入点
    @Before(value = "cut()")
    public void before(){
        System.out.println("前置通知");
    }

    //目标方法在执行后,执行该通知(无论有没有异常)
    @After(value = "cut()")
    public void after(){
        System.out.println("最终通知");
    }

    //目标方法无异常执行后,执行该通知
    @AfterReturning(value = "cut()")
    public void afterReturn(){
        System.out.println("返回通知");
    }

    //目标方法执行出现异常后,执行该通知
    @AfterThrowing(value = "cut()")
    public void afterThrow(){
        System.out.println("异常通知");
    }

    @Around(value = "cut()")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("环绕通知中的前置通知");
        Object object = null;
        try {
            object = pjp.proceed();
            System.out.println("环绕通知中的返回通知");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕通知中的异常通知");
        }
        System.out.println("环绕通知中的最终通知");
        return object;
    }

(4)开启aop自动代理。在xml文件中添加如下配置:

<aop:aspectj-autoproxy/>

这步要注意将命名空间导入,不然不生效。

(5)测试。以service包下的类为例。在这里只测环绕通知

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
@Service
public class UserService {

    public void test(){
        System.out.println("test");
    }
}

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值