-
添加 @Aspect注解,代表一个类是一个切面
示例
@Aspect public class Audience { ... }
-
通知的时刻有5种,详见"基本概念.md"
示例
@Aspect public class AroundAudience { @Around("execution(* com.springinaction.springidol.performance.Performance.perform())") public void watchPerformance(ProceedingJoinPoint joinpoint) { try { System.out.println("Now we use around aspectOfJavaConfig."); System.out.println("The audience is taking their seats."); System.out.println("The audience is turning off their cellphones"); long start = System.currentTimeMillis(); joinpoint.proceed(); long end = System.currentTimeMillis(); System.out.println("CLAP CLAP CLAP CLAP CLAP"); System.out.println("The performance took " + (end - start) + " milliseconds."); } catch (Throwable t) { System.out.println("Boo! We want our money back!"); } } }
具体的操作是在方法上方插入@Before(..), @AfterReturning(..), @AfterThrowing(..),@After(..),@Around(..)注解,注解中包括AspectJ切点表达式,切点表达式中必须要包含的是 execution
-
启用自动代理功能
(1) 必须启用自动代理,否则 @Aspect注解不会被解析
(2) 使用JavaConfig的话,可以添加 @EnableAspectJAutoProxy 注解启用自动代理
示例
@Configuration @EnableAspectJAutoProxy public class AroundAspectConfig { @Bean public AroundAudience aroundAudience() { return new AroundAudience(); } @Bean public Performance performance() { return new MagicPerformance(); } }
-
环绕通知 @Around
(1) 它是另外四种通知的集合,可以实现另外四种通知的功能
(2) 它对应的函数接收 ProceedingJoinPoint类型的对象,这个对象是必须的。 joinpoint.proceed(); 代表执行被通知的方法,也可以获取返回值
(3) 也可以不调用 joinpoint.proceed()方法实现阻塞效果;也可以在通知中多次进行joinpoint.proceed()调用
-
处理通知中的参数
(1) 示例
CompactDisc.java
package com.springinaction.springidol.TrackCounter; public interface CompactDisc { void play(); void playTrack(int index, String artist); }
TrackCounter.java
package com.springinaction.springidol.TrackCounter; @Aspect public class TrackCounter { private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>(); private Map<Integer, String> artistName = new HashMap<Integer, String>(); @Before("execution(* com.springinaction.springidol.TrackCounter.CompactDisc.playTrack(int, String)) && args(trackNumber, artist)") public void countTrack(int trackNumber, String artist) { int currentCount = trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0; trackCounts.put(trackNumber, currentCount + 1); artistName.put(trackNumber, artist); } public int getPlayCount(int trackNumber) { return (trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0); } public String getArtistName(int trackNumber) { return artistName.get(trackNumber); } }
(2) 说明
args()用于指定要提供给通知方法的参数;中间用,隔开;参数名称要匹配
(3) 通知方法必须是具体的实现类,不能是接口。接口的情况目前还没试验成功过
网友评论