前置通知(@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(); } }