Springboot使用AOP

谈及Spring,就会想起它的两个特性IOC(Inversion of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程),当时,也不太注意这俩东西,到后来也多次重新了解过AOP思想(都是学得稀里糊涂的),这次,特意翻看官方文档,再次学习一下AOP。
AOP使用场景,个人不太好说,毕竟项目经验不足,反正听到最多的是使用AOP来实现全局异常处理。
引用官方的概念:
Let us begin by defining some central AOP concepts and terminology. These terms are not Spring-specific. Unfortunately, AOP terminology is not particularly intuitive. However, it would be even more confusing if Spring used its own terminology.

Aspect: A modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in enterprise Java applications. In Spring AOP, aspects are implemented by using regular classes (the schema-based approach) or regular classes annotated with the @Aspect annotation (the @AspectJ style).

Join point: A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.

Advice: Action taken by an aspect at a particular join point. Different types of advice include “around”, “before” and “after” advice. (Advice types are discussed later.) Many AOP frameworks, including Spring, model an advice as an interceptor and maintain a chain of interceptors around the join point.

Pointcut: A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut expression language by default.

Introduction: Declaring additional methods or fields on behalf of a type. Spring AOP lets you introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)

Target object: An object being advised by one or more aspects. Also referred to as the “advised object”. Since Spring AOP is implemented by using runtime proxies, this object is always a proxied object.

AOP proxy: An object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy is a JDK dynamic proxy or a CGLIB proxy.

Weaving: linking aspects with other application types or objects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.
谷歌浏览器的一键翻译:
让我们首先定义一些主要的AOP概念和术语。这些术语不是特定于Spring的。不幸的是,AOP术语并不是特别直观。但是,如果使用Spring自己的术语,将会更加令人困惑。

切面:涉及多个类别的关注点的模块化。事务管理是企业Java应用程序中横切关注的一个很好的例子。在Spring AOP中,方面是通过使用常规类(基于模式的方法)或通过注释进行@Aspect注释的常规类 (@AspectJ样式)来实现的。

连接点:在程序执行过程中的一点,例如方法的执行或异常的处理。在Spring AOP中,连接点始终代表方法的执行。

通知:方面在特定的连接点处采取的操作。不同类型的通知包括“周围”,“之前”和“之后”通知。(通知类型将在后面讨论。)包括Spring在内的许多AOP框架都将通知建模为拦截器,并在连接点周围维护一系列拦截器。

切入点:与连接点匹配的谓词。建议与切入点表达式关联,并在与该切入点匹配的任何连接点处运行(例如,执行具有特定名称的方法)。切入点表达式匹配的连接点的概念是AOP的核心,默认情况下,Spring使用AspectJ切入点表达语言。

简介(Introduction):代表类型声明其他方法或字段。Spring AOP允许您向任何建议对象引入新的接口(和相应的实现)。例如,您可以使用简介来使Bean实现 IsModified接口,以简化缓存。(在AspectJ社区中,介绍被称为类型间声明。)

目标对象:一个或多个方面建议的对象。也称为“建议对象”。由于Spring AOP是使用运行时代理实现的,因此该对象始终是代理对象。

AOP代理:由AOP框架创建的一个对象,用于实现方面合同(建议方法执行等)。在Spring Framework中,AOP代理是JDK动态代理或CGLIB代理。

织入:将方面与其他应用程序类型或对象链接以创建建议的对象。这可以在编译时(例如,使用AspectJ编译器),加载时或在运行时完成。像其他纯Java AOP框架一样,Spring AOP在运行时执行编织。

AOP能做什么呢?AOP能让我们更加的关注于自己的业务逻辑代码(后面结合案例就很好理解了),举个例子:今天,你想出去玩(你脑子就只需要想出去玩就OK了),至于你出去玩之前行程如何安排,装着如何打扮;出去玩之后,你如何回来,怎么回来,回来后干嘛,这些你都不需要关心,自然有人帮你安排好。这就是AOP帮你做的事了,你只关心你自己的业务逻辑代码。

既然你想出去玩,是否要让别人知道你出去玩?你只有让别人知道你出去玩,他们才能帮组安排好一切事宜,是吧?那好,你让别人知道你出去玩的一整个过程就是**切入点(pointCut)**了,pointCut就是让AOP知道需要管理的代码模块是谁;切入点有了,别人也知道你要出去玩了,就会着手安排你出去玩之前、玩时、之后的事宜

之前、玩时、之后的事宜就是AOP的连接点(Join Point)
切入点和连接点结合就成了AOP的核心了,官方解释:切入点表达式匹配的连接点的概念是AOP的核心

首先深入了解这两个点,结合案例就可以弄明白Spring AOP了,在案例之前首先了解一下AOP的通知(advice):
Spring AOP includes the following types of advice:

Before advice: Advice that runs before a join point but that does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).

After returning advice: Advice to be run after a join point completes normally (for example, if a method returns without throwing an exception).

After throwing advice: Advice to be executed if a method exits by throwing an exception.

After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).

Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

中文:
Spring AOP包括以下类型的通知:
通知前:在连接点之前运行但不能阻止执行流继续到连接点的通知(除非它抛出异常)。

返回通知后:连接点正常完成后要运行的通知(例如,如果方法返回而未引发异常)。

抛出通知之后:如果方法通过抛出异常而退出,则执行通知。

通知后(最终):不管连接点以何种方式退出(正常或异常返回)都要执行的通知。

环绕通知:包围连接点(如方法调用)的通知。这是最有力的通知。Around通知可以在方法调用前后执行自定义行为。它还负责选择是继续到连接点,还是通过返回自己的返回值或引发异常来缩短通知的方法执行。

Spring官网文档:spring aop
Springboot使用AOP需要引入AOP依赖包,MVN依赖库地址:mvn

AOP作为面向切面编程,所以,首先写一个切面类

package com.websocket.component;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 面向切面编程AOP
 * @date 2020-05-06
 * @author hjx
 *
 * */
@Component
@Aspect
public class SpringAopDemo {

 
}

@Aspect 注解:开启AOP支持
@Component 注解:把当前类交给Spring管理

切面好了,那就要知道谁需要AOP管理了,那就要用到切入点了(PointCut)

package com.websocket.component;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 面向切面编程AOP
 * @date 2020-05-06
 * @author hjx
 *
 * */
@Component
@Aspect
public class SpringAopDemo {

    /*
    * 切入点
    * */
    @Pointcut("execution(* com.websocket.controller..*.*(..))")
    public void pointCut(){};  
}

@Pointcut 注解: 标签当前方法是aop的切入点方法
需要注意的是pointCut的表达式execution()
这里的表达式含义:
第一个* 代表类型
com.websocket.controller..*代表这个包下的所以类包含子包的类
*..)代表所有方法的所有参数类型

所以在com.websocket.controller包下新建一个java类:

package com.websocket.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AopController {

    @RequestMapping(value = "/aopDemo")
    public String aopDemo() {
    //这里就是我们需要关心的业务逻辑代码了
//        int a = 1 /0;
        System.out.println("aopDemo Controller"); 
        return "AOP";
    }
}

上面说到,今天,你只需要知道自己要出去玩,但是,其他的事务,得有人帮忙处理啊,是吧?所以,AOP的通知、连接点就作用上了。

package com.websocket.component;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 面向切面编程AOP
 * @date 2020-05-06
 * @author hjx
 *
 * */
@Component
@Aspect
public class SpringAopDemo {

    /*
    * 切入点
    * 理解好表达式execution()
    * */
    @Pointcut("execution(* com.websocket.controller..*.*(..))")
    public void pointCut(){};
	
	/*
	熟悉吧,Before(通知的一种),再来看下连接点的概念:连接点:在程序执行过程中的一点,例如方法的执行或异常的处理。在Spring AOP中,连接点始终代表方法的执行。

	@Before()注解,标记这个方法是一个执行前方法,在目标对象执行前执行
	*/
    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println(signature.getDeclaringTypeName()+"下的" + signature.getName() + "执行了:----Advice Before----");
    }

	/*
	*运行返回执行,可以得到目标对象的返回值
	*/
    @AfterReturning(pointcut = "pointCut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, String result) {
        Signature signature = joinPoint.getSignature();
        System.out.println(result);
        System.out.println(signature.getDeclaringTypeName()+"下的" + signature.getName() + "执行了:----Advice AfterReturning----");
    }

	/*
	*目标对象抛出异常时执行,得到抛出的异常
	*/
    @AfterThrowing(pointcut = "pointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        Signature signature = joinPoint.getSignature();
        System.out.println(e);
        System.out.println(signature.getDeclaringTypeName()+"下的" + signature.getName() + "执行了:----Advice AfterThrowing----");
    }
	
	/*
	*目标对象执行完后执行
	*/
    @After("pointCut()")
    public void doAfter(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println(signature.getDeclaringTypeName()+"下的" + signature.getName() + "执行了:----Advice After----");
    }
}

执行结果:

com.websocket.controller.AopController下的aopDemo执行了:----Advice Before----
aopDemo Controller
com.websocket.controller.AopController下的aopDemo执行了:----Advice After----
AOP
com.websocket.controller.AopController下的aopDemo执行了:----Advice AfterReturning----

这样AOP的切面,切入点,连接点,通知,目标对象,代理(@Aspect已经集成了代理了)都用到了。
环绕通知:

@Around("pointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println(pjp.getTarget().getClass());
        return pjp.proceed();
    }
    结果:
class com.websocket.controller.AopController
com.websocket.controller.AopController下的aopDemo执行了:----Advice Before----
aopDemo Controller
com.websocket.controller.AopController下的aopDemo执行了:----Advice After----
AOP
com.websocket.controller.AopController下的aopDemo执行了:----Advice AfterReturning----

至此,Springboot使用AOP功能就完成了。
AOP的常用注解:
@Aspect 切面
@Before 通知前
@AfterReturning 通知返回后
@AfterThrowing 通知抛出异常后
@After 通知后
@Around 环绕通知

以上是个人对AOP的理解,不足之处,请指出,谢谢…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用SpringBoot AOP的步骤: 1. 首先,在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 2. 创建一个切面类,使用@Aspect注解标记该类,并在该类中定义切点和通知。 ```java @Aspect @Component public class MyAspect { @Pointcut("execution(* com.example.demo.service.*.*(..))") public void pointcut() {} @Before("pointcut()") public void before(JoinPoint joinPoint) { System.out.println("Before method: " + joinPoint.getSignature().getName()); } @After("pointcut()") public void after(JoinPoint joinPoint) { System.out.println("After method: " + joinPoint.getSignature().getName()); } } ``` 3. 在应用程序主类上添加@EnableAspectJAutoProxy注解,启用自动代理。 ```java @SpringBootApplication @EnableAspectJAutoProxy public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 4. 在需要使用AOP的类或方法上添加自定义注解,并在切面类中使用@Around注解来拦截该注解。 ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation {} @Around("@annotation(com.example.demo.aspect.MyAnnotation)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Before method: " + joinPoint.getSignature().getName()); Object result = joinPoint.proceed(); System.out.println("After method: " + joinPoint.getSignature().getName()); return result; } @Service public class MyService { @MyAnnotation public void doSomething() { System.out.println("Doing something..."); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值