Spring A Op

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Spring A Op as PDF for free.

More details

  • Words: 3,267
  • Pages: 12
Spring: A Quick Journey Through Spring AOP One of the strengths of the Spring Framework is its robust and flexible aspect oriented programming infrastructure. In Spring, AOP is a little different than other AOP frameworks in that it brings with it a consistent AOP infrastructure that can be applied for other AOP technical solutions. Out of the gate, Spring supports dynamic-proxy-based AOP, and CGLib-based AOP. Both of these have their limitations, but can honestly be used in a very large majority of cases. Spring does have integration support with AspectJ as well, however, so don't worry. Thankfully, the AspectJ integration is not drastically different from the regular AOP, which I think shows some of the strengths of Spring's AOP infrastructure; even an AOP library as different as AspectJ can still be integrated. General Education Spring's 'built-in' AOP infrastructure is defined by the org.springframework.aop.* packages. To understand the packages, you have to have at least some idea of the concepts of AOP as Spring models these concepts *very* closely in implementation, so I'll explain them. Now... every article I read on AOP seems to just try to confuse me - and the vocabulary around AOP even makes it worse. I'm going to do my best to describe things as simply as possible, so bear with me: •







• •

Aspect - Think of this as the general feature you want to apply globally to your application (logging, performance monitoring, exception handling, transaction management, etc). Advice - A chunk of code that is invoked during program execution, and is a piece of the logic for implementing your aspect. This is the first important piece of a Spring AOP aspect implementation! I like to compare advice implementations to the decorator pattern. While an advice doesn't necessarily wrap an entire object in concept, it has the same general effect. We'll learn in a bit that how that advice is applied is more granular/formal than typically defined in the decorator pattern however. Joinpoint - A *single* location in the code where an advice should be executed (such as field access, method invocation , constructor invocation, etc.). Spring's built-in AOP only supports method invocation currently, so joinpoints aren't particularly important to focus on at this point. Pointcut - A pointcut is a set of many joinpoints where an advice should be executed. So if, in Spring, a joinpoint is always a method invocation, then a pointcut is just a set of methods that, when called, should have advices invoked around them. This is the second important pieces of a Spring AOP aspect implementation! Targets/Target Objects - The objects you want to apply an aspect or set of aspects to! Introduction - This is the ability to add methods to an object. This is closely tied to, and is almost analogous to the term 'mixins'. It's really just a way to make an object of type A also an object of type B. Introduction in Spring is limited to interfaces.

Spring and Advice Objects I like to start with the concept of advice objects, because they are the easiest to bridge to from a non-AOP way of thinking, because an advice is really very similar to a decorator (as I mentioned above). Advice implementations in Spring are simply implementations of the org.aopalliance.intercept.MethodInterceptor interface. Woah! Wait a minute - that's not a Spring class! Nope - it turns out that Spring's AOP implementation uses a *standard* AOP API from the AOP Alliance, which you can read more about here . The MethodInterceptor interface is actually a child of the org.aopalliance.intercept.Interceptor interface, which is a child of another interface, org.aopalliance.aop.Advice - Whew!. Remember that I said Spring AOP only supports method invocation, but that conceptually, an advice could include field access, constructor invocation and a bunch of other things. That is why Spring's advice starts at the MethodInterceptor interface, even though there are other interfaces higher up - because MethodInterceptor is the sub-interface that is designed for methodinvocation style advice and for which Spring has support. The MethodInterceptor interface is really quite simple: public interface MethodInterceptor extends Interceptor { Object invoke(MethodInvocation invocation) throws Throwable; }

Basically, when you write an advice for intercepting a method, you have to implement one method - the invoke method, and you are given a MethodInvocation object to work with. The MethodInvocation object tells us a bunch of stuff about the method that we're intercepting, and also gives a hook to tell the method to go ahead and run. Let's jump right in and look at a (very) basic method performance profiling advice: import org.aopalliance.intercept.*; public class PerformanceInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation method) throws Throwable { long start = System.currentTimeMillis(); try { Object result = method.proceed(); return result; } finally { long end = System.currentTimeMillis(); long timeMs = end - start; System.out.println("Method: " + method.toString() + " took: " + timeMs +"ms."); } } }

Not too complicated really - just capture the time before the method invocation, tell the method to go ahead and run, then afterward capture the time again, calculate the

difference, and print it out. Incidentally, Spring already has a better implementation of this type of interceptor - the org.springframework.aop.interceptor.PerformanceMonitorInterceptor - there are actually quite a few useful concrete interceptor implementations in there - check it out. Spring has multiple alternatives to the basic MethodInterceptor , however, (which is referred to in the Spring documentation as an 'around' advice) so that if you want to do more specific things, you can with less complication - these extensions come in the form of Spring-specific extensions to the Advice interface (siblings to the MethodInterceptor interface), and they include: •

org.springframework.aop.MethodBeforeAdvice - Implementations of this interface have to implement this contract:



void before(Method method, Object[] args, Object target) throws Throwable;

You'll notice in this case you aren't given the MethodInvocation object, just the underlying Method object - this is because the call to proceed() will be handled by Spring for you; all you need to do is do what you need *before* the method is called (as the interface name implies).



org.springframework.aop.AfterReturningAdvice - This is the pong to the ping of MethodBeforeAdvice . This interface's method will be called on the return from the invocation of a method. The contract looks like this:



void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;

You'll notice it looks a whole like the before advice, but simply adds the Object's return value to the method arguments.



org.springframework.aop.ThrowsAdvice - This is a strange implementation. Instead of requiring you to implement a particular contract, this is simply a 'marker' interface, and expects you to implement any number of methods that look like this:



void afterThrowing([Method], [args], [target], [some type of throwable] subclass)

Oddly enough, the only mandatory argument is the Throwable sub-type. Here is a snapshot that generally covers the 'advice' hierarchy:

That's a primer on advice objects. Not too bad so far, right? If you've ever worked with in reflection in Java, most of this is fairly similar in style. Spring and Pointcuts What seperates AOP from object-oriented design patterns such as the decorator pattern, at least when talking about Spring AOP, is the fact that the *what* is defined seperately from the *where* (or would it be *whom*?). In other words, the 'advice', which is the code to be invoked, is disconnected entirely from the particular item it is 'advising' which, again, in the Spring case is always a method. In other words, an advice in Spring doesn't have any association, type binding, dependency, or any other form of direct awareness of the method it is working with. Remember that the thing that an advice works with is called a JoinPoint . Our join points in Spring are always methods, and at runtime resolve to org.aopalliance.aop.Method objects which have made appearances as method arguments to our advices above. To solidify the point, org.aopalliance.aop.Method extends org.aopalliance.aop.JoinPoint . The reason I am bringing joinpoints back up is because a Pointcut object is all about defining all of the joinpoints that an advice should be 'applied to'. In Spring terms, a pointcut defines all of the methods that our interceptor should intercept. Pointcuts in Spring implement the org.springframework.aop.Pointcut interface and look something like this: package org.springframework.aop;

public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher(); }

The class filter is a special type of object that describes which classes have potential joinpoints (read methods) on them. The method matcher simply describes which methods for a given class are considered valid joinpoints for this pointcut. I don't want to spend too much time on the pointcut interface, however, because chances are - you won't be implementing it. Static vs. Dynamic Method Matching Spring makes a distinction between static and dynamic method matching. A static method matching pointcut (a subclass of the org.springframework.aop.support.StaticMethodMatcherPointcut class) knows at the time it proxies a target object what methods it considers joinpoints on that object. A dymamic method matching pointcut (see below for implementation details), on the other hand must be consulted at *every* method invocation. This is a useful implementation detail because a static method matcher, while having less flexibility (you can't check the method invocation arguments), is, by design, much faster, as the check is only performed once, rather than at every method invocation. Static Matching pointcuts implementations look something like this: public class MyBeanPointcut extends StaticMethodMatcherPointcut { public boolean matches(java.lang.reflect.Method theMethod, java.lang.Class theClass) { return (MyBean.class.isAssignableFrom(theClass) && theMethod.equals(...)); } }

In most cases, however, this is irrelevant, because there is a very convenient pair of static method matchers that cover almost all concerns - the org.springframework.aop.support.JdkRegexpMethodPointcut and org.springframework.aop.support.PerlRegexpMethodPointcut classes. You typically configure these outside of your code (we'll get to configuration in a bit), and don't have to do any nasty reflection checks as seen above. In addition, there is a simpler variety of text-based matching called the NameMatchedMethodPointcut - which is similar to the regex implementations, but only matches exact names. Dynamic matching pointcut implementations typically look something like this: public class MyBeanPointcut extends StaticMethodMatcherPointcut { public boolean matches(java.lang.reflect.Method theMethod, java.lang.Class theClass, Object[] arguments) { boolean matches = false;

if(MyBean.class.isAssignableFrom(theClass) && theMethod.equals(...)) { if(arguments[0].equals("Joe Smith")) { matches = true; } } return matches; } }

Due to the nature of dynamic pointcuts, there are no real convenience implementations of this class. Here is what the pointcut hierarchy generally looks like:

You may have noticed, neither of my pointcut examples made any reference to any advice (e.g. MethodInterceptor implementation) - remember that I said an advice knows the *what*, not the *where*? Well, a pointcut is the inverse - it knows the *where*, not the *what*. Therefore, theoretically, these two components can be intermingled in different configurations and reused. Tying Pointcuts with Advisors - PointcutAdvisors I've gone to great lengths above to clarify that pointcuts don't know about advice objects, and advice objects don't know about pointcuts. Some object somewhere, however, must know about both if we are going to have any hope of wrapping our beans in aspects. That is where implementations of PointcutAdvisor come in. Conceptually speaking, a PointcutAdvisor is nothing more than a pointcut and an advice object combined hence the name. The most basic variety of pointcut advisor is the org.springframework.aop.support.DefaultPointcutAdvisor class. This is for the most part just a bean that has two references - something akin to this: public class DefaultPointcutAdvisor { private Pointcut pointcut; private Advice advice; public public public public }

Pointcut getPointcut() { return pointcut; } Advice getAdvice() { return advice; } void setPointcut(Pointcut pc) { pointcut = pc; } void setAdvice(Advice a) { advice = a; }

Yes, yes, in reality it is more complicated than this - but really that is the bulk of it right there. Now we are getting to a point where we can define the *what* (the Advice) and the *where* (the Pointcut) in one discrete location. A basic configuration of this advisor in a spring bean definition may look something like this: <property name="mappedName" value="handleRequestInternal"/> <property name="advice" ref="interceptorA"/> <property name="pointcut" ref="controller.handle.pointcut"/> <property name="advice" ref="beforeAdviceA"/> <property name="pointcut" ref="controller.handle.pointcut"/>

Hopefully this gives you some idea of the relationship of these three classes. As you can see, advice objects and pointcuts can be intermixed freely into varying pointcut advisors. Let's Simplify Things Ok, now, throw all of that example out of the window. Why? Well, because in reality while the above example is much more flexible, it is quite verbose as well. Most times that level of granularity is unnecessary, as we will soon see. Earlier I glossed over the org.springframework.aop.support.PointcutAdvisor class hierarchy, and just

mentioned the most basic DefaultPointcutAdvisor . Let's take a closer look at the available class hierarchy now:

Did you notice how similar the names are to the pointcuts we just learned about? Most of these classes take the seperation of pointcut and advisor out of the equation, which, while theoretically reducing some degree of flexibility, typically makes configuration much easier. Here is the same example above, using the NameMatchMethodPointcut Advisor object (which combines the PointcutAdvisor API with the NameMatchMethodPointcut class): <property name="advice" ref="interceptorA"/> <property name="mappedName" value="handleRequestInternal"/> <property name="advice" ref="beforeAdviceA"/> <property name="mappedName" value="handleRequestInternal"/>

As you can see, we got rid of the configuration of one bean entirely. Technically speaking we are no longer reusing the pointcut, but since pointcut definitions are typically a configuration concern (as seen above), it doesn't usually matter one way or another to us. Gluing it All Together So, we've covered advice objects and pointcut objects - which when you get down to it, are the core; the center of Spring AOP support. Then we covered pointcut advisors which take advice objects and pointcut objects and glue them together into one cohesive chunk the peanut butter and jelly; the meat and potatoes; the spaghetti and meatballs; the lamb and tunafish. There is a very important piece of the puzzle missing however: how do we wrap these pointcut-advisor combos around our objects? After all, that is the whole point of all of this. Enter the ProxyFactoryBean . Without getting into too much detail, Spring supports the concept of a FactoryBean , which is a special type of bean, in that the bean returned is a factory result, rather than just a plain 'newInstance()' call on the class you provided. So, you could have a factory bean implementation that, based on certain configuration details, factoried different implementations of a certain class. So, just to solidify my point, in this example:

If you ask for myBean from the bean factory, you're *not* going to get an instance of MyFactoryBean - instead, Spring is going to consult with the MyFactoryBean object, and ask it to provide the object you want. Why is all of this important? Well, because this FactoryBean concept is how Spring wraps your beans - via the some configuration details, and then using some internal tool (dynamic proxies, CGLib, etc.) to create a proxy for your bean that executes some advice on method calls when the pointcut says the method is a joinpoint (assuming a pointcut is defined). Expanding our example above, here is how Spring's proxy factory bean works:

<property name="advice" ref="interceptorA"/> <property name="mappedName" value="handleRequestInternal"/> <property name="advice" ref="beforeAdviceA"/> <property name="mappedName" value="handleRequestInternal"/> <property name="interceptorNames"> <list> pointcut.advisor2 pointcut.advisor1 myRawController

Notice the interceptorNames property? This is how we tell the proxy factory bean what advisors or advice objects we want to apply to the proxied bean. Order is important in this list - the order the advisors or advice objects are entered in the list defines the order they will be invoked when entering and exiting the bean. Note that in this case the *last* entry in the list is our bean that we want to be proxied. This is just one possible way to define the bean to be proxied as we'll see in a moment. Also, did you notice that I said advisors or advice objects ? That is because the proxy factory bean allows for another shortcut; not specifying a pointcut at all, just an advice. In those cases, an 'every method is a joinpoint' style pointcut will automatically be applied. So, if we didn't care which methods were advised, we could shorten the example above like this:

<property name="interceptorNames"> <list> beforeAdviceA interceptorA myRawController

Now, I mentioned earlier that there is another way to specify the target bean. This can be done through the targetName and/or target properties on the factory bean: <property name="target" ref="myRawController"/> <property name="interceptorNames"> <list> beforeAdviceA interceptorA

If you don't need direct (non-AOP'd) access to your bean, then it may be better for the simplicity of the file to just use an anonymous inner bean, rather than declaring the bean seperately to the proxy: <property name="target"> <property name="interceptorNames"> <list> beforeAdviceA interceptorA

Conclusion for Now

Ok, well, I could keep going on and on and on, but I'd never finish this article, and you'd never get to read it; and if you *did*, it'd be so long and boring that I might as well put it on the shelf next to the encyclopedia. Now, some people who already know about Spring AOP are probably ready to clamor because I haven't covered these topics (among others I'm sure): • • •

Introductions/Mixins Specialized Proxy Support (such as the TransactionProxyFactoryBean) Other corner cases

I didn't cover introductions specifically because they are so uniquely different from other types of Spring AOP, I thought it would be good to cover the basic, common forms first. As far as the specialized cases and 'unique tweaks', let's gauge the popularity of the subject, and see where we get.

Related Documents

Spring A Op
November 2019 7
A Op
May 2020 7
Home Op A Ti A
May 2020 13
Est Op A
April 2020 8
Op Am A
May 2020 27
Op A 2227
November 2019 12