diff --git a/src/docs/asciidoc/core/core-aop-api.adoc b/src/docs/asciidoc/core/core-aop-api.adoc index c1f75e0aae8c5de0ae72c976315d3bebae81a231..f2541e937b175cf0c712737fa9aa308c5fe2a0a1 100644 --- a/src/docs/asciidoc/core/core-aop-api.adoc +++ b/src/docs/asciidoc/core/core-aop-api.adoc @@ -1,14 +1,10 @@ [[aop-api]] = Spring AOP APIs -The previous chapter described the Spring's support for AOP with -@AspectJ and schema-based aspect definitions. In this chapter, we discuss the lower-level -Spring AOP APIs and the AOP support typically used in Spring 1.2 applications. For new -applications, we recommend the use of the Spring 2.0 and later AOP support described in -the previous chapter. However, when you work with existing applications (or when you read books -and articles), you may come across Spring 1.2-style examples. Spring 5 remains backwards -compatible with Spring 1.2, and everything described in this chapter is fully supported -in Spring 5. +The previous chapter described the Spring's support for AOP with @AspectJ and schema-based +aspect definitions. In this chapter, we discuss the lower-level Spring AOP APIs. For common +applications, we recommend the use of Spring AOP with AspectJ pointcuts as described in the +previous chapter. @@ -117,7 +113,7 @@ Since 2.0, the most important type of pointcut used by Spring is `org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that uses an AspectJ-supplied library to parse an AspectJ pointcut expression string. -See the <> for a discussion of supported AspectJ pointcut primitives. +See the <> for a discussion of supported AspectJ pointcut primitives. @@ -253,8 +249,7 @@ following example shows how to subclass `StaticMethodMatcherPointcut`: ==== There are also superclasses for dynamic pointcuts. - -You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above. +You can use custom pointcuts with any advice type. @@ -1046,8 +1041,7 @@ to consider: and included in the spring-core JAR. In other words, CGLIB-based AOP works "`out of the box`", as do JDK dynamic proxies. -There is little performance difference between CGLIB proxying and dynamic proxies. As of -Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. +There is little performance difference between CGLIB proxying and dynamic proxies. Performance should not be a decisive consideration in this case. @@ -1150,7 +1144,7 @@ we override the transaction propagation settings: Note that in the parent bean example, we explicitly marked the parent bean definition as being abstract by setting the `abstract` attribute to `true`, as described -<>, so that it may not actually ever be +<>, so that it may not actually ever be instantiated. Application contexts (but not simple bean factories), by default, pre-instantiate all singletons. Therefore, it is important (at least for singleton beans) that, if you have a (parent) bean definition that you intend to use only as a template, @@ -1290,9 +1284,7 @@ Depending on how you created the proxy, you can usually set a `frozen` flag. In case, the `Advised` `isFrozen()` method returns `true`, and any attempts to modify advice through addition or removal results in an `AopConfigException`. The ability to freeze the state of an advised object is useful in some cases (for example, to -prevent calling code removing a security interceptor). It may also be used in Spring 1.1 -to allow aggressive optimization if runtime advice modification is known not to be -required. +prevent calling code removing a security interceptor). diff --git a/src/docs/asciidoc/core/core-aop.adoc b/src/docs/asciidoc/core/core-aop.adoc index 83ad5afdf9b65750388cd206b771747607f4d5c2..fbaf5c276a797eff53b0c8df430ec66bef3dfbe1 100644 --- a/src/docs/asciidoc/core/core-aop.adoc +++ b/src/docs/asciidoc/core/core-aop.adoc @@ -2,33 +2,31 @@ = Aspect Oriented Programming with Spring Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by -providing another way of thinking about program structure. The key unit of modularity in -OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects +providing another way of thinking about program structure. The key unit of modularity +in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns (such as transaction management) that cut across -multiple types and objects. (Such concerns are often termed "`crosscutting`" concerns in -AOP literature.) +multiple types and objects. (Such concerns are often termed "`crosscutting`" concerns +in AOP literature.) One of the key components of Spring is the AOP framework. While the Spring IoC container does not depend on AOP (meaning you do not 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 AOP with AspectJ pointcuts **** -Spring 2.0 introduced a simpler and more powerful way of writing custom aspects by using -either a <> or the <>. Both of these styles offer fully typed advice and use of the AspectJ pointcut -language while still using Spring AOP for weaving. - -This chapter discusses the Spring 2.0+ schema- and @AspectJ-based AOP support. -The lower-level AOP support, as commonly exposed in Spring 1.2 applications, is -discussed in <>. +Spring provides simple and powerful ways of writing custom aspects by using either a +<> or the <>. +Both of these styles offer fully typed advice and use of the AspectJ pointcut language +while still using Spring AOP for weaving. + +This chapter discusses the schema- and @AspectJ-based AOP support. +The lower-level AOP support is discussed in <>. **** 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 - <>. +* Provide declarative enterprise services. The most important such service is + <>. * Let users implement custom aspects, complementing their use of OOP with AOP. NOTE: If you are interested only in generic declarative services or other pre-packaged @@ -48,7 +46,7 @@ However, it would be even more confusing if Spring used its own terminology. * Aspect: A modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in enterprise Java applications. In Spring AOP, aspects are implemented by using regular classes - (the <>) or regular classes annotated with the + (the <>) or regular classes annotated with the `@Aspect` annotation (the <>). * 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 @@ -104,14 +102,14 @@ the same thing. Using the most specific advice type provides a simpler programmi 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, you 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. +All advice parameters are statically typed so that you work with advice parameters of +the appropriate type (e.g. the type of the return value from a method execution) 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, you can apply an around advice -providing declarative transaction management to a set of methods that span +targeted independently of the object-oriented hierarchy. For example, you can apply an +around advice providing declarative transaction management to a set of methods that span multiple objects (such as all business operations in the service layer). @@ -149,8 +147,8 @@ frameworks such as AspectJ are valuable and that they are complementary, rather competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable all uses of 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. See <> for a -discussion of the Spring AOP APIs. +API. Spring AOP remains backward-compatible. See <> +for a discussion of the Spring AOP APIs. [NOTE] ==== @@ -171,8 +169,8 @@ configuration-style approach. The fact that this chapter chooses to introduce th @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 <> for a more complete discussion of the "`whys and wherefores`" of each -style. +See <> for a more complete discussion of the "`whys and wherefores`" of +each style. ==== @@ -188,7 +186,7 @@ Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather interfaces. By default, CGLIB is used if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes, business classes normally implement one or more business interfaces. It is possible to -<>, in those (hopefully rare) cases where you +<>, 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. @@ -209,8 +207,8 @@ interprets the same annotations as AspectJ 5, using a library supplied by Aspect 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. -NOTE: Using the AspectJ compiler and weaver enables use of the full AspectJ language and is -discussed in <>. +NOTE: Using the AspectJ compiler and weaver enables use of the full AspectJ language and +is discussed in <>. @@ -263,9 +261,9 @@ element, as the following example shows: ==== This assumes that you use schema support as described in -<>. See -<> for how to import the tags in the `aop` -namespace. +<>. +See <> for how to +import the tags in the `aop` namespace. @@ -277,8 +275,8 @@ class that is an @AspectJ aspect (has the `@Aspect` annotation) is automatically detected by Spring and used to configure Spring AOP. The next two examples show the minimal definition required for a not-very-useful aspect. -The first of the two example shows a regular bean definition in the application context that points to a bean class that has -the `@Aspect` annotation: +The first of the two example shows a regular bean definition in the application +context that points to a bean class that has the `@Aspect` annotation: ==== [source,xml,indent=0] @@ -290,8 +288,8 @@ the `@Aspect` annotation: ---- ==== -The second of the two examples shows the `NotVeryUsefulAspect` class definition, which is annotated with -the `org.aspectj.lang.annotation.Aspect` annotation; +The second of the two examples shows the `NotVeryUsefulAspect` class definition, +which is annotated with the `org.aspectj.lang.annotation.Aspect` annotation; ==== [source,java,indent=0] @@ -423,7 +421,7 @@ If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenari potential non-public interactions through proxies, it needs to be defined accordingly. If your interception needs include method calls or even constructors within the target -class, consider the use of Spring-driven <> instead +class, consider the use of Spring-driven <> instead of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving before making a decision. @@ -1097,8 +1095,8 @@ taken by Spring is simpler and a better match to its proxy-based, execution-only semantics. You only need to be aware of this difference if you compile @AspectJ aspects written for Spring and use `proceed` with arguments with the AspectJ compiler and weaver. There is a way to write such aspects that is 100% compatible across both -Spring AOP and AspectJ, and this is discussed in the <>. +Spring AOP and AspectJ, and this is discussed in the +<>. The following example shows how to use around advice: @@ -1654,8 +1652,7 @@ of advice parameters. To use the aop namespace tags described in this section, you need to import the `spring-aop` schema, as described in <>. -See <> +XML Schema-based configuration>>. See <> for how to import the tags in the `aop` namespace. Within your Spring configurations, all aspect and advisor elements must be placed within @@ -1664,10 +1661,11 @@ application context configuration). An `` element can contain pointc advisor, and aspect elements (note that these must be declared in that order). WARNING: The `` style of configuration makes heavy use of Spring's -<> mechanism. This can cause issues (such as advice not -being woven) if you already use explicit auto-proxying through the use of -`BeanNameAutoProxyCreator` or something similar. The recommended usage pattern is to use either -only the `` style or only the `AutoProxyCreator` style and never mix them. +<> mechanism. This can cause issues (such as advice +not being woven) if you already use explicit auto-proxying through the use of +`BeanNameAutoProxyCreator` or something similar. The recommended usage pattern is to +use either only the `` style or only the `AutoProxyCreator` style and +never mix them. @@ -1725,10 +1723,9 @@ be defined as follows: ==== Note that the pointcut expression itself is using the same AspectJ pointcut expression -language as described in <>. If you use the schema based -declaration style, you can refer to named pointcuts defined in types -(@Aspects) within the pointcut expression. Another way of defining the above pointcut -would be as follows: +language as described in <>. If you use the schema based declaration +style, you can refer to named pointcuts defined in types (@Aspects) within the +pointcut expression. Another way of defining the above pointcut would be as follows: ==== [source,xml,indent=0] @@ -2582,11 +2579,11 @@ The downside of the XML approach is that you cannot define the The @AspectJ style supports additional instantiation models and richer pointcut composition. It has the advantage of keeping the aspect as a modular unit. It also has -the advantage that the @AspectJ aspects can be understood (and thus consumed) both by Spring -AOP and by AspectJ. So, if you later decide you need the capabilities of AspectJ to -implement additional requirements, you can easily migrate to an AspectJ-based -approach. On balance, the Spring team prefers the @AspectJ style whenever you have aspects -that do more than simple configuration of enterprise services. +the advantage that the @AspectJ aspects can be understood (and thus consumed) both by +Spring AOP and by AspectJ. So, if you later decide you need the capabilities of AspectJ +to implement additional requirements, you can easily migrate to a classic AspectJ setup. +On balance, the Spring team prefers the @AspectJ style for custom aspects beyond simple +configuration of enterprise services. @@ -2595,10 +2592,9 @@ that do more than simple configuration of enterprise services. == Mixing Aspect Types It is perfectly possible to mix @AspectJ style aspects by using the auto-proxying support, -schema-defined `` aspects, `` declared advisors, and even -proxies and interceptors defined with the Spring 1.2 style in the same configuration. -All of these are implemented by using the same underlying support mechanism and can -co-exist without any difficulty. +schema-defined `` aspects, `` declared advisors, and even proxies +and interceptors in other styles in the same configuration. All of these are implemented +by using the same underlying support mechanism and can co-exist without any difficulty. @@ -2607,29 +2603,26 @@ co-exist without any difficulty. == Proxying Mechanisms Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given -target object. (JDK dynamic proxies are preferred whenever you have a choice). +target object. JDK dynamic proxies are built into the JDK, whereas CGLIB is a common +open-source class definition library (repackaged into `spring-core`). If the target object to be proxied implements at least one interface, a JDK dynamic -proxy is used. All of the interfaces implemented by the target type are -proxied. If the target object does not implement any interfaces, a CGLIB proxy is -created. +proxy is used. All of the interfaces implemented by the target type are proxied. +If the target object does not implement any interfaces, a CGLIB proxy is created. If you want to force the use of CGLIB proxying (for example, to proxy every method -defined for the target object, not only those implemented by its interfaces), you can do -so. However, you should consider the following issues: - -* `final` methods cannot be advised, as they cannot be overridden. -* As of Spring 3.2, it is no longer necessary to add CGLIB to your project classpath, as - CGLIB classes are repackaged under `org.springframework` and included directly in the - spring-core JAR. This means that CGLIB-based proxy support "`just works`", in the same - way that JDK dynamic proxies always have. -* As of Spring 4.0, the constructor of your proxied object is NOT called twice - any more, since the CGLIB proxy instance is created through Objenesis. Only if your - JVM does not allow for constructor bypassing, you might see double invocations and +defined for the target object, not only those implemented by its interfaces), +you can do so. However, you should consider the following issues: + +* With CGLIB, `final` methods cannot be advised, as they cannot be overridden in + runtime-generated subclasses. +* As of Spring 4.0, the constructor of your proxied object is NOT called twice anymore, + since the CGLIB proxy instance is created through Objenesis. Only if your JVM does + not allow for constructor bypassing, you might see double invocations and corresponding debug log entries from Spring's AOP support. -To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute of -the `` element to true, as follows: +To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute +of the `` element to true, as follows: ==== [source,xml,indent=0] @@ -2642,8 +2635,8 @@ the `` element to true, as follows: ==== To force CGLIB proxying when you use the @AspectJ auto-proxy support, set the -`proxy-target-class` attribute of the `` element to `true`, as -follows: +`proxy-target-class` attribute of the `` element to `true`, +as follows: ==== [source,xml,indent=0] @@ -2709,9 +2702,7 @@ image::images/aop-proxy-plain-pojo-call.png[] public class Main { public static void main(String[] args) { - Pojo pojo = new SimplePojo(); - // this is a direct method call on the 'pojo' reference pojo.foo(); } @@ -2731,13 +2722,11 @@ image::images/aop-proxy-call.png[] public class Main { public static void main(String[] args) { - ProxyFactory factory = new ProxyFactory(new SimplePojo()); factory.addInterface(Pojo.class); factory.addAdvice(new RetryAdvice()); Pojo pojo = (Pojo) factory.getProxy(); - // this is a method call on the proxy! pojo.foo(); } @@ -2745,23 +2734,22 @@ image::images/aop-proxy-call.png[] ---- ==== -The key thing to understand here is that the client code inside the `main(..)` method of the -`Main` class has a reference to the proxy. This means that method calls on that -object reference are calls on the proxy. As a result, the proxy can -delegate to all of the interceptors (advice) that are relevant to that particular method -call. However, once the call has finally reached the target object (the `SimplePojo`, -reference in this case), any method calls that it may make on itself, such as -`this.bar()` or `this.foo()`, are going to be invoked against the `this` reference, -and not the proxy. This has important implications. It means that self-invocation is -not going to result in the advice associated with a method invocation getting a -chance to execute. +The key thing to understand here is that the client code inside the `main(..)` method +of the `Main` class has a reference to the proxy. This means that method calls on that +object reference are calls on the proxy. As a result, the proxy can delegate to all of +the interceptors (advice) that are relevant to that particular method call. However, +once the call has finally reached the target object (the `SimplePojo`, reference in +this case), any method calls that it may make on itself, such as `this.bar()` or +`this.foo()`, are going to be invoked against the `this` reference, and not the proxy. +This has important implications. It means that self-invocation is not going to result +in the advice associated with a method invocation getting a chance to execute. -Okay, so what is to be done about this? The best approach (the term, "`best,`" is used loosely -here) is to refactor your code such that the self-invocation does not happen. +Okay, so what is to be done about this? The best approach (the term, "`best,`" is used +loosely here) is to refactor your code such that the self-invocation does not happen. This does entail some work on your part, but it is the best, least-invasive approach. -The next approach is absolutely horrendous, and we hesitate to point it out, -precisely because it is so horrendous. You can (painful as it is to us) totally tie the logic within -your class to Spring AOP, as the following example shows: +The next approach is absolutely horrendous, and we hesitate to point it out, precisely +because it is so horrendous. You can (painful as it is to us) totally tie the logic +within your class to Spring AOP, as the following example shows: ==== [source,java,indent=0] @@ -2793,14 +2781,12 @@ following example shows: public class Main { public static void main(String[] args) { - ProxyFactory factory = new ProxyFactory(new SimplePojo()); factory.adddInterface(Pojo.class); factory.addAdvice(new RetryAdvice()); factory.setExposeProxy(true); Pojo pojo = (Pojo) factory.getProxy(); - // this is a method call on the proxy! pojo.foo(); } @@ -2817,11 +2803,11 @@ it is not a proxy-based AOP framework. [[aop-aspectj-programmatic]] == Programmatic Creation of @AspectJ Proxies -In addition to declaring aspects in your configuration by using either `` or -``, it is also possible to programmatically create proxies that -advise target objects. For the full details of Spring's AOP API, see the <>. -Here, we want to focus on the ability to automatically create proxies by using @AspectJ -aspects. +In addition to declaring aspects in your configuration by using either `` +or ``, it is also possible to programmatically create proxies +that advise target objects. For the full details of Spring's AOP API, see the +<>. Here, we want to focus on the ability to automatically +create proxies by using @AspectJ aspects. You can use the `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` class to create a proxy for a target object that is advised by one or more @AspectJ aspects. @@ -2939,13 +2925,12 @@ Spring now looks for a bean definition named `account` and uses that as the definition to configure new `Account` instances. You can also use autowiring to avoid having to specify a dedicated bean definition at -all. To have Spring apply autowiring, use the `autowire` property of the -`@Configurable` annotation. You can specify either `@Configurable(autowire=Autowire.BY_TYPE)` or +all. To have Spring apply autowiring, use the `autowire` property of the `@Configurable` +annotation. You can specify either `@Configurable(autowire=Autowire.BY_TYPE)` or `@Configurable(autowire=Autowire.BY_NAME` for autowiring by type or by name, -respectively. As an alternative, as of Spring 2.5, it is preferable to specify explicit, -annotation-driven dependency injection for your `@Configurable` beans by using -`@Autowired` or `@Inject` at the field or method level (see <> -for further details). +respectively. As an alternative, it is preferable to specify explicit, annotation-driven +dependency injection for your `@Configurable` beans through `@Autowired` or `@Inject` +at the field or method level (see <> for further details). Finally, you can enable Spring dependency checking for the object references in the newly created and configured object by using the `dependencyCheck` attribute (for example, @@ -2955,13 +2940,13 @@ are not primitives or collections) have been set. Note that using the annotation on its own does nothing. It is the `AnnotationBeanConfigurerAspect` in `spring-aspects.jar` that acts on the presence of -the annotation. In essence, the aspect says, "`after returning from the initialization of a -new object of a type annotated with `@Configurable`, configure the newly created object +the annotation. In essence, the aspect says, "`after returning from the initialization of +a new object of a type annotated with `@Configurable`, configure the newly created object using Spring in accordance with the properties of the annotation`". In this context, -"`initialization`" refers to newly instantiated objects (for example, objects instantiated with -the `new` operator) as well as to `Serializable` objects that are undergoing +"`initialization`" refers to newly instantiated objects (for example, objects instantiated +with the `new` operator) as well as to `Serializable` objects that are undergoing deserialization (for example, through -http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html[readResolve()]). +http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html[readResolve()]). [NOTE] ===== @@ -2978,7 +2963,7 @@ available for use in the body of the constructors, you need to define this on th [source,java,indent=0] [subs="verbatim,quotes"] ---- - @Configurable(preConstruction=true) + @Configurable(preConstruction = true) ---- ==== @@ -3005,7 +2990,6 @@ use Java-based configuration, you can add `@EnableSpringConfigured` to any @Configuration @EnableSpringConfigured public class AppConfig { - } ---- ==== @@ -3143,7 +3127,6 @@ fully qualified class names: initialization(new(..)) && SystemArchitecture.inDomainModel() && this(beanInstance); - } ---- ==== @@ -3231,14 +3214,12 @@ per-`ClassLoader` basis, which is more fine-grained and which can make more sense in a 'single-JVM-multiple-application' environment (such as is found in a typical application server environment). -Further, <>, this support enables +Further, <>, this support enables load-time weaving without making any modifications to the application server's launch -script that is needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we -describe later in this section) -`-javaagent:path/to/org.springframework.instrument-{version}.jar` (previously named -`spring-agent.jar`). Developers modify one or more files that form the -application context to enable load-time weaving instead of relying on administrators who -typically are in charge of the deployment configuration, such as the launch script. +script that is needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we describe +later in this section) `-javaagent:path/to/spring-instrument.jar`. Developers configure +the application context to enable load-time weaving instead of relying on administrators +who typically are in charge of the deployment configuration, such as the launch script. Now that the sales pitch is over, let us first walk through a quick example of AspectJ LTW that uses Spring, followed by detailed specifics about elements introduced in the @@ -3250,18 +3231,18 @@ https://github.com/spring-projects/spring-petclinic[Petclinic sample application ==== A First Example Assume that you are an application developer who has been tasked with diagnosing -the cause of some performance problems in a system. Rather than break out a profiling -tool, we are going to switch on a simple profiling aspect that lets us -quickly get some performance metrics. We can then apply a finer-grained -profiling tool to that specific area immediately afterwards. +the cause of some performance problems in a system. Rather than break out a +profiling tool, we are going to switch on a simple profiling aspect that lets us +quickly get some performance metrics. We can then apply a finer-grained profiling +tool to that specific area immediately afterwards. -NOTE: The example presented here uses XML configuration. You can also -configure and use @AspectJ with <>. -Specifically, you can use the `@EnableLoadTimeWeaving` annotation as an alternative to -`` (see <> for details). +NOTE: The example presented here uses XML configuration. You can also configure and +use @AspectJ with <>. Specifically, you can use the +`@EnableLoadTimeWeaving` annotation as an alternative to `` +(see <> for details). -The following example shows the profiling aspect, which is not fancy -- it is a time-based -profiler that uses the @AspectJ-style of aspect declaration: +The following example shows the profiling aspect, which is not fancy. +It is a time-based profiler that uses the @AspectJ-style of aspect declaration: ==== [source,java,indent=0] @@ -3297,10 +3278,10 @@ profiler that uses the @AspectJ-style of aspect declaration: ---- ==== -We also need to create an `META-INF/aop.xml` file, to inform the AspectJ weaver -that we want to weave our `ProfilingAspect` into our classes. This file convention, -namely the presence of a file (or files) on the Java classpath called -`META-INF/aop.xml` is standard AspectJ. The following example shows the `aop.xml` file: +We also need to create an `META-INF/aop.xml` file, to inform the AspectJ weaver that +we want to weave our `ProfilingAspect` into our classes. This file convention, namely +the presence of a file (or files) on the Java classpath called `META-INF/aop.xml` is +standard AspectJ. The following example shows the `aop.xml` file: ==== [source,xml,indent=0] @@ -3323,12 +3304,13 @@ namely the presence of a file (or files) on the Java classpath called ---- ==== -Now we can move on to the Spring-specific portion of the configuration. We need to configure a -`LoadTimeWeaver` (explained later). This load-time -weaver is the essential component responsible for weaving the aspect configuration in -one or more `META-INF/aop.xml` files into the classes in your application. The good -thing is that it does not require a lot of configuration (there -are some more options that you can specify, but these are detailed later), as can be seen in the following example: +Now we can move on to the Spring-specific portion of the configuration. We need +to configure a `LoadTimeWeaver` (explained later). This load-time weaver is the +essential component responsible for weaving the aspect configuration in one or +more `META-INF/aop.xml` files into the classes in your application. The good +thing is that it does not require a lot of configuration (there are some more +options that you can specify, but these are detailed later), as can be seen in +the following example: ==== [source,xml,indent=0] @@ -3355,8 +3337,8 @@ are some more options that you can specify, but these are detailed later), as ca ==== Now that all the required artifacts (the aspect, the `META-INF/aop.xml` -file, and the Spring configuration) are in place, we can create the following driver class with a -`main(..)` method to demonstrate the LTW in action: +file, and the Spring configuration) are in place, we can create the following +driver class with a `main(..)` method to demonstrate the LTW in action: ==== [source,java,indent=0] @@ -3369,11 +3351,10 @@ file, and the Spring configuration) are in place, we can create the following dr public final class Main { public static void main(String[] args) { - ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml", Main.class); - EntitlementCalculationService entitlementCalculationService - = (EntitlementCalculationService) ctx.getBean("entitlementCalculationService"); + EntitlementCalculationService entitlementCalculationService = + (EntitlementCalculationService) ctx.getBean("entitlementCalculationService"); // the profiling aspect is 'woven' around this method execution entitlementCalculationService.calculateEntitlement(); @@ -3384,8 +3365,8 @@ file, and the Spring configuration) are in place, we can create the following dr We have one last thing to do. The introduction to this section did say that one could switch on LTW selectively on a per-`ClassLoader` basis with Spring, and this is true. -However, for this example, we use a Java agent (supplied with Spring) -to switch on the LTW. We use the following command to run the `Main` class shown earlier: +However, for this example, we use a Java agent (supplied with Spring) to switch on LTW. +We use the following command to run the `Main` class shown earlier: ==== [literal] @@ -3396,7 +3377,7 @@ java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main ==== The `-javaagent` is a flag for specifying and enabling -http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agents +http://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html[agents to instrument programs that run on the JVM]. The Spring Framework ships with such an agent, the `InstrumentationSavingAgent`, which is packaged in the `spring-instrument.jar` that was supplied as the value of the `-javaagent` argument in @@ -3437,11 +3418,10 @@ result: public final class Main { public static void main(String[] args) { - new ClassPathXmlApplicationContext("beans.xml", Main.class); EntitlementCalculationService entitlementCalculationService = - new StubEntitlementCalculationService(); + new StubEntitlementCalculationService(); // the profiling aspect will be 'woven' around this method execution entitlementCalculationService.calculateEntitlement(); @@ -3479,8 +3459,9 @@ Furthermore, the compiled aspect classes need to be available on the classpath. The AspectJ LTW infrastructure is configured by using one or more `META-INF/aop.xml` files that are on the Java classpath (either directly or, more typically, in jar files). -The structure and contents of this file is detailed in the LTW part http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[AspectJ reference -documentation]. Because the aop.xml file is 100% AspectJ, we do not describe it further here. +The structure and contents of this file is detailed in the LTW part of the +http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[AspectJ reference +documentation]. Because the `aop.xml` file is 100% AspectJ, we do not describe it further here. [[aop-aj-ltw-libraries]] @@ -3489,10 +3470,10 @@ documentation]. Because the aop.xml file is 100% AspectJ, we do not describe it At minimum, you need the following libraries to use the Spring Framework's support for AspectJ LTW: -* `spring-aop.jar` (version 2.5 or later, plus all mandatory dependencies) -* `aspectjweaver.jar` (version 1.6.8 or later) +* `spring-aop.jar` +* `aspectjweaver.jar` -If you use the <>, you also need: * `spring-instrument.jar` @@ -3528,7 +3509,6 @@ which typically is done by using the `@EnableLoadTimeWeaving` annotation, as fol @Configuration @EnableLoadTimeWeaving public class AppConfig { - } ---- ==== @@ -3557,50 +3537,50 @@ Alternatively, if you prefer XML-based configuration, use the ---- ==== -The preceding configuration automatically defines and registers a number of LTW-specific infrastructure -beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you. +The preceding configuration automatically defines and registers a number of LTW-specific +infrastructure beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you. The default `LoadTimeWeaver` is the `DefaultContextLoadTimeWeaver` class, which attempts -to decorate an automatically detected `LoadTimeWeaver`. The exact type of -`LoadTimeWeaver` that is "`automatically detected`" is dependent upon your runtime -environment. The following table summarizes various `LoadTimeWeaver` implementations: +to decorate an automatically detected `LoadTimeWeaver`. The exact type of `LoadTimeWeaver` +that is "`automatically detected`" is dependent upon your runtime environment. +The following table summarizes various `LoadTimeWeaver` implementations: [[aop-aj-ltw-spring-env-impls]] .DefaultContextLoadTimeWeaver LoadTimeWeavers |=== | Runtime Environment| `LoadTimeWeaver` implementation -| Running in Oracle's - http://www.oracle.com/technetwork/middleware/weblogic/overview/index-085209.html[WebLogic] -| `WebLogicLoadTimeWeaver` - -| Running in Oracle's http://glassfish.dev.java.net/[GlassFish] -| `GlassFishLoadTimeWeaver` - | Running in http://tomcat.apache.org/[Apache Tomcat] | `TomcatLoadTimeWeaver` +| Running in http://glassfish.dev.java.net/[GlassFish] (limited to EAR deployments) +| `GlassFishLoadTimeWeaver` + | Running in Red Hat's http://www.jboss.org/jbossas/[JBoss AS] or http://www.wildfly.org/[WildFly] | `JBossLoadTimeWeaver` | Running in IBM's http://www-01.ibm.com/software/webservers/appserv/was/[WebSphere] | `WebSphereLoadTimeWeaver` -| JVM started with Spring `InstrumentationSavingAgent` (`java - -javaagent:path/to/spring-instrument.jar`) +| Running in Oracle's + http://www.oracle.com/technetwork/middleware/weblogic/overview/index-085209.html[WebLogic] +| `WebLogicLoadTimeWeaver` + +| JVM started with Spring `InstrumentationSavingAgent` + (`java -javaagent:path/to/spring-instrument.jar`) | `InstrumentationLoadTimeWeaver` -| Fallback, expecting the underlying ClassLoader to follow common conventions (for example - applicable to `TomcatInstrumentableClassLoader` and http://www.caucho.com/[Resin]) +| Fallback, expecting the underlying ClassLoader to follow common conventions + (namely `addTransformer` and optionally a `getThrowawayClassLoader` method) | `ReflectiveLoadTimeWeaver` |=== -Note that the table lists only the `LoadTimeWeavers` that are autodetected when you use the -`DefaultContextLoadTimeWeaver`. You can specify exactly which -`LoadTimeWeaver` implementation to use. +Note that the table lists only the `LoadTimeWeavers` that are autodetected when you +use the `DefaultContextLoadTimeWeaver`. You can specify exactly which `LoadTimeWeaver` +implementation to use. To specify a specific `LoadTimeWeaver` with Java configuration, implement the -`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method. The -following example specifies a `ReflectiveLoadTimeWeaver`: +`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method. +The following example specifies a `ReflectiveLoadTimeWeaver`: ==== [source,java,indent=0] @@ -3652,10 +3632,9 @@ the `org.aspectj.weaver.loadtime` package) class. See the class-level javadoc of `ClassPreProcessorAgentAdapter` class for further details, because the specifics of how the weaving is actually effected is beyond the scope of this document. -There is one final attribute of the configuration left to discuss: the -`aspectjWeaving` attribute (or `aspectj-weaving` if you use XML). This -attribute controls whether LTW is enabled or not. -It accepts one of three possible values, with the default value being +There is one final attribute of the configuration left to discuss: the `aspectjWeaving` +attribute (or `aspectj-weaving` if you use XML). This attribute controls whether LTW +is enabled or not. It accepts one of three possible values, with the default value being `autodetect` if the attribute is not present. The following table summarizes the three possible values: @@ -3686,71 +3665,17 @@ This last section contains any additional settings and configuration that you ne when you use Spring's LTW support in environments such as application servers and web containers. -[[aop-aj-ltw-environment-tomcat]] -===== Tomcat - -Historically, http://tomcat.apache.org/[Apache Tomcat]'s default class loader did not -support class transformation, which is why Spring provides an enhanced implementation -that addresses this need. Named `TomcatInstrumentableClassLoader`, the loader works on -Tomcat 6.0 and above. - -TIP: Do not define `TomcatInstrumentableClassLoader` on Tomcat 8.0 and higher. -Instead, let Spring automatically use Tomcat's new native `InstrumentableClassLoader` -facility through the `TomcatLoadTimeWeaver` strategy. - -If you still need to use `TomcatInstrumentableClassLoader`, you can register it -individually for each web application as follows: - -. Copy `org.springframework.instrument.tomcat.jar` into `$CATALINA_HOME/lib`, where - `$CATALINA_HOME` represents the root of the Tomcat installation -. Instruct Tomcat to use the custom class loader (instead of the default) by editing the - web application context file, as the following example shows: - -==== -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- -==== - -Apache Tomcat 6.0+ supports several context locations: - -* Server configuration file: `$CATALINA_HOME/conf/server.xml` -* Default context configuration: `$CATALINA_HOME/conf/context.xml`, which affects all - deployed web applications -* A per-web application configuration, which can be deployed either on the server-side at - `$CATALINA_HOME/conf/[enginename]/[hostname]/[webapp]-context.xml` or embedded - inside the web-app archive at `META-INF/context.xml` +[[aop-aj-ltw-environments-tomcat-jboss-etc]] +===== Tomcat, JBoss, WebSphere, WebLogic -For efficiency, we recommend the embedded per-web application configuration style, because it -impacts only applications that use the custom class loader and does not require any -changes to the server configuration. See the Tomcat 6.0.x -http://tomcat.apache.org/tomcat-6.0-doc/config/context.html[documentation] for more -details about available context locations. +Tomcat, JBoss/WildFly, IBM WebSphere Application Server and Oracle WebLogic Server all +provide a general app `ClassLoader` that is capable of local instrumentation. Spring's +native LTW may leverage those ClassLoader implementations to provide AspectJ weaving. +You can simply enable load-time weaving, as <>. +Specifically, you do not need to modify the JVM launch script to add +`-javaagent:path/to/spring-instrument.jar`. -Alternatively, consider using the Spring-provided generic VM agent, to be specified -in Tomcat's launch script (described earlier in this section). This makes instrumentation available to all -deployed web applications, no matter the `ClassLoader` on which they happen to run. - -[[aop-aj-ltw-environments-weblogic-oc4j-resin-glassfish-jboss]] -===== WebLogic, WebSphere, Resin, GlassFish, and JBoss - -Recent versions of WebLogic Server (version 10 and above), IBM WebSphere Application -Server (version 7 and above), Resin (version 3.1 and above), and JBoss (version 6.x or above) provide a -`ClassLoader` that is capable of local instrumentation. Spring's native LTW leverages such -ClassLoader implementations to enable AspectJ weaving. You can enable LTW by activating -load-time weaving, as <>. Specifically, you do not need to modify the -launch script to add `-javaagent:path/to/spring-instrument.jar`. - -Note that the GlassFish instrumentation-capable `ClassLoader` is available only in its EAR -environment. For GlassFish web applications, follow the Tomcat setup instructions -<>. - -Note that, on JBoss 6.x, you need to disable the app server scanning to prevent it from +Note that on JBoss, you may need to disable the app server scanning to prevent it from loading the classes before the application actually starts. A quick workaround is to add to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following content: @@ -3762,33 +3687,30 @@ to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following co ---- ==== -[[aop-aj-ltw-environment-generic]] +[[aop-aj-ltw-environments-generic]] ===== Generic Java Applications -When class instrumentation is required in environments that do not support or are not -supported by the existing `LoadTimeWeaver` implementations, a JDK agent can be the only -solution. For such cases, Spring provides `InstrumentationLoadTimeWeaver`, which -requires a Spring-specific (but very general) VM agent, -`org.springframework.instrument-{version}.jar` (previously named `spring-agent.jar`). +When class instrumentation is required in environments that are not supported by +specific `LoadTimeWeaver` implementations, a JVM agent is the general solution. +For such cases, Spring provides `InstrumentationLoadTimeWeaver` which requires a +Spring-specific (but very general) JVM agent, `spring-instrument.jar`, autodetected +by common `@EnableLoadTimeWeaving` and `` setups. -To use it, you must start the virtual machine with the Spring agent by supplying the -following JVM options: +To use it, you must start the virtual machine with the Spring agent by supplying +the following JVM options: ==== [literal] [subs="verbatim,quotes"] ---- --javaagent:/path/to/org.springframework.instrument-{version}.jar +-javaagent:/path/to/spring-instrument.jar ---- ==== -Note that this requires modification of the VM launch script, which may prevent you from -using this in application server environments (depending on your operation policies). -Additionally, the JDK agent instruments the entire VM, which can be expensive. - -For performance reasons, we recommend that you use this configuration only if your target -environment (such as http://www.eclipse.org/jetty/[Jetty]) does not have (or does not -support) a dedicated LTW. +Note that this requires modification of the JVM launch script, which may prevent you +from using this in application server environments (depending on your server and your +operation policies). That said, for one-app-per-JVM deployments such as standalone +Spring Boot applications, you typically control the entire JVM setup in any case.