How to?
Guice提供了MethodInterceptor的功能,讓你可以做Method的前置處理。有以下幾個步驟:
- 需要aopalliance.jar。
- 建立對應處理的Annotation。
- 建立處理的Interceptor。
- 透過Module將Annotation與Interceptor做連結,並指定作用類別。
- 透過Injector取得提供服務的Instance。
我們以刷卡服務做為範例,在扣款前我們會先確認信用卡內容是否正確。以往我們會把檢查動作寫在charge的method最前面,但透過AOP可以讓我們把這動作變得可以重複使用。在這我宣告了ValidCreditCard的Annotation做註記。
public class BillingService implements IBillingService { @Override @ValidCreditCard public IChargeResult charge(String amount, CreditCard creditCard) { return null; } }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ValidCreditCard { }
接著實做MethodInterceptor介面的類別CreditCardInterceptor,用以確認信用卡資料是否正確。主要重點是,我們可以透過MethodInvocation參數去得被呼叫method的參數,然後再去做我們想做的事情。
public class CreditCardInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation arg0) throws Throwable { CreditCard creditCard = getCreditCardArgument(arg0.getArguments()); verify(creditCard); return arg0.proceed(); } ... }
接著實做Module類別,以做Annotation與對應Interceptor綁定。bindInterceptor第一個參數可以設定你希望有此功能的類別有哪些,第二個參數則是對應Annotation,第三個參數是處理的Interceptor。
public class BillingModule extends AbstractModule { @Override protected void configure() { bindInterceptor(Matchers.any(), Matchers.annotatedWith(ValidCreditCard.class), new CreditCardInterceptor()); } }
測試程式可以這樣寫:
public class BillingClient { public static void main(String[] args) { Injector injector = Guice.createInjector(new BillingModule()); BillingService billingService = injector.getInstance(BillingService.class); billingService.charge("1000", new CreditCard("1234-5678-6666-0001-5555")); try { billingService.charge("1000", new CreditCard("1234-5678-6666-0001")); } catch( Throwable e ){ e.printStackTrace(); } } }
留言
張貼留言