免费注册 查看新帖 |

Chinaunix

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

AOP1 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-19 16:20 |只看该作者 |倒序浏览
6.1. Introduction
Aspect-Oriented Programming
    (AOP) complements Object-Oriented Programming (OOP)
    by providing another way of thinking about program structure. In addition
    to classes, AOP gives you aspects. Aspects
    enable modularization of concerns such as transaction management that
    cut across multiple types and objects. (Such concerns are often
    termed crosscutting concerns.)
One of the key components of Spring is the AOP
    framework. While the Spring IoC container does not depend on AOP,
    meaning you don't need to use AOP if you don't want to, AOP complements
    Spring IoC to provide a very capable middleware solution.
Spring 2.0 AOP
Spring 2.0 introduces a simpler and more powerful
        way of writing custom aspects using either a schema-based approach
        or the @AspectJ annotation style. Both of these styles offer fully
        typed advice and use of the AspectJ pointcut language, while still using
        Spring AOP for weaving.
The Spring 2.0 schema and @AspectJ based AOP support is discussed in
                this chapter. Spring 2.0 AOP remains fully backwards compatible with
                Spring 1.2 AOP, and the lower-level AOP support offered by the Spring 1.2 APIs
                is discussed in       
the following chapter
.
AOP is used in the Spring Framework:

  • To provide declarative enterprise services, especially as a
            replacement for EJB declarative services. The most important such
            service is
            
    declarative transaction management
    ,
            which builds on the Spring Framework's transaction abstraction.

  • To allow users to implement custom aspects, complementing their
            use of OOP with AOP.
    If you are interested only in generic declarative services or
        other pre-packaged declarative middleware services such as pooling, you
        don't need to work directly with Spring AOP, and can skip most of this
        chapter.
    6.1.1. AOP concepts
    Let us begin by defining some central AOP concepts. These terms
          are not Spring-specific. Unfortunately, AOP terminology is not
          particularly intuitive; however, it would be even more confusing if
          Spring used its own terminology.

  • Aspect: A modularization of a concern
              that cuts across multiple objects. Transaction management is a good example
                      of a crosscutting concern in J2EE applications. In Spring AOP, aspects are
                      implemented using regular classes (the schema-based approach) or regular
                      classes annotated with the @Aspect annotation
                      (@AspectJ style).

  • Join point: A point during the execution of
              a program, such as the execution of a method or the handling of
              an exception. In Spring AOP, a join point always represents
              a method execution. Join point information is available in advice
              bodies by declaring a parameter of type org.aspectj.lang.JoinPoint.
             

  • Advice: Action taken by an aspect
              at a particular join point. Different types of advice include
              "around," "before" and "after" advice. Advice types are discussed
              below. Many AOP frameworks, including Spring, model an advice as an
              interceptor, maintaining a chain of
              interceptors "around" the join point.

  • Pointcut: A predicate that matches join points.
              Advice is associated with a pointcut expression and runs at any join
              point matched by the pointcut (for example, the execution of a method with
              a certain name). The concept of join points as matched by pointcut
                      expressions is central to AOP: Spring uses the AspectJ pointcut language by default.

  • Introduction: (Also known as an
              inter-type declaration). Declaring additional methods or fields on
              behalf of a type. Spring AOP allows you to introduce new interfaces
                      (and a corresponding implementation) to
              any proxied object. For example, you could use an introduction to
              make a bean implement an IsModified
              interface, to simplify caching.

  • Target object: Object being advised
              by one or more aspects. Also referred to as the advised
                      object. Since Spring AOP is implemented using runtime proxies, this object
                      will always be a proxied object.

  • AOP proxy: An object created by the AOP
              framework in order to implement the aspect contracts (advise method
              executions and so on). In the Spring Framework, an AOP proxy will be a JDK
              dynamic proxy or a CGLIB proxy. Proxy creation is
                      transparent to users of the schema-based and @AspectJ styles of
                      aspect declaration introduced in Spring 2.0.

  • Weaving: Linking aspects with other
              application types or objects to create an advised object. This can be
                      done at compile time (using the AspectJ compiler, for example), load time,
                      or at runtime. Spring AOP, like other pure Java AOP frameworks, performs
                      weaving at runtime.

    Types of advice:

  • Before advice: Advice that executes
              before a join point, but which does not have the ability to prevent
              execution flow proceeding to the join point (unless it throws an
              exception).

  • After returning advice: Advice to be
              executed after a join point completes normally: for example, if a
              method returns without throwing an exception.

  • After throwing advice: Advice to be executed if a
              method exits by throwing an exception.

  • After (finally) advice: Advice to be executed regardless
              of the means by which a join point exits (normal or exceptional return).

  • Around advice: Advice that surrounds a
              join point such as a method invocation. This is the most powerful
              kind of advice. Around advice can perform custom behavior before
              and after the method invocation. It is also responsible for choosing
              whether to proceed to the join point or to shortcut the advised method
                      execution by returning its own return value or throwing an exception.

    Around advice is the most general kind of advice. Since Spring AOP,
                    like AspectJ, provides a full range of advice types, we recommend that you
                    use the least powerful advice type that can implement the required behavior.
                    For example, if you need only to update a cache with the return value of a
                    method, you are better off implementing an after returning advice than an
                    around advice, although an around advice can accomplish the same thing. Using
                    the most specific advice type provides a simpler programming model with less
                    potential for errors. For example, you  do not need to invoke the
                    proceed() method on the JoinPoint
                    used for around advice, and hence cannot fail to invoke it.
    In Spring 2.0, all advice parameters are statically typed, so that you
              work with advice parameters of the appropriate type (the type of the return
              value from a method execution for example) rather than
              Object arrays.
    The concept of join points, matched by pointcuts, is the key to AOP
              which distinguishes it from older technologies offering only interception.
              Pointcuts enable advice to be targeted independently of the Object-Oriented hierarchy.
              For example, an around advice providing declarative transaction management can
              be applied to a set of methods spanning multiple objects (such as all business
              operations in the service layer).
    6.1.2. Spring AOP capabilities and goals
    Spring AOP is implemented in pure Java. There is no need for a
          special compilation process. Spring AOP does not need to control the
          class loader hierarchy, and is thus suitable for use in a J2EE web
          container or application server.
    Spring AOP currently supports only method execution join points
          (advising the execution of methods on Spring beans). Field interception
              is not implemented, although support for field interception could be added
              without breaking the core Spring AOP APIs. If you need to advise field
          access and update join points, consider a language such as AspectJ.
    Spring AOP's approach to AOP differs from that of most other AOP
          frameworks. The aim is not to provide the most complete AOP
          implementation (although Spring AOP is quite capable); it is rather to
          provide a close integration between AOP implementation and Spring IoC to
          help solve common problems in enterprise applications.
    Thus, for example, the Spring Framework's AOP functionality is normally
              used in conjunction with the Spring IoC container. Aspects are configured
              using normal bean definition syntax (although this allows powerful
          "autoproxying" capabilities): this is a crucial difference from other AOP
          implementations. There are some things you cannot do easily or
          efficiently with Spring AOP, such as advise very fine-grained objects:
          AspectJ is the best choice in such cases. However, our experience is that
              Spring AOP provides an excellent solution to most problems in J2EE applications
              that are amenable to AOP.
    Spring AOP will never strive to compete with AspectJ to provide
              a comprehensive AOP solution. We believe that both proxy-based frameworks like
              Spring AOP and full-blown frameworks such as AspectJ are valuable, and that they
              are complementary, rather than in competition. Spring 2.0 seamlessly integrates
              Spring AOP and IoC with AspectJ, to enable all uses of AOP to be catered for within
              a consistent Spring-based application architecture. This integration does not
              affect the Spring AOP API or the AOP Alliance API: Spring AOP remains
              backward-compatible. See
    the following chapter
    for a
              discussion of the Spring AOP APIs.

    Note
    One of the central tenets of the Spring Framework is that of
                      non-invasiveness; this is the idea that you should not be forced to
                      introduce framework-specific classes and interfaces into your business/domain
                      model. However, in some places the Spring Framework does give you the option
                      to introduce Spring Framework-specific dependencies into your codebase: the
                      rationale in giving you such options is because in certain scenarios it
                      might be just plain easier to read or code some specific piece of functionality
                      in such a way. The Spring Framework (almost) always offers you the choice
                      though: you have the freedom to make an informed decision as to which option
                      best suits your particular use case or scenario.
    One such choice that is relevant to this chapter is that of which AOP
                      framework (and which AOP style) to choose. You have the choice of AspectJ and/or
                      Spring AOP, and you also have the choice of either the @AspectJ annotation-style
                      approach or the Spring XML configuration-style approach. The fact that this chapter
                      chooses to introduce the @AspectJ-style approach first should not be taken as
                      an indication that the Spring team favors the @AspectJ annotation-style approach
                      over the Spring XML configuration-style.
    See the section entitled
    Section 6.4, “Choosing which AOP declaration style to use”
    for a fuller discussion
                      of the whys and wherefores of each style.
    6.1.3. AOP Proxies
    Spring AOP defaults to using standard J2SE dynamic proxies
          for AOP proxies. This enables any interface (or set of interfaces) to be
          proxied.
    Spring AOP can also use CGLIB proxies. This is necessary to proxy
          classes, rather than interfaces. CGLIB is used by default if a business
          object does not implement an interface. As it is good practice to
          program to interfaces rather than classes, business classes normally will
              implement one or more business interfaces. It is possible to
              
    force the use of CGLIB
    ,
          in those (hopefully rare) cases where you need to advise a method that
          is not declared on an interface, or where you need to pass a proxied object
          to a method as a concrete type.
    It is important to grasp the fact that Spring AOP is
                    proxy-based. See the section entitled
                   
    Section 6.6.1, “Understanding AOP proxies”
    for a thorough examination
                    of exactly what this implementation detail actually means.
    6.2. @AspectJ support
    @AspectJ refers to a style of declaring aspects as regular Java classes annotated with
        Java 5 annotations. The @AspectJ style was introduced by the
       
    AspectJ project
    as part of
        the AspectJ 5 release. Spring 2.0 interprets the same annotations as AspectJ 5,
        using a library supplied by AspectJ for pointcut parsing and matching. The AOP runtime
        is still pure Spring AOP though, and there is no dependency on the AspectJ compiler
        or weaver.

                
    Using the AspectJ compiler and weaver enables use of the full AspectJ language,
                    and is discussed in
    Section 6.8, “Using AspectJ with Spring applications”
    .
           
    6.2.1. Enabling @AspectJ Support
    To use @AspectJ aspects in a Spring configuration you need to enable Spring
            support for configuring Spring AOP based on @AspectJ aspects, and
            autoproxying beans based on whether or not they are advised by
            those aspects. By autoproxying we mean that if Spring determines that a bean is advised
            by one or more aspects, it will automatically generate a proxy for that bean to intercept
            method invocations and ensure that advice is executed as needed.
            
    The @AspectJ support is enabled by including the following element inside
            your spring configuration:
    This assumes that you are using schema support 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.
    If you are using the DTD, it is still possible to enable @AspectJ support by
            adding the following definition to your application context:
    You will also need two AspectJ libraries on the classpath of your application:
            aspectjweaver.jar and
            aspectjrt.jar. These libraries
            are available in the 'lib' directory of an AspectJ installation (version
            1.5.1 or later required), or in the 'lib/aspectj' directory of the
            Spring-with-dependencies distribution.
    6.2.2. Declaring an aspect
    With the @AspectJ support enabled, any bean defined in your application context
          with a class that is an @AspectJ aspect (has the @Aspect
          annotation) will be automatically detected by Spring and used to configure Spring AOP.
          The following example shows the minimal definition required for a not-very-useful
          aspect:
    A regular bean definition in the application context, pointing to a bean class
          that has the @Aspect annotation:
       
    And the NotVeryUsefulAspect class definition, annotated with
              org.aspectj.lang.annotation.Aspect annotation;
    package org.xyz;
    import org.aspectj.lang.annotation.Aspect;
    @Aspect
    public class NotVeryUsefulAspect {
    }
    Aspects (classes annotated with @Aspect) may have
                    methods and fields just like any other class. They may also contain pointcut, advice,
                    and introduction (inter-type) declarations.

    Advising aspects
    In Spring AOP, it is not possible to
                            have aspects themselves be the target of advice from other aspects.
                            The @Aspect annotation on a class marks it as an
                            aspect, and hence excludes it from auto-proxying.
    6.2.3. Declaring a pointcut
    Recall that pointcuts determine join points of interest, and thus enable us
              to control when advice executes. Spring AOP only supports method execution
              join points for Spring beans, so you can think of a pointcut as matching
              the execution of methods on Spring beans. A pointcut declaration has two parts: a
              signature comprising a name and any parameters, and a pointcut expression
              that determines exactly which method executions we are interested in.
              In the @AspectJ annotation-style of AOP, a pointcut signature is provided by a regular method
              definition, and the pointcut expression is indicated using the
              @Pointcut annotation (the method serving as the pointcut
              signature must have a void return
              type).
    An example will help make this distinction between a pointcut signature and a
              pointcut expression clear. The following example defines a pointcut named
              'anyOldTransfer' that will match the execution of any method named
              'transfer':
    @Pointcut("execution(* transfer(..))")// the pointcut expression
    private void anyOldTransfer() {}// the pointcut signature
    The pointcut expression that forms the value of the @Pointcut
              annotation is a regular AspectJ 5 pointcut expression. For a full discussion of AspectJ's
              pointcut language, see the
              
    AspectJ Programming Guide
              (and for Java 5 based extensions, the
              
    AspectJ 5 Developers Notebook
    )
              or one of the books on AspectJ such as “Eclipse AspectJ” by Colyer et. al.
              or “AspectJ in Action” by Ramnivas Laddad.
    6.2.3.1. Supported Pointcut Designators
    Spring AOP supports the following AspectJ pointcut designators for use in pointcut
              expressions:
    Other pointcut types
    The full AspectJ pointcut language supports additional pointcut designators
                  that are not supported in Spring. These are: call, initialization,
                  preinitialization, staticinitialization, get, set, handler, adviceexecution,
                  withincode, cflow, cflowbelow, if, @this, and @withincode.
                  Use of these pointcut designators in pointcut expressions interpreted by Spring AOP
                  will result in an IllegalArgumentException being thrown.
    The set of pointcut designators supported by Spring AOP may be extended in
                  future releases both to support more of the AspectJ pointcut designators (e.g. "if"),
                  and potentially to support Spring specific designators such as "bean" (matching on
                  bean name).

  • execution - for matching method execution join points,
                  this is the primary pointcut designator you will use when working with Spring AOP

  • within - limits matching to join points within certain
                  types (simply the execution of a method declared within a matching type when using
                  Spring AOP)

  • this - limits matching to
                      join points (the execution of methods when using Spring AOP) where the bean
                  reference (Spring AOP proxy) is an instance of the given type

  • target - limits matching to join points (the execution
                  of methods when using Spring AOP) where the target object (application object
                  being proxied) is an instance of the given type

  • args - limits matching to
                      join points (the execution of methods when using Spring AOP) where the
                  arguments are instances of the given types

  • @target - limits matching
                  to join points (the execution of methods when using Spring AOP) where the
                  class of the executing object has an annotation of the given type

  • @args - limits matching to
                      join points (the execution of methods when using Spring AOP) where the
                  runtime type of the actual arguments passed have annotations of the given type(s)

  • @within - limits matching
                  to join points within types that have the given annotation (the execution of methods
                  declared in types with the given annotation when using Spring AOP)  
                      

  • @annotation - limits matching to join points where the
                  subject of the join point (method being executed in Spring AOP) has the given
                  annotation
    Because Spring AOP limits matching to only method execution join points, the
                discussion of the pointcut designators above gives a narrower definition than you will
                find in the AspectJ programming guide. In addition, AspectJ itself has type-based
                semantics and at an execution join point both 'this' and 'target' refer to the same
                object - the object executing the method. Spring AOP is a proxy based system and
                differentiates between the proxy object itself (bound to 'this') and the target
                object behind the proxy (bound to 'target').
    6.2.3.2. Combining pointcut expressions
    Pointcut expressions can be combined using '&&', '||' and '!'. It is also possible
              to refer to pointcut expressions by name. The following example shows three pointcut
              expressions: anyPublicOperation (which matches if a method execution
              join point represents the execution of any public method); inTrading (which matches
              if a method execution is in the trading module), and tradingOperation
              (which matches if a method execution represents any public method in the trading module).
        @Pointcut("execution(public * *(..))")
        private void anyPublicOperation() {}
       
        @Pointcut("within(com.xyz.someapp.trading..*")
        private void inTrading() {}
       
        @Pointcut("anyPublicOperation() && inTrading()")
        private void tradingOperation() {}
    It is a best practice to build more complex pointcut expressions out of smaller
              named components as shown above. When referring to pointcuts by name, normal Java
              visibility rules apply (you can see private pointcuts in the same type, protected
              pointcuts in the hierarchy, public pointcuts anywhere and so on). Visibility does not
              affect pointcut matching.
    6.2.3.3. Sharing common pointcut definitions
    When working with enterprise applications, you often want to refer to modules of the
            application and particular sets of operations from within several aspects. We recommend
            defining a "SystemArchitecture" aspect that captures common pointcut expressions
            for this purpose. A typical such aspect would look as follows:
    package com.xyz.someapp;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    @Aspect
    public class SystemArchitecture {
      /**
       * A join point is in the web layer if the method is defined
       * in a type in the com.xyz.someapp.web package or any sub-package
       * under that.
       */
      @Pointcut("within(com.xyz.someapp.web..*)")
      public void inWebLayer() {}
      /**
       * A join point is in the service layer if the method is defined
       * in a type in the com.xyz.someapp.service package or any sub-package
       * under that.
       */
      @Pointcut("within(com.xyz.someapp.service..*)")
      public void inServiceLayer() {}
      /**
       * A join point is in the data access layer if the method is defined
       * in a type in the com.xyz.someapp.dao package or any sub-package
       * under that.
       */
      @Pointcut("within(com.xyz.someapp.dao..*)")
      public void inDataAccessLayer() {}
      /**
       * A business service is the execution of any method defined on a service
       * interface. This definition assumes that interfaces are placed in the
       * "service" package, and that implementation types are in sub-packages.
       *
       * If you group service interfaces by functional area (for example,
       * in packages com.xyz.someapp.abc.service and com.xyz.def.service) then
       * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
       * could be used instead.
       */
      @Pointcut("execution(* com.xyz.someapp.service.*.*(..))")
      public void businessService() {}
      
      /**
       * A data access operation is the execution of any method defined on a
       * dao interface. This definition assumes that interfaces are placed in the
       * "dao" package, and that implementation types are in sub-packages.
       */
      @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
      public void dataAccessOperation() {}
    }
    The pointcuts defined in such an aspect can be referred to anywhere that you
            need a pointcut expression. For example, to make the service layer transactional, you
            could write:
      
       
      
    The  and
            tags are discussed in the section entitled
    Section 6.3, “Schema-based AOP support”
    . The transaction
            tags are discussed in the chapter entitled
    Chapter 9, Transaction management
    .
    6.2.3.4. Examples
    Spring AOP users are likely to use the execution pointcut
         designator the most often. The format of an execution expression is:
    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
              throws-pattern?)
         All parts except the returning type pattern (ret-type-pattern in the snippet above),
             name pattern, and parameters pattern are optional.
         The returning type pattern determines what the return type of the method must be in order
         for a join point to be matched. Most frequently you will use * as the
         returning type pattern, which matches any return type. A fully-qualified type name will
         match only when the method returns the given type. The name pattern matches the method name.
         You can use the * wildcard as all or part of a name pattern. The
         parameters pattern is slightly more complex: () matches a method that takes
         no parameters, whereas (..) matches any number of parameters (zero or more).
         The pattern (*) matches a method taking one parameter of any type,
         (*,String) matches a method taking two parameters, the first can be of
         any type, the second must be a String. Consult the
         
         Language Semantics section of the AspectJ Programming Guide for more
         information.
         
    Some examples of common pointcut expressions are given below.

  • the execution of any public method:
    execution(public * *(..))

  • the execution of any method with a name beginning with "set":
    execution(* set*(..))

  • the execution of any method defined by the AccountService interface:
    execution(* com.xyz.service.AccountService.*(..))

  • the execution of any method defined in the service package:
    execution(* com.xyz.service.*.*(..))

  • the execution of any method defined in the service package or a sub-package:
    execution(* com.xyz.service..*.*(..))

  • any join point (method execution only in Spring AOP) within the service package:
    within(com.xyz.service.*)

  • any join point (method execution only in Spring AOP) within the service package or a sub-package:
    within(com.xyz.service..*)

  • any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
    this(com.xyz.service.AccountService)'this' is more commonly used in a binding form :- see the following section
         on advice for how to make the proxy object available in the advice body.

  • any join point (method execution only in Spring AOP) where the target object implements the AccountService interface:
    target(com.xyz.service.AccountService)'target' is more commonly used in a binding form :- see the following section
         on advice for how to make the target object available in the advice body.

  • any
    join point (method execution only in Spring AOP) which takes a single
    parameter, and where the argument passed at runtime is Serializable:
    args(java.io.Serializable)'args' is more commonly used in a binding form :- see the following section
         on advice for how to make the method arguments available in the advice body.

    Note that the pointcut given in this example is different to
         execution(* *(java.io.Serializable)): the args version matches if
         the argument passed at runtime is Serializable, the execution version matches if the
         method signature declares a single parameter of type Serializable.

  • any join point (method execution only in Spring AOP) where the target object has an @Transactional annotation:
    @target(org.springframework.transaction.annotation.Transactional)'@target' can also be used in a binding form :- see the following section
         on advice for how to make the annotation object available in the advice body.

  • any join point (method execution only in Spring AOP) where the declared type of the target object has an @Transactional annotation:
    @within(org.springframework.transaction.annotation.Transactional)'@within' can also be used in a binding form :- see the following section
         on advice for how to make the annotation object available in the advice body.

  • any join point (method execution only in Spring AOP) where the executing method has an @Transactional annotation:
    @annotation(org.springframework.transaction.annotation.Transactional)'@annotation' can also be used in a binding form :- see the following section
         on advice for how to make the annotation object available in the advice body.

  • any join point (method execution only in Spring AOP) which takes a single parameter, and where the
         runtime type of the argument passed has the @Classified annotation:
    @args(com.xyz.security.Classified)'@args' can also be used in a binding form :- see the following section
         on advice for how to make the annotation object(s) available in the advice body.

                   
                   
                   

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

    本版积分规则 发表回复

      

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

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP