최근 많은 분들을 대상으로 이력서 수정 및 모의면접을 하던 중 몇몇 친구들이 Spring AOP 면접 질문에 대한 피드백을 줬는데, 오늘 물어보겠습니다.
처음에 Spring의 가장 강력한 점은 IOC/AOP의 두 가지 핵심 기능입니다. 오늘은 Spring AOP의 공통 주석과 실행 순서에 대해 알아 보겠습니다.
Spring 인터뷰 핵심 포인트:
IOC, AOP, Bean 주입, Bean 수명 주기, Bean 순환 종속성
먼저 Spring Aop에서 일반적으로 사용되는 몇 가지 주석을 검토해 보겠습니다.
@Before
前置通知:目标方法之前执行@After
后置通知:目标方法之后执行(始终执行)@AfterReturning
返回之后通知:执行方法结束之前执行(异常不执行)@AfterThrowing
异常通知:出香异常后执行@Around
@After
게시물 알림 : 실행됨 대상 메소드 이후(항상 실행됨) @ AfterReturning
반환 후 알림: 실행 메서드가 끝나기 전에 실행됨(예외는 실행되지 않음) @AfterThrowing
예외 알림: 향 예외 이후 실행
@Around
Around 알림: Surround 대상 메서드 실행🎜🎜🎜🎜🎜🎜FAQ🎜🎜🎜 🎜🎜🎜1. 꼭 알아두셔야 할 점 Spring, Aop의 모든 알림 순서에 대해 이야기해 보겠습니다. Spring Boot 또는 Spring Boot 2는 Aop의 실행 순서에 어떤 영향을 줍니까? 🎜🎜2. AOP에서 겪은 함정에 대해 알려주세요. 🎜Spring AOP에 대한 몇 가지 세부 사항을 논의하기 위해 Spring AOP 데모 프로그램을 빠르게 구축해 보겠습니다.
빠른 프로젝트 구축을 위해 spring-boot를 직접 활용하기 쉽도록 아이디어의 spring-boot 프로젝트 빠른 생성 기능을 이용하거나 에 들어가시면 됩니다. ="글꼴 크기: 14px; 패딩: 2px 4px; 테두리 반경: 4px; 여백 오른쪽: 2px; 여백 왼쪽: 2px; 배경 색상: rgba(27, 31, 35, 0.05); 글꼴 계열: "Operator Mono" , Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">start.spring.io 위의 스프링- 부팅 응용 프로그램. start.spring.io
上面去快速创建spring-boot 应用。
因为本人经常手动去网上贴一些依赖导致,依赖冲突服务启动失败等一些问题。
plugins { id 'org.springframework.boot' version '2.6.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group 'io.zhengsh' version '1.0-SNAPSHOT' repositories { mavenCentral() maven { url 'https://repo.spring.io/milestone' } maven { url 'https://repo.spring.io/snapshot' } } dependencies { # 其实这里也可以不增加 web 配置,为了试验简单,大家请忽略 implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-aop' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
首先我们需要定义一个接口。我们这里可以再来回顾一下 JDK 的默认代理实现的选择:
这块的逻辑在 DefaultAopProxyFactory
몇 가지 종속성을 온라인에 수동으로 게시하는 경우가 많기 때문에 종속성 충돌이 발생합니다. 서비스 시작 실패와 같은 일부 문제.
public interface CalcService { public int div(int x, int y); }
먼저 인터페이스를 정의해야 합니다. 여기에서 JDK의 기본 프록시 구현 선택을 검토할 수 있습니다.
@Aspect @Component public class MyAspect { @Pointcut("execution(* io.zhengsh.spring.service.impl..*.*(..))") public void divPointCut() { } @Before("divPointCut()") public void beforeNotify() { System.out.println("----===>> @Before 我是前置通知"); } @After("divPointCut") public void afterNotify() { System.out.println("----===>> @After 我是后置通知"); } @AfterReturning("divPointCut") public void afterReturningNotify() { System.out.println("----===>> @AfterReturning 我是前置通知"); } @AfterThrowing("divPointCut") public void afterThrowingNotify() { System.out.println("----===>> @AfterThrowing 我是异常通知"); } @Around("divPointCut") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object retVal; System.out.println("----===>> @Around 环绕通知之前 AAA"); retVal = proceedingJoinPoint.proceed(); System.out.println("----===>> @Around 环绕通知之后 BBB"); return retVal; } }🎜🎜🎜aop Interceptor🎜🎜🎜🎜인터셉터를 선언하고 현재 객체에 @Aspect와 @Component를 추가해야 합니다. 작성자는 이전에 그런 구덩이를 밟았을 뿐이고 하나만 추가했습니다. 🎜
其实这块我刚开始也不是很理解,但是我看了 Aspect 注解的定义我就清楚了
这里面根本就没有 Bean 的定义。所以我们还是乖乖的加上两个注解。
还有就是如果当测试的时候需要开启Aop 的支持为配置类上增加@EnableAspectJAutoProxy
注解。
其实 Aop 使用就三个步骤:
@Aspect @Component public class MyAspect { @Pointcut("execution(* io.zhengsh.spring.service.impl..*.*(..))") public void divPointCut() { } @Before("divPointCut()") public void beforeNotify() { System.out.println("----===>> @Before 我是前置通知"); } @After("divPointCut") public void afterNotify() { System.out.println("----===>> @After 我是后置通知"); } @AfterReturning("divPointCut") public void afterReturningNotify() { System.out.println("----===>> @AfterReturning 我是前置通知"); } @AfterThrowing("divPointCut") public void afterThrowingNotify() { System.out.println("----===>> @AfterThrowing 我是异常通知"); } @Around("divPointCut") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object retVal; System.out.println("----===>> @Around 环绕通知之前 AAA"); retVal = proceedingJoinPoint.proceed(); System.out.println("----===>> @Around 环绕通知之后 BBB"); return retVal; } }
其实我这个测试类,虽然用了 @Test 注解,但是我这个类更加像一个 main 方法把:如下所示:
结果记录:spring 4.x, spring-boot 1.5.9
无法现在依赖,所以无法试验
我直接说一下结论:Spring 4 中环绕通知是在最里面执行的
结果记录:spring 版本5.3.15 springboot 版本2.6.3
多个切面的情况下,可以通过@Order指定先后顺序,数字越小,优先级越高。如下图所示:
下面一种场景会导致 aop 代理失效,因为我们在执行 a 方法的时候其实本质是执行 AServer#a
的方法拦截器(MethodInterceptor
)链, 当我们在 a 方法内直接执行b(), 其实本质就相当于 this.b() , 这个时候由执行 a方法是调用到 a 的原始对象相当于是 this 调用,那么会导致 b() 方法的代理失效。这个问题也是我们开发者在开发过程中最常遇到的一个问题。
@Service public class AService { public void a() { System.out.println("...... a"); b(); } public void b() { System.out.println("...... b"); } }
위 내용은 인터뷰어: Spring Aop 공통 주석 및 실행 순서의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!