Aspect-oriented programming (AOP) complements object-oriented programming (OOP) by providing a different way of thinking about program structure. The key unit of modularity in OOP is the class, while in AOP the unit of modularity is the aspect. Aspects allow for a modular organization of functionality (such as transaction management) that spans multiple types and objects. (In the AOP literature, this functionality is often called "crosscutting.")

One of the key components of Spring is the AOP framework. Although Spring's IoC container is independent of AOP (meaning you don't have to use AOP if you don't want to), AOP complements Spring IoC, resulting in a very adequate middleware solution.

Spring AOP using slices from AspectJ

Spring offers simple and full-featured ways to write custom aspects with using either the schema-based approach or the @AspectJ annotation style. Both of these styles support fully typed Advice and the ability to use the AspectJ slicing language, but still use Spring AOP for binding.

This chapter covers support for schema-based AOP and @AspectJ.

AOP is used in the Spring Framework to:

  • Provide declarative enterprise services. The most important such service is declarative transaction management.

  • Allows users to implement special aspects, complementing the use of OOP with AOP.

If you are only interested in generic declarative services or other no-prep declarative middleware services such as pooling, then you won't have to work directly with Spring AOP, so you can safely skip most of this chapter.

AOP Concepts

Let's start by defining some basic AOP concepts and terminology. These terms are not Spring specific. Unfortunately, AOP terminology is not particularly intuitive. However, it gets even more confusing if Spring uses its own terminology.

  • Aspect: A modularly organized functionality (concern) that spans multiple classes. Transaction management is a good example of end-to-end functionality in enterprise Java applications. In Spring AOP, aspects are implemented using regular classes (schema-based approach) or regular classes annotated with the @Aspect annotation (@AspectJ style).

  • Joint point: A point during program execution, such as executing a method or handling an exception. In Spring AOP, a connection point always represents the execution of a method.

  • Advice: The action taken by an aspect at a specific connection point. The different types of Advice include Advice "around", "before" and "after". (Advice types will be discussed further). Many AOP frameworks, including Spring, model Advice as an interceptor and support a chain of interceptors instead of a join point.

  • Pointcut: A predicate that matches join points. Advice is associated with a slice expression and is executed at any connection point that matches the slice (for example, executing a method with a specific name). The concept of join points mapped to slice expressions is central to AOP, and Spring uses the AspectJ slice expression language by default.

  • Introduction: Declaring additional methods or fields on behalf of type. Spring AOP allows you to implement new interfaces (and corresponding implementation) into any Advice-enabled object. For example, you can use injection to force the bean to implement the IsModified interface to facilitate caching. (In the AspectJ community, an introduction is known as an intertype declaration.)

  • Target object: An object that is supplied with Advice on one or more aspects. Also called an Advice-supplied object. Because Spring AOP is implemented using dynamic proxies, this object is always a proxied object.

  • AOP Proxy: An object created by the AOP framework to implement aspect contracts (provides Advice with method execution and so on). In the Spring Framework, an AOP proxy is a dynamic JDK proxy or a CGLIB proxy.

  • Weaving: Binding aspects with other application types or objects to create an advice-equipped object. It can be produced at compile time (for example, using the AspectJ compiler), at load time, or at program runtime. Spring AOP, like other pure Java AOP frameworks, does the binding at runtime.

Spring AOP includes the following types of tips:

  • Before tip: A tip that runs before the join point, but has no way of preventing thread of execution from going to the join point (unless it throws an exception).

  • Hint "after returning": Advice that will be executed after the connection point has exited normally (for example, if the method returns without throwing an exception).

  • Throwing tip: The tip that will be executed if the method exits by throwing an exception.

  • After tip (finally)": The advice must be executed regardless of the way the join point is exited (either a regular or an exceptional return).

  • Around tip: A hint that surrounds the join point , such as calling a method. This is the most effective type of advice. The "instead" advice can follow special operating logic before and after the method call. It is also responsible for choosing whether to jump to a join point or shortcut the recommended method by returning its own return value or throwing an exception.

The "instead" advice is the most general one type of advice. Since Spring AOP, like AspectJ, provides a full range of advice types, we recommend using the least powerful advice type that can implement the required operating logic. For example, if you only need to update the cache with the return value of a method, then it is better to implement the after-return advice than the instead-advice, although the instead-advice can do the same thing. Using the most specific type of advice provides a simpler programming model with less chance of errors. For example, you don't need to call the proceed() method on the JoinPoint used for the "instead" advice, and therefore you can't avoid calling it.

All advice parameters are statically typed, so you work with advice parameters of the appropriate type (for example, the return value type when executing a method), rather than with Object arrays.

The concept of junction points , mapped to slices, is the key to understanding AOP, which distinguishes it from older technologies that only offer interception. Slices allow advice to be addressed independently of the object-oriented hierarchy. For example, you can apply the "instead" advice, which provides declarative transaction management, to a set of methods that span multiple objects (for example, all business operations at the service level).

Spring AOP Features and Goals

Spring AOP is implemented in pure Java. There is no need for a special compilation process. Spring AOP does not require class loader hierarchy management and is therefore suitable for use in a servlet container or application server.

Spring AOP currently only supports method execution junction points (providing method execution advice to 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 like AspectJ.

Spring AOP's approach to AOP is different from most other AOP frameworks. The goal is not to provide the most complete implementation of AOP (although Spring AOP is quite capable of that). Rather, the goal is to provide tight integration between an AOP implementation and Spring IoC, which will help solve common problems in enterprise applications.

For example, the AOP functionality in the Spring Framework is typically used in conjunction with IoC. Spring container. Aspects are configured using the normal bean definition syntax (although this allows for high-performance "auto-proxy" capabilities). This is a fundamental difference from other AOP implementations. You won't be able to do some things easily and efficiently with Spring AOP, such as providing advice to extremely small-scale objects (usually domain objects). AspectJ is the best choice in such cases. However, our experience has been that Spring AOP provides an excellent solution to most problems in enterprise Java applications that lend themselves to AOP.

Spring AOP has in no way attempted to compete with AspectJ in providing a comprehensive solution for AOP. We believe that both proxy-based frameworks such as Spring AOP and full-fledged frameworks such as AspectJ are valuable and complement each other rather than compete. Spring seamlessly integrates Spring AOP and IoC with AspectJ, allowing you to use AOP 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.

One of the core principles of the Spring Framework is non-invasiveness. The idea is to not force you to implement framework-specific classes and interfaces into your business or domain model. However, at some points the Spring Framework gives you the ability to inject Spring Framework-specific dependencies into your codebase. The point of providing such capabilities is that in certain scenarios it may simply be easier to read or code certain functionality this way. However, the Spring Framework (almost) always offers a choice: You have the opportunity to make an informed decision about which option is best for your specific use case or use case.

One such choice that is relevant to this chapter, this is the choice of an AOP framework (and AOP style). You have the following choices: AspectJ, Spring AOP, or both. You also have the choice of either an @AspectJ annotation style approach or a Spring XML configuration style approach. The fact that we chose to present the @AspectJ style approach first in this chapter should not be taken as an indication that the Spring team favors the @AspectJ annotation style approach over the Spring XML configuration style approach.

AOP Proxy

Spring AOP uses standard JDK dynamic proxies for AOP proxies by default. This allows you to proxy any interface (or set of interfaces).

Spring AOP can also use a CGLIB proxy. They are needed to proxy classes, not interfaces. By default, CGLIB is used if the business object does not implement the interface. Because it is recommended to program interfaces rather than classes, business classes typically implement one or more business interfaces. You can force the use of CGLIB in those (hopefully rare) cases where you need to provide advice to a method not declared in an interface, or when you need to pass a method proxied object as a concrete type.

It is important to understand that Spring AOP is based on a proxy.