Author: limpbizkit Date: Fri Jun 19 01:04:42 2009 New Revision: 1018 Modified: wiki/AOP.wiki
Log: Edited wiki page through web user interface. Modified: wiki/AOP.wiki ============================================================================== --- wiki/AOP.wiki (original) +++ wiki/AOP.wiki Fri Jun 19 01:04:42 2009 @@ -8,14 +8,66 @@ [http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInterceptor.html MethodInterceptors] are executed whenever a matching method is invoked. They have the opportunity to inspect the call: the method, its arguments, and the receiving instance. They can perform their cross-cutting logic and then delegate to the underlying method. Finally, they may inspect the return value or exception and return. Since interceptors may be applied to many methods and will receive many calls, the intercepting method should be efficient and unintrusive. -==Example: Forbidding a method during weekends== - -We'll define an interceptor that forbids code from running on weekends. - - - - -AOP alliance -Injecting interceptors +==Example: Forbidding method calls on weekends== +To illustrate how method interceptors work with Guice, we'll forbid calls to our pizza billing system on weekends. The delivery guys only work Monday thru Friday so we'll prevent pizza from being ordered when it can't be delivered! This example is structurally similar to use of AOP for authorization. +To mark select methods as weekdays-only, we define an annotation: +{{{ +...@retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) +...@interface NotOnWeekends {} +}}} +...and apply it to the methods that need to be intercepted: +{{{ +public class RealBillingService implements BillingService { + + @NotOnWeekends + public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) { + ... + } +} +}}} +Next, we define the interceptor by implementing the `org.aopalliance.intercept.MethodInterceptor` interface. When we need to call through to the underlying method, we do so by calling `invocation.proceed()`: +{{{ +public class WeekendBlocker implements MethodInterceptor { + public Object invoke(MethodInvocation invocation) throws Throwable { + Calendar today = new GregorianCalendar(); + if (today.getDisplayName(DAY_OF_WEEK, LONG, ENGLISH).startsWith("S")) { + throw new IllegalStateException( + invocation.getMethod().getName() + " not allowed on weekends!"); + } + return invocation.proceed(); + } +} +}}} +Finally, we configure everything. This is where we create matchers for the classes and methods to be intercepted. In this case we match any class, but only the methods with our `...@notonweekends` annotation: +{{{ +public class NotOnWeekendsModule extends AbstractModule { + protected void configure() { + bindInterceptor(Matchers.any(), Matchers.annotatedWith(NotOnWeekends.class), + new WeekendBlocker()); + } +} +}}} +Putting it all together, (and waiting until Saturday), we see the method is intercepted and our order is rejected: +{{{ +Exception in thread "main" java.lang.IllegalStateException: chargeOrder not allowed on weekends! + at com.publicobject.pizza.WeekendBlocker.invoke(WeekendBlocker.java:65) + at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64) + at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:44) + at com.publicobject.pizza.RealBillingService$$EnhancerByGuice$$49ed77ce.chargeOrder(<generated>) + at com.publicobject.pizza.WeekendExample.main(WeekendExample.java:47)}}} +}}} + +==Limitations== +Behind the scenes, method interception is implemented by generating bytecode at runtime. Guice dynamically creates a subclass that applies interceptors by overriding methods. If you are on a platform that doesn't support bytecode generation (such as Android), you should use [OptionalAOP Guice without AOP support]. + +This approach imposes limits on what can be interception: + * Classes must be public or package-private. + * Classes must be non-final + * Methods must be public, package-private or protected + * Methods must be non-final + * Instances must be created by Guice by an `...@inject`-annotated or no-argument constructor +It is not possible to use method interception on instances that aren't constructed by Guice. +==AOP Alliance== +The method interceptor API implemented by Guice is a part of a public specification called [http://aopalliance.sourceforge.net/ AOP Alliance]. This makes it possible to use the same interceptors across a variety of other frameworks. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "google-guice-dev" group. To post to this group, send email to google-guice-dev@googlegroups.com To unsubscribe from this group, send email to google-guice-dev+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/google-guice-dev?hl=en -~----------~----~----~----~------~----~------~--~---