1 / 37

Spring AOP – Part 2

Spring AOP – Part 2. Advanced Aspect-Oriented Programming. 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

tameka
Télécharger la présentation

Spring AOP – Part 2

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Spring AOP – Part 2 Advanced Aspect-Oriented Programming

  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.

  3. Spring’s Advice Interfaces (2) • Before implement MethodBeforeAdvice: void before(Method method, Object[] args, Object target) throws Throwable;

  4. Spring’s Advice Interfaces (3) • After implement AfterReturningAdvice: void afterReturning(Object retval, Method method, Object[] args, Object target) throws Throwable;

  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) {..}

  6. Spring’s Advice Interfaces (5) • Around implement org.aopalliance.intercept.MethodInterceptor: public abstract Object invoke(MethodInvocation invocation) throws Throwable;

  7. Using Advice with the ProxyFactory Create 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 and return the proxy This version of the ObscenityFilterAdvice would implement the MethodBeforeAdvice interface

  8. Invoking Advice via ProxyFactoryBean Specify the target <bean id="target" class="com.springsource.training.aop.MessageServiceImpl"/> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target“ ref=“target”/> <property name="proxyInterfaces"> <value>com.springsource.training.aop.MessageService</value> </property> <property name="interceptorNames"> <value>advice</value> </property> </bean> <bean id="advice" class="com.springsource.training.aop.after.ReturnCheckingAdvice"/> Specify the interface(s) the proxy should implement Specify the advice to add to the proxy

  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

  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

  11. Modification Detection with Introductions (1) • Create a ModificationTracker interface: public interface ModificationTracker { public boolean isModified(); public void setModified(boolean modified); }

  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; } }

  13. Modification Detection with Introductions (3) • Use <aop:declare-parents> to wrap Contacts with proxy which implements ModificationTracker: <aop:config> <aop:aspect id="introductionsExample"> <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:config> <bean id="contact" class="com.springsource.training.aop.introductions.SimpleContact"> <property name="firstName" value="Ben"/> <property name="lastName" value="Hale"/> </bean> Apply to any implementation of the Contact interface

  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 callproceed()

  15. Modification Detection with Introductions (5) • Apply around advice: <bean id="introduction" class="com.springsource.training.aop.introductions.ModificationTrackingIntroduction"/> <aop:config> <aop:aspect id="introductionsExample" ref="introduction"> <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)"/> </aop:aspect> </aop:config> <bean id="contact" class="com.springsource.training.aop.introductions.SimpleContact"> <property name="firstName" value="Ben"/> <property name="lastName" value="Hale"/> </bean> Pointcut expression matches setter methods

  16. Demo Modification Detection with Introductions

  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

  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

  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 • Set exposeProxy config property to true • Invoke result of AopContext.currentProxy() • Similar to getEJBObject()

  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!

  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

  22. @Configurable (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

  23. @Configurable (2) @Configurable publicclass WeatherMonitor { private String location; private WeatherService weatherService; public WeatherMonitor(String location) { this.location = location; } publicvoid setWeatherService(WeatherService) { this.weatherService = weatherService; } public String getWeatherReport { return weatherService.getCurrentSummary(location); }

  24. @Configurable (3) Class whose instances require Dependency Injection <aop:spring-configured/> <bean class="com.i21.WeatherMonitor" scope="prototype"> <property name="weatherService" ref="weatherService"/> </bean> <bean id="weatherService" class="com.i21.StubWeatherService"/> Scope must be prototype DI as usual

  25. @Configurable (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

  26. @Configurable (5) • By enabling DI for fine-grained instances, @Configurable 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. • @Configurable will have no effect • Set dependencies programmatically • Use mocks and/or stubs as needed

  27. Demo @Configurable

  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

  29. AspectJ Integration (2) • AspectJ itself has no DI capabilities • Spring adds DI to AspectJ • Currently only for singleton aspects • Use @Configurable for non-singletons • Configuring AspectJ aspects in Spring is just like configuring Spring aspects

  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 */ }

  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(); } } Standard JavaBeans setter Define a pointcut for setting the balance field of the Account class Before modifying the balance field, use the SecurityManager to authorise the action

  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"); } }

  33. Using Spring and AspectJ (4) • Configure the aspect in Spring: <beans> <bean id="securityManager" class="...aop.aspectj.StubSecurityManager"/> <bean id="securityAspect" class="...aop.aspectj.SecurityManagerAspect" factory-method="aspectOf"> <property name="securityManager"> <ref local="securityManager"/> </property> </bean> </beans> Configure the SecurityManager Retrieve the aspect instance Inject the SecurityManager

  34. Demo Integrating with AspectJ

  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

  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 with @AspectJ style configuration. • For an individual bean (or pre-Spring 2.0), use ProxyFactory of ProxyFactoryBean

  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 • @AspectJ annotation-based syntax • @Configurable 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

More Related