Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. Spring AOP – Part 2 Advanced Aspect-Oriented Programming
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 2 Spring’s Advice Interfaces (1) Spring provides interfaces that can be used to implement advice. The advice can then be added either: –Programmatically with the ProxyFactory –Declaratively with a ProxyFactoryBean Prior to Spring 2.0, this was the most common way to introduce custom AOP The namespace-based and annotation-driven approaches make use of these interfaces internally.
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 3 Spring’s Advice Interfaces (2) Before implement MethodBeforeAdvice: void before(Method method, Object[] args, Object target) throws Throwable;
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 4 Spring’s Advice Interfaces (3) After implement AfterReturningAdvice: void afterReturning(Object retval, Method method, Object[] args, Object target) throws Throwable;
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 5 Spring’s Advice Interfaces (4) After Throwing implement ThrowsAdvice : NO REQUIRED METHODS TO IMPLEMENT 2 options: public void afterThrowing(Method method, Object[] args, Object target, MyException e) {..} OR… public void afterThrowing(MyException e) {..}
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 6 Spring’s Advice Interfaces (5) Around implement org.aopalliance.intercept.MethodInterceptor: public abstract Object invoke(MethodInvocation invocation) throws Throwable;
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 7 Using Advice with the ProxyFactory private MessageService getMessageService(List obscenities) { MessageService target = new MessageServiceImpl(); ProxyFactory pf = new ProxyFactory(target); pf.addAdvice(new ObscenityFilterAdvice(obscenities)); return (MessageService) pf.getProxy(); } Create the ProxyFactory This version of the ObscenityFilterAdvice would implement the MethodBeforeAdvice interface Create and return the proxy
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 8 Invoking Advice via ProxyFactoryBean <bean id="target" class="com.springsource.training.aop.MessageServiceImpl"/> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> com.springsource.training.aop.MessageService advice <bean id="advice" class="com.springsource.training.aop.after.ReturnCheckingAdvice "/> Specify the advice to add to the proxy Specify the interface(s) the proxy should implement Specify the target
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 9 Out of the Box Interceptors You may not need to implement AOP advice yourself Spring provides interceptors out of the box for –Transaction management –Accessing remote resources –Accessing JMX resources Rich potential for aspect libraries –Spring is a key part of this effort
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 10 Understanding Introductions Introductions allow you to add new behavior to a bean dynamically at runtime –In Spring AOP, this means making objects implement additional interfaces Allows more complex cross-cutting logic to be applied –Locking –Modification checking Mixin –Essentially a more dynamic form of concrete inheritance –Typically adds state to target on a per-instance basis Inter-type declarations –Another name for introductions –Preferred by AspectJ community
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 11 Modification Detection with Introductions (1) Create a ModificationTracker interface: public interface ModificationTracker { public boolean isModified(); public void setModified(boolean modified); }
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 12 Modification Detection with Introductions (2) Create an implementation: –The state and behavior behind the interface public class DefaultModificationTracker implements ModificationTracker { private boolean isModified; public boolean isModified() { return isModified; } public void setModified(boolean modified) { this.isModified = modified; }
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 13 Modification Detection with Introductions (3) Use to wrap Contact s with proxy which implements ModificationTracker : <aop:declare-parents types-matching="com.springsource.training.aop.introductions.Contact+" implement-interface="com.springsource.training.aop.introductions.ModificationTracker" default-impl="com.springsource.training.aop.introductions.DefaultModificationTracker"/> Apply to any implementation of the Contact interface
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 14 Modification Detection with Introductions (4) Create around advice to use new interface : public class ModificationTrackingIntroduction { public void trackModifications( ProceedingJoinPoint pjp, ModificationTracker mixin) throws Throwable { boolean modified = mixin.isModified() || hasModification(pjp.getSignature().getName(), pjp.getTarget(), pjp.getArgs()); mixin.setModified(modified); pjp.proceed(); … Remember to call proceed()
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 15 Modification Detection with Introductions (5) Apply around advice: <aop:declare-parents types-matching="com.springsource.training.aop.introductions.Contact+" implement-interface="com.springsource.training.aop.introductions.ModificationTracker" default-impl="com.springsource.training.aop.introductions.DefaultModificationTracker"/> <aop:around method="trackModifications" pointcut="execution(void set*(*)) and this(mixin)"/> Pointcut expression matches setter methods
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. Demo Modification Detection with Introductions
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 17 Key configuration options Key configuration options for Spring proxies, inherited from the ProxyConfig class. Apply to auto proxy creators as well as ProxyFactoryBean and conveniences such as TransactionProxyFactoryBean NameMeaning proxyTargetClass Proxy interfaces or create a subclass to proxy class and any interfaces exposeProxyBind the proxy to the thread to allow invocation against it opaquePrevent casting to Advised frozenPrevent changing advice chain at runtime
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 18 Interceptor and proxy lifecycle Can advise singletons or prototypes (in Spring IoC terminology) Each advice can be a singleton (shared) or prototype (per-instance) Can mix shared and per-instance advice Shared advice is most common –Most enterprise advice is stateless, such as transaction advice Prototype advice will only make a difference if you advise several singletons or advise a prototype
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 19 A note on self-invocation Consequences of having distinct proxies and targets –If a target returns this, the proxy wraps it automatically –If a target wants to invoke itself but with advice applying, it’s necessary to 1.Set exposeProxy config property to true 2.Invoke result of AopContext.currentProxy() –Similar to getEJBObject()
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 20 Interrogating and changing proxy state By default, objects advised by Spring AOP can be cast to the Advised interface –Advised a = (Advised) myProxy; Can query advice chain toProxyConfigString() returns useful diagnostic information Can even add or remove advisors –Useful in tests, but questionable in a deployed application Try casting to Advised in the labs!
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 21 Other dynamic runtime behavior enabled by AOP Spring AOP is also used to enable Spring to deliver hot swapping and pooling support with no need to modify Java code Done through ability to define a TargetSource, enabling target to be changed at runtime, to be taken from a pool etc. –TargetSource is used to obtain the joinpoint instance for each invocation The default TargetSource used is SingletonTargetSource, with a static target In some cases there will be no target –Terminal interceptor does all the work Example: Calling out to a remote object in Spring proxy implementations
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. (1) It is possible to apply dependency injection to objects that are not explicitly managed by the Spring IOC container. For example, calling new() to construct a domain instance as opposed to using getBean(..) to retrieve a prototype bean. An aspect from spring-aspects.jar makes this possible. Enable weaving by setting the – javaagent VM arg with the full path to aspectjweaver.jar
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. public class WeatherMonitor { private String location; private WeatherService weatherService; public WeatherMonitor(String location) { this.location = location; } public void setWeatherService(WeatherService) { this.weatherService = weatherService; } public String getWeatherReport { return weatherService.getCurrentSummary(location); }
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. (3) <bean class="com.i21.WeatherMonitor" scope="prototype"> <property name="weatherService" ref="weatherService"/> <bean id="weatherService" class="com.i21.StubWeatherService"/> Class whose instances require Dependency Injection Scope must be prototype DI as usual
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. (4) public static void main(String[] args) { new ClassPathXmlApplicationContext(“beans.xml”); WeatherMonitor monitor = new WeatherMonitor("Chicago"); System.out.println(monitor.getWeatherReport()); } public String getWeatherReport() { return weatherService.getCurrentSummary(location); } weatherService property was provided via dependency injection
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. (5) By enabling DI for fine-grained promotes a rich domain model. It is a much better approach than the Singleton anti- pattern. For unit testing, simply run without the AspectJ weaver. will have no effect –Set dependencies programmatically –Use mocks and/or stubs as needed
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 28 AspectJ Integration (1) AspectJ is a programming language –Compiles classes + aspects to bytecode or link (weave) aspects with existing.class files –No proxies are used –No distinction between target and proxy –Cannot apply different advice to same class Comprehensive join point model –Method call/execution –Field read/write –Object initialization –Static initialization
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 29 AspectJ Integration (2) AspectJ itself has no DI capabilities Spring adds DI to AspectJ –Currently only for singleton aspects for non-singletons Configuring AspectJ aspects in Spring is just like configuring Spring aspects
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 30 Using Spring and AspectJ (1) Consider the following business object: public class Account { private int balance; private int overdraft; public int withdraw(int amount) throws InsufficientFundsException { int newBalance = balance - amount; if (newBalance < -overdraft) { throw new InsufficientFundsException(); } balance = newBalance; return balance; } public int deposit(int amount) { balance += amount; return balance; } /* getters and setters omitted */ }
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 31 Using Spring and AspectJ (2) Now consider this AspectJ aspect: public aspect SecurityManagerAspect { private SecurityManager securityManager; public void setSecurityManager(SecurityManager securityManager) { this.securityManager = securityManager; } private pointcut balanceChange() : set(int Account.balance); before() : balanceChange() { this.securityManager.checkCanModify(); } Before modifying the balance field, use the SecurityManager to authorise the action Define a pointcut for setting the balance field of the Account class Standard JavaBeans setter
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 32 Using Spring and AspectJ (3) SecurityManager is a standard Java interface: public interface SecurityManager { void checkCanModify(); } We have a stub implementation: public class StubSecurityManager implements SecurityManager { public void checkCanModify() { System.err.println("Checking security"); }
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 33 Using Spring and AspectJ (4) Configure the aspect in Spring: <bean id="securityManager" class="...aop.aspectj.StubSecurityManager"/> <bean id="securityAspect" class="...aop.aspectj.SecurityManagerAspect" factory-method="aspectOf"> Inject the SecurityManager Retrieve the aspect instance Configure the SecurityManager
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. Demo Integrating with AspectJ
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 35 Summary (1) Spring supports a limited core of AOP –Interceptor based approach –Extensive integration with AspectJ if needed –Can reuse AOP Alliance aspects Spring provides important prepackaged aspects. This allows you to take advantage of AOP without having to know much about it –Transactions –Security –Remoting –And others Can gradually start adding in custom AOP as desired
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 36 Summary (2) Spring AOP supports method execution join points and the standard advice types: around, before, after-returning, after-throwing, after Spring AOP supports introductions –Make proxy implement additional interfaces beyond those implemented by target class Spring AOP offers several ways to create a proxy: –XML-based configuration with the AOP namespace. –Annotation-based style configuration. –For an individual bean (or pre-Spring 2.0), use ProxyFactory of ProxyFactoryBean
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 37 Summary (3) Spring 2.0+ enables important AspectJ features at runtime within the Spring AOP proxy-based model (and without the ajc compiler): –AspectJ pointcut expression language annotation-based annotation used by an AspectJ aspect to enable dependency injection for objects not instantiated by a Spring container. Combines ease-of-adoption of Spring AOP with de facto standard of AspectJ