前置通知(@Before)和后置通知(@After)有着一些非常明顯的限制,比如不使用類的成員變量的話,這些通知之間想實現信息共享是非常的困難。而使用成員變量的話,又容易出線程安全的問題。
所以就有環繞通知(@Around)。通過環繞通知,我們可以在一個方法內完成前置、后置、異常(@AfterThrowing)等通知所實現的功能。由於這些實現都是在同一個方法內,這樣就不需要通過類的成員變量來共享信息。
寫一個類 Hello:
@Component public class Hello { public void sayHello(){ System.out.println("Hello, this is @Around!"); } }
寫一個 Aop 的配置類 AopConfig:
@Component @Aspect // 必須的注解 public class AopConfig { // 聲明切點 @Pointcut("execution(* com.san.spring.aop.Hello.*(..))") public void pointcut() { } // 定義環繞通知方法 // 方法必須接受 ProceedingJoinPoint 為參數,因為要通過它來調用被通知的方法。 // 我們可以在方法中執行其他操作。當需要執行被通知的方法時,就調用 ProceedingJoinPoint 的 proceed()。 @Around("pointcut()") public void around(ProceedingJoinPoint pjp){ int count = 0; try { System.out.println("count = " + count++); // 相當於@Before System.out.println("count = " + count++); // 相當於@Before pjp.proceed(); // 通過調用此方法來執行被通知的方法 System.out.println("count = " + count++); // 相當於@After } catch (Throwable throwable) { // 相當於@AfterThrowing throwable.printStackTrace(); } } }
寫一個 SpringConfig 配置類:
@Configuration @ComponentScan @EnableAspectJAutoProxy // 必須的注解 public class SpringConfig { }
最后寫一個 Test 進行測試:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfig.class) public class AroundTest { @Autowired private Hello hello; @Test public void testAround(){ hello.sayHello(); } }