免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 897 | 回复: 0
打印 上一主题 下一主题

AOP3 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-19 16:21 |只看该作者 |倒序浏览
6.3. Schema-based AOP support
If you are unable to use Java 5, or simply prefer an XML-based format, then
    Spring 2.0 also offers support for defining aspects using the new "aop" namespace
    tags. The exact same pointcut expressions and advice kinds are supported as when
    using the @AspectJ style, hence in this section we will focus on the new
    syntax and refer the reader to the discussion in the previous
    section (
Section 6.2, “@AspectJ support”
) for an understanding of writing pointcut
    expressions and the binding of advice parameters.
To use the aop namespace tags described in this section, you need to import
    the spring-aop schema as described in
       
Appendix A, XML Schema-based configuration
. See
Section A.2.6, “The aop schema”

        for how to import the tags in the aop namespace.
Within your Spring configurations, all aspect and advisor elements must be
    placed within an  element (you can have more
    than one  element in an application context
    configuration). An  element can contain
    pointcut, advisor, and aspect elements (note these must be declared in that order).

Warning
The  style of configuration makes
        heavy use of Spring's
auto-proxying
        mechanism. This can cause issues (such as advice not being woven) if you are
        already using explicit auto-proxying via the use of
        BeanNameAutoProxyCreator or suchlike. The recommended
        usage pattern is to use either just the AutoProxyCreator style.
        style, or just the
6.3.1. Declaring an aspect
Using the schema support, an aspect is simply a regular Java object
        defined as a bean in your Spring application context. The state and behavior is
        captured in the fields and methods of the object, and the pointcut and advice
        information is captured in the XML.
An aspect is declared using the  element, and the backing bean
        is referenced using the ref attribute:
  
    ...
  
  ...
            The bean backing the aspect ("aBean" in this case) can of course be
            configured and dependency injected just like any other Spring bean.
6.3.2. Declaring a pointcut
        A pointcut can be declared inside an aspect, in which case it is visible only within
        that aspect. A pointcut can also be declared directly inside an
        element, enabling the pointcut definition to be shared across several aspects and
        advisors.
A pointcut representing the execution of any business service in the service
        layer could be defined as follows:
  
Note that the pointcut expression itself is using the same AspectJ pointcut
        expression language as described in
Section 6.2, “@AspectJ support”
. If you are
        using the schema based declaration style with Java 5, you can refer to named
        pointcuts defined in types (@Aspects) within the pointcut expression, but this
        feature is not available on JDK 1.4 and below (it relies on the Java 5 specific
        AspectJ reflection APIs). On JDK 1.5 therefore, another way of defining the above
        pointcut would be:
  
Assuming you have a SystemArchitecture aspect as described in
       
Section 6.2.3.3, “Sharing common pointcut definitions”
.
Declaring a pointcut inside an aspect is very similar to declaring a top-level pointcut:
  
   
         
    ...
   
  
When combining pointcut sub-expressions, '&&' is awkward within an XML
        document, and so the keywords 'and', 'or' and 'not' can be used in place
        of '&&', '||' and '!' respectively.
Note that pointcuts defined in this way are referred to by their XML id, and
        cannot define pointcut parameters. The named pointcut support in the schema based
        definition style is thus more limited than that offered by the @AspectJ style.
6.3.3. Declaring advice
The same five advice kinds are supported as for the @AspectJ style, and they
        have exactly the same semantics.
6.3.3.1. Before advice
Before advice runs before a matched method execution.
        It is declared inside an  using
        the  element.
   
         
    ...
   
Here dataAccessOperation is the id of a pointcut defined at
          the top () level. To define the pointcut
          inline instead, replace the pointcut-ref attribute with a
          pointcut attribute:
   
         
    ...
   
As we noted in the discussion of the @AspectJ style, using named pointcuts
          can significantly improve the readability of your code.
The method attribute identifies a method (doAccessCheck) that
          provides the body of the advice. This method must be defined for the bean referenced
          by the aspect element containing the advice. Before a data access operation is
          executed (a method execution join point matched by the pointcut expression), the
          "doAccessCheck" method on the aspect bean will be invoked.
6.3.3.2. After returning advice
After returning advice runs when a matched method execution completes normally.
            It is declared inside an  in
            the same way as before advice. For example:
          
   
         
    ...
   
Just as in the @AspectJ style, it is possible to get hold of the return value within
        the advice body. Use the returning attribute to specify the name of the parameter to which
        the return value should be passed:
   
         
    ...
   
The doAccessCheck method must declare a parameter named retVal. The
        type of this parameter constrains matching in the same way as described for @AfterReturning.
        For example, the method signature may be declared as:
       
public void doAccessCheck(Object retVal) {...6.3.3.3. After throwing advice
After throwing advice executes when a matched method execution exits by throwing
        an exception. It is declared inside an  using
        the after-throwing element:
   
         
    ...
   
Just as in the @AspectJ style, it is possible to get hold of the thrown exception within
        the advice body. Use the throwing attribute to specify the name of the parameter to which
        the exception should be passed:
   
         
    ...
   
The doRecoveryActions method must declare a parameter named dataAccessEx.
        The type of this parameter constrains matching in the same way as described for
        @AfterThrowing.
        For example, the method signature may be declared as:
       
public void doRecoveryActions(DataAccessException dataAccessEx) {...6.3.3.4. After (finally) advice
After (finally) advice runs however a matched method execution exits. It is declared
        using the after element:
   
         
    ...
   
6.3.3.5. Around advice
The final kind of advice is around advice. Around advice runs "around" a
        matched method execution. It has the opportunity to do work both before and
        after the method executes, and to determine when, how, and even if, the method
        actually gets to execute at all. Around advice is often used if you need to
        share state before and after a method execution in a thread-safe manner (starting
        and stopping a timer for example).  Always use the least powerful form of
        advice that meets your requirements; don't use around advice if simple
        before advice would do.
Around advice is declared using the aop:around element.
        The first parameter of the advice method must be of type
        ProceedingJoinPoint. Within the body of the
        advice, calling proceed() on the
        ProceedingJoinPoint causes the
        underlying method to execute. The proceed method may also be
        calling passing in an Object[] - the values in the array will be used as the arguments
        to the method execution when it proceeds. See
Section 6.2.4.5, “Around advice”
        for notes on calling proceed with an Object[].
       
   
         
    ...
   
The implementation of the doBasicProfiling advice would be
        exactly the same as in the @AspectJ example (minus the annotation of course):
       
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
    // start stopwatch
    Object retVal = pjp.proceed();
    // stop stopwatch
    return retVal;
}6.3.3.6. Advice parameters
The schema based declaration style supports fully typed advice in the same way as
         described for the @AspectJ support - by matching pointcut parameters by name
         against advice method parameters. See
Section 6.2.4.6, “Advice parameters”
         for details.
         
If you wish to explicity specify argument names for the advice methods (not
         relying on either of the detection strategies previously described) then this is
         done using the arg-names attribute of the advice element. For
         example:
The arg-names attribute accepts a comma-delimited list of
        parameter names.
Find below a slightly more involved example of the XSD-based approach that
        illustrates some around advice used in conjunction with a number of strongly typed
        parameters.
package x.y.service;
public interface FooService {
   Foo getFoo(String fooName, int age);
}
public class DefaultFooService implements FooService {
   public Foo getFoo(String name, int age) {
      return new Foo(name, age);
   }
}
Next up is the aspect. Notice the fact that the
    profile(..) method accepts a number of strongly-typed parameters,
    the first of which happens to be the join point used to proceed with the method call: the
    presence of this parameter is an indication that the profile(..)
    is to be used as around advice:
package x.y;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
public class SimpleProfiler {
   public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable {
      StopWatch clock = new StopWatch(
            "Profiling for '" + name + "' and '" + age + "'");
      try {
         clock.start(call.toShortString());
         return call.proceed();
      } finally {
         clock.stop();
         System.out.println(clock.prettyPrint());
      }
   }
}
Finally, here is the XML configuration that is required to effect the
        execution of the above advice for a particular joinpoint:
   
   
   
   
   
      
         
         
      
   
If we had the following driver script, we would get output something like this
        on standard output:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import x.y.service.FooService;
public final class Boot {
   public static void main(final String[] args) throws Exception {
      BeanFactory ctx = new ClassPathXmlApplicationContext("x/y/plain.xml");
      FooService foo = (FooService) ctx.getBean("fooService");
      foo.getFoo("Pengo", 12);
   }
}StopWatch 'Profiling for 'Pengo' and '12'': running time (millis) = 0
-----------------------------------------
ms     %     Task name
-----------------------------------------
00000  ?  execution(getFoo)6.3.3.7. Advice ordering
When multiple advice needs to execute at the same join point (executing
        method) the ordering rules are as described in
Section 6.2.4.7, “Advice ordering”
.
        The precedence between aspects is determined by either adding the Order
        annotation to the bean backing the aspect or by having the bean implement the
        Ordered interface.
6.3.4. Introductions
Introductions (known as inter-type declarations in AspectJ) enable an aspect
        to declare that advised objects implement a given interface, and to provide an implementation
        of that interface on behalf of those objects.
An introduction is made using the aop:declare-parents element
        inside an aop:aspect This element is
        used to declare that matching types have a new parent (hence the name). For example, given
        an interface UsageTracked, and an implementation of that
        interface DefaultUsageTracked, the following
        aspect declares that all implementors of service interfaces also implement the
        UsageTracked interface. (In order to expose statistics
        via JMX for example.)
       
  
  
  
  
The class backing the usageTracking bean would contain the
    method:
public void recordUsage(UsageTracked usageTracked) {
    usageTracked.incrementUseCount();
}
        The interface to be implemented is determined by implement-interfacetypes-matching attribute is an AspectJ type pattern :-
        any bean of a matching type will implement the UsageTrackedUsageTracked
        attribute. The value of the
       
        interface. Note that in the before advice of the above example, service
        beans can be directly used as implementations of the  interface. If accessing
        a bean programmatically you would write the following:
       
UsageTracked usageTracked = (UsageTracked) context.getBean("myService");6.3.5. Aspect instantiation models
The only supported instantiation model for schema-defined aspects is the
        singleton model. Other instantiation models may be supported in future releases.
6.3.6. Advisors
The concept of "advisors" is brought forward from the AOP support defined
        in Spring 1.2 and does not have a direct equivalent in AspectJ. An advisor is
        like a small self-contained aspect that has a single piece of advice. The advice
        itself is represented by a bean, and must implement one of the advice
        interfaces described in
Section 7.3.2, “Advice types in Spring”
. Advisors can
        take advantage of AspectJ pointcut expressions though.
       
Spring 2.0 supports the advisor concept with the  
        element. You will most commonly see it used in conjunction with transactional advice,
        which also has its own namespace support in Spring 2.0. Here's how it looks:
       
  
  
      
  
   
  
As well as the pointcut-ref attribute used in the above
        example, you can also use the pointcut attribute to define a
        pointcut expression inline.
To define the precedence of an advisor so that the advice can participate
        in ordering, use the order attribute to define the
        Ordered value of the advisor.
6.3.7. Example
Let's see how the concurrent locking failure retry example from
       
Section 6.2.7, “Example”
looks when rewritten using the schema support.
       
The execution of business services can sometimes fail
      due to concurrency issues (for example, deadlock loser).
      If the operation is retried, it is quite likely it will succeed next time round. For
      business services where it is appropriate to retry in such conditions (idempotent
      operations that don't need to go back to the user for conflict resolution), we'd like
      to transparently retry the operation to avoid the client seeing a
      PessimisticLockingFailureException. This is a requirement that clearly cuts across
      multiple services in the service layer, and hence is ideal for implementing via an aspect.
      
Because we want to retry the operation, we'll need to use around advice so
      that we can call proceed multiple times. Here's how the basic aspect implementation
      looks (it's just a regular Java class using the schema support):
      
public class ConcurrentOperationExecutor implements Ordered {
   
   private static final int DEFAULT_MAX_RETRIES = 2;
   private int maxRetries = DEFAULT_MAX_RETRIES;
   private int order = 1;
   public void setMaxRetries(int maxRetries) {
      this.maxRetries = maxRetries;
   }
   
   public int getOrder() {
      return this.order;
   }
   
   public void setOrder(int order) {
      this.order = order;
   }
   
   public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
      int numAttempts = 0;
      PessimisticLockingFailureException lockFailureException;
      do {
         numAttempts++;
         try {
            return pjp.proceed();
         }
         catch(PessimisticLockingFailureException ex) {
            lockFailureException = ex;
         }
      }
      while(numAttempts
Note that the aspect implements the Ordered interface so we can set the precedence
      of the aspect higher than the transaction advice (we want a fresh transaction
      each time we retry). The maxRetries and orderdoConcurrentOperation around advice method. We
      try to proceed, and if we fail with a PessimisticLockingFailureException
      we simply try again unless we have exhausted all of our retry attempts.
      
      properties will both be configured by Spring. The main action happens in the
      
This class is identical to the one used in the @AspectJ example, but
      with the annotations removed.

The corresponding Spring configuration is:
  
   
      
   
  
  
     
      
Notice that for the time being we assume that all business services
       are idempotent. If this is not the case we can refine the aspect so that it only
       retries genuinely idempotent operations, by introducing an
       Idempotent annotation:
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
  // marker annotation
}
and using the annotation to annotate the implementation of service operations.
       The change to the aspect to only retry idempotent operations simply involves
       refining the pointcut expression so that only @Idempotent operations match:
  
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/24141/showart_324461.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP