浅谈Spring——AOP

前言

Spring是目前比较常用的框架,其核心是控制反转(IoC)和面向切面编程(AOP)。通过IOC容器管理POJO或JavaBean对象,以及它们之间的耦合关系;通过AOP以动态非入侵的方式增强服务。这篇主要浅谈一下AOP~

一、AOP概念

面向切面的技术,开发者可以在不改变原有方法逻辑的情况下,对方法逻辑进行加强,或者校验操作。

实现:动态代理是面向切面编程最主流的实现。而SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层动态代理机制,对特定的方法进行编程。

二、AOP的简单应用

1.我这边使用的是maven项目,如果没有相应的包,需要先导入依赖到maven仓库。

<!--AOP依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.创建一个切面类,用来统计方法的执行时间和返回结果。其中

@Aspect 注解用来告知该类属于切面类

 @Component 注解将该类声明为IOC容器的been对象

@Pointcut用于定义切入点,切入点表达式中用execution定义方法切点保重包含的方法(

 com.example.testdemo.service.*.*(..)对应的就是下面第二张图中的方法。


@Aspect
@Component
public class AspectTest {

    // 切点定义
    @Pointcut("execution(* com.example.testdemo.service.*.*(..))")
    public void servicePointcut() {}

    // 前置通知,记录方法调用入参和当前时间
    @Around("servicePointcut()")
    public void logMethodEntry(ProceedingJoinPoint joinPoint) throws Throwable {
        String method = joinPoint.getSignature().getName();
        System.out.println("调用 " + method + " 方法");
        System.out.println("调用开始时间 " + new Date() + " -----------------------------------------------");
        Object result = joinPoint.proceed();
        System.out.println("调用结果 " + result);
        System.out.println("调用结束时间 " + new Date() + " -----------------------------------------------");
    }
}
@Service
public class TestDemoServiceImpl implements TestDemoService {


    @Override
    public String helloWord() {
        int n=0;
        for(int i=0; i<1000 ; i++){
            n = n+i;
        }
        return String.valueOf(n);
    }
}

执行结果

其中有几个注意的点

@Around:环绕通知,使用此注解标注的通知方法在目标前、后都被执行。

@Before:前置通知,会在通知方法使用之前被执行。

@After:后置通知,会在通知方法使用之后被执行,无论是否有异常都会被执行。

@AfterReturning:返回后通知,会在方法完成后被执行,有异常不会执行。

@AfterThrowing:异常后通知,会在通知方法发生异常后执行。

三、自定义注解的使用

我们接着以上的实例进行一个自定义注解话的改造。

1.首先创建一个注解类

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

}
@Target 注解——指明可以被注解修饰的类型
ElementType.TYPE                                  可以用于类、接口和枚举类型
ElementType.FIELD                                 可以用于字段(包括枚举常量)
ElementType.METHOD                            可以用于方法(controller上面的接口里它也是方法)
ElementType.PARAMETER                     可以用于方法的参数
ElementType.CONSTRUCTOR                可以用于构造函数
ElementType.LOCAL_VARIABLE           可以用于局部变量
ElementType.ANNOTATION_TYPE         可以用于注解类型
ElementType.PACKAGE                          可以用于包
ElementType.TYPE_PARAMETER          可以用于类型参数声明(Java 8新增)
ElementType.TYPE_USE                         可以用于使用类型的任何语句中(Java 8新增)

@Rerention 注解——指明被注解的类的生命周期(一般都会使用RUNTIME)
RetentionPolicy.SOURCE在源文件中有效(即源文件保留)
RetentionPolicy.CLASS在class文件中有效(即class保留),不会被加载到JVM中
RetentionPolicy.RUNTIME在运行时有效(即运行时保留),会被加载到JVM中

@Documented 注解——表示被注解的类将被javadoc 工具提取成文档。

@Inherited 注解——表示被它修饰的注解具有继承性,即如果一个类声明了被 @Inherited 修饰的注解,那么它的子类也将具有这个注解。

 2.此处的切点指向的是刚刚创建的注解类。

@Aspect
@Component
public class AspectTest {

    // 切点定义
    @Pointcut(value="@annotation(com.example.testdemo.until.TestTimeDate)")
    public void servicePointcut() {}

    // 前置通知,记录方法调用入参和当前时间
    @Around("servicePointcut()")
    public void logMethodEntry(ProceedingJoinPoint joinPoint) throws Throwable {
        String method = joinPoint.getSignature().getName();
        System.out.println("调用 " + method + " 方法");
        System.out.println("调用开始时间 " + new Date() + " -----------------------------------------------");
        Object result = joinPoint.proceed();
        System.out.println("调用结果 " + result);
        System.out.println("调用结束时间 " + new Date() + " -----------------------------------------------");
    }
}

3.在运行的方法上添加注解 @TestTimeDate

    @Override
    @TestTimeDate
    public String helloWord() {
        int n=0;
        for(int i=0; i<1000 ; i++){
            n = n+i;
        }
        return String.valueOf(n);
    }

我们先看一下没有加注解时候的运行结果。可以看到,并没有进入我们的切面方法。

接下来看下加了注解时候的运行结果。可以看出,由注解进入了我们的切面方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值