|
|
|
|
@ -3,7 +3,7 @@
@@ -3,7 +3,7 @@
|
|
|
|
|
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
|
|
|
|
<appendix id="classic-aop-spring"> |
|
|
|
|
<title>Classic Spring AOP Usage</title> |
|
|
|
|
<section id="aop-classic-introduction"> |
|
|
|
|
<section id="classic-aop-classic-introduction"> |
|
|
|
|
<para>In this chapter we discuss |
|
|
|
|
the lower-level Spring AOP APIs and the AOP support used in Spring 1.2 applications. |
|
|
|
|
For new applications, we recommend the use of the Spring 2.0 AOP support |
|
|
|
|
@ -15,12 +15,12 @@
@@ -15,12 +15,12 @@
|
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts"> |
|
|
|
|
<section id="classic-aop-api-pointcuts"> |
|
|
|
|
<title>Pointcut API in Spring</title> |
|
|
|
|
|
|
|
|
|
<para>Let's look at how Spring handles the crucial pointcut concept.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-concepts"> |
|
|
|
|
<section id="classic-aop-api-concepts"> |
|
|
|
|
<title>Concepts</title> |
|
|
|
|
|
|
|
|
|
<para>Spring's pointcut model enables pointcut reuse independent of |
|
|
|
|
@ -88,7 +88,7 @@
@@ -88,7 +88,7 @@
|
|
|
|
|
</tip> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcut-ops"> |
|
|
|
|
<section id="classic-aop-api-pointcut-ops"> |
|
|
|
|
<title>Operations on pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>Spring supports operations on pointcuts: notably, |
|
|
|
|
@ -115,7 +115,7 @@
@@ -115,7 +115,7 @@
|
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-aspectj"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-aspectj"> |
|
|
|
|
<title>AspectJ expression pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>Since 2.0, the most important type of pointcut used by Spring is |
|
|
|
|
@ -128,14 +128,14 @@
@@ -128,14 +128,14 @@
|
|
|
|
|
</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-impls"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-impls"> |
|
|
|
|
<title>Convenience pointcut implementations</title> |
|
|
|
|
|
|
|
|
|
<para>Spring provides several convenient pointcut implementations. Some |
|
|
|
|
can be used out of the box; others are intended to be subclassed in |
|
|
|
|
application-specific pointcuts.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-static"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-static"> |
|
|
|
|
<title>Static pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>Static pointcuts are based on method and target class, and |
|
|
|
|
@ -148,7 +148,7 @@
@@ -148,7 +148,7 @@
|
|
|
|
|
<para>Let's consider some static pointcut implementations included |
|
|
|
|
with Spring.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-regex"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-regex"> |
|
|
|
|
<title>Regular expression pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>One obvious way to specify static pointcuts is regular |
|
|
|
|
@ -204,7 +204,7 @@
@@ -204,7 +204,7 @@
|
|
|
|
|
with any Advice type.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-attribute-driven"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-attribute-driven"> |
|
|
|
|
<title>Attribute-driven pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>An important type of static pointcut is a |
|
|
|
|
@ -213,7 +213,7 @@
@@ -213,7 +213,7 @@
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-dynamic"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-dynamic"> |
|
|
|
|
<title>Dynamic pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>Dynamic pointcuts are costlier to evaluate than static |
|
|
|
|
@ -225,7 +225,7 @@
@@ -225,7 +225,7 @@
|
|
|
|
|
<para>The main example is the <literal>control flow</literal> |
|
|
|
|
pointcut.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-cflow"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-cflow"> |
|
|
|
|
<title>Control flow pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>Spring control flow pointcuts are conceptually similar to |
|
|
|
|
@ -247,7 +247,7 @@
@@ -247,7 +247,7 @@
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-superclasses"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-superclasses"> |
|
|
|
|
<title>Pointcut superclasses</title> |
|
|
|
|
|
|
|
|
|
<para>Spring provides useful pointcut superclasses to help you to |
|
|
|
|
@ -269,7 +269,7 @@
@@ -269,7 +269,7 @@
|
|
|
|
|
RC2 and above.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-pointcuts-custom"> |
|
|
|
|
<section id="classic-aop-api-pointcuts-custom"> |
|
|
|
|
<title>Custom pointcuts</title> |
|
|
|
|
|
|
|
|
|
<para>Because pointcuts in Spring AOP are Java classes, rather than |
|
|
|
|
@ -286,12 +286,12 @@
@@ -286,12 +286,12 @@
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice"> |
|
|
|
|
<section id="classic-aop-api-advice"> |
|
|
|
|
<title>Advice API in Spring</title> |
|
|
|
|
|
|
|
|
|
<para>Let's now look at how Spring AOP handles advice.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-lifecycle"> |
|
|
|
|
<section id="classic-aop-api-advice-lifecycle"> |
|
|
|
|
<title>Advice lifecycles</title> |
|
|
|
|
|
|
|
|
|
<para>Each advice is a Spring bean. An advice instance can be shared across all |
|
|
|
|
@ -313,14 +313,14 @@
@@ -313,14 +313,14 @@
|
|
|
|
|
the same AOP proxy.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-types"> |
|
|
|
|
<section id="classic-aop-api-advice-types"> |
|
|
|
|
<title>Advice types in Spring</title> |
|
|
|
|
|
|
|
|
|
<para>Spring provides several advice types out of the box, and is |
|
|
|
|
extensible to support arbitrary advice types. Let us look at the basic |
|
|
|
|
concepts and standard advice types.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-around"> |
|
|
|
|
<section id="classic-aop-api-advice-around"> |
|
|
|
|
<title>Interception around advice</title> |
|
|
|
|
|
|
|
|
|
<para>The most fundamental advice type in Spring is |
|
|
|
|
@ -373,7 +373,7 @@
@@ -373,7 +373,7 @@
|
|
|
|
|
pointcut interfaces.</para></note> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-before"> |
|
|
|
|
<section id="classic-aop-api-advice-before"> |
|
|
|
|
<title>Before advice</title> |
|
|
|
|
|
|
|
|
|
<para>A simpler advice type is a <emphasis role="bold">before |
|
|
|
|
@ -424,7 +424,7 @@
@@ -424,7 +424,7 @@
|
|
|
|
|
<tip><para>Before advice can be used with any pointcut.</para></tip> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-throws"> |
|
|
|
|
<section id="classic-aop-api-advice-throws"> |
|
|
|
|
<title>Throws advice</title> |
|
|
|
|
|
|
|
|
|
<para><emphasis role="bold">Throws advice</emphasis> is invoked after |
|
|
|
|
@ -492,7 +492,7 @@
@@ -492,7 +492,7 @@
|
|
|
|
|
<tip><para>Throws advice can be used with any pointcut.</para></tip> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-after-returning"> |
|
|
|
|
<section id="classic-aop-api-advice-after-returning"> |
|
|
|
|
<title>After Returning advice</title> |
|
|
|
|
|
|
|
|
|
<para>An after returning advice in Spring must implement the |
|
|
|
|
@ -533,7 +533,7 @@
@@ -533,7 +533,7 @@
|
|
|
|
|
<tip><para>After returning advice can be used with any pointcut.</para></tip> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advice-introduction"> |
|
|
|
|
<section id="classic-aop-api-advice-introduction"> |
|
|
|
|
<title>Introduction advice</title> |
|
|
|
|
<para>Spring treats introduction advice as a special kind of |
|
|
|
|
interception advice.</para> |
|
|
|
|
@ -752,7 +752,7 @@ public interface IntroductionInfo {
@@ -752,7 +752,7 @@ public interface IntroductionInfo {
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advisor"> |
|
|
|
|
<section id="classic-aop-api-advisor"> |
|
|
|
|
<title>Advisor API in Spring</title> |
|
|
|
|
|
|
|
|
|
<para>In Spring, an Advisor is an aspect that contains just a single advice |
|
|
|
|
@ -771,7 +771,7 @@ public interface IntroductionInfo {
@@ -771,7 +771,7 @@ public interface IntroductionInfo {
|
|
|
|
|
automatically create the necessary interceptor chain.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-pfb"> |
|
|
|
|
<section id="classic-aop-pfb"> |
|
|
|
|
<title>Using the ProxyFactoryBean to create AOP proxies</title> |
|
|
|
|
|
|
|
|
|
<para>If you're using the Spring IoC container (an ApplicationContext or |
|
|
|
|
@ -790,7 +790,7 @@ public interface IntroductionInfo {
@@ -790,7 +790,7 @@ public interface IntroductionInfo {
|
|
|
|
|
and their ordering. However, there are simpler options that are preferable |
|
|
|
|
if you don't need such control.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-pfb-1"> |
|
|
|
|
<section id="classic-aop-pfb-1"> |
|
|
|
|
<title>Basics</title> |
|
|
|
|
|
|
|
|
|
<para>The <literal>ProxyFactoryBean</literal>, like other Spring |
|
|
|
|
@ -813,7 +813,7 @@ public interface IntroductionInfo {
@@ -813,7 +813,7 @@ public interface IntroductionInfo {
|
|
|
|
|
pluggability provided by Dependency Injection.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-pfb-2"> |
|
|
|
|
<section id="classic-aop-pfb-2"> |
|
|
|
|
<title>JavaBean properties</title> |
|
|
|
|
<para> |
|
|
|
|
In common with most <interfacename>FactoryBean</interfacename> implementations |
|
|
|
|
@ -931,7 +931,7 @@ public interface IntroductionInfo {
@@ -931,7 +931,7 @@ public interface IntroductionInfo {
|
|
|
|
|
</itemizedlist> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-pfb-proxy-types"> |
|
|
|
|
<section id="classic-aop-pfb-proxy-types"> |
|
|
|
|
<title>JDK- and CGLIB-based proxies</title> |
|
|
|
|
<para> |
|
|
|
|
This section serves as the definitive documentation on how the |
|
|
|
|
@ -1005,7 +1005,7 @@ public interface IntroductionInfo {
@@ -1005,7 +1005,7 @@ public interface IntroductionInfo {
|
|
|
|
|
|
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-proxying-intf"> |
|
|
|
|
<section id="classic-aop-api-proxying-intf"> |
|
|
|
|
<title>Proxying interfaces</title> |
|
|
|
|
|
|
|
|
|
<para> |
|
|
|
|
@ -1129,7 +1129,7 @@ public interface IntroductionInfo {
@@ -1129,7 +1129,7 @@ public interface IntroductionInfo {
|
|
|
|
|
example, in certain test scenarios.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-proxying-class"> |
|
|
|
|
<section id="classic-aop-api-proxying-class"> |
|
|
|
|
<title>Proxying classes</title> |
|
|
|
|
|
|
|
|
|
<para>What if you need to proxy a class, rather than one or more |
|
|
|
|
@ -1176,7 +1176,7 @@ public interface IntroductionInfo {
@@ -1176,7 +1176,7 @@ public interface IntroductionInfo {
|
|
|
|
|
decisive consideration in this case.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-global-advisors"> |
|
|
|
|
<section id="classic-aop-global-advisors"> |
|
|
|
|
<title>Using 'global' advisors</title> |
|
|
|
|
|
|
|
|
|
<para>By appending an asterisk to an interceptor name, all advisors with |
|
|
|
|
@ -1198,7 +1198,7 @@ public interface IntroductionInfo {
@@ -1198,7 +1198,7 @@ public interface IntroductionInfo {
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-concise-proxy"> |
|
|
|
|
<section id="classic-aop-concise-proxy"> |
|
|
|
|
<title>Concise proxy definitions</title> |
|
|
|
|
|
|
|
|
|
<para>Especially when defining transactional proxies, you may end up with |
|
|
|
|
@ -1261,7 +1261,7 @@ public interface IntroductionInfo {
@@ -1261,7 +1261,7 @@ public interface IntroductionInfo {
|
|
|
|
|
it.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-prog"> |
|
|
|
|
<section id="classic-aop-prog"> |
|
|
|
|
<title>Creating AOP proxies programmatically with the ProxyFactory</title> |
|
|
|
|
|
|
|
|
|
<para>It's easy to create AOP proxies programmatically using Spring. This |
|
|
|
|
@ -1298,7 +1298,7 @@ MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();</programlisti
@@ -1298,7 +1298,7 @@ MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();</programlisti
|
|
|
|
|
</tip> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-advised"> |
|
|
|
|
<section id="classic-aop-api-advised"> |
|
|
|
|
<title>Manipulating advised objects</title> |
|
|
|
|
|
|
|
|
|
<para>However you create AOP proxies, you can manipulate them using the |
|
|
|
|
@ -1392,7 +1392,7 @@ assertEquals("Added two advisors",
@@ -1392,7 +1392,7 @@ assertEquals("Added two advisors",
|
|
|
|
|
advice modification is known not to be required.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-autoproxy"> |
|
|
|
|
<section id="classic-aop-autoproxy"> |
|
|
|
|
<title>Using the "autoproxy" facility</title> |
|
|
|
|
|
|
|
|
|
<para>So far we've considered explicit creation of AOP proxies using a |
|
|
|
|
@ -1423,13 +1423,13 @@ assertEquals("Added two advisors",
@@ -1423,13 +1423,13 @@ assertEquals("Added two advisors",
|
|
|
|
|
</listitem> |
|
|
|
|
</itemizedlist> |
|
|
|
|
|
|
|
|
|
<section id="aop-autoproxy-choices"> |
|
|
|
|
<section id="classic-aop-autoproxy-choices"> |
|
|
|
|
<title>Autoproxy bean definitions</title> |
|
|
|
|
|
|
|
|
|
<para>The <literal>org.springframework.aop.framework.autoproxy</literal> |
|
|
|
|
package provides the following standard autoproxy creators.</para> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-autoproxy"> |
|
|
|
|
<section id="classic-aop-api-autoproxy"> |
|
|
|
|
<title>BeanNameAutoProxyCreator</title> |
|
|
|
|
|
|
|
|
|
<para>The <literal>BeanNameAutoProxyCreator</literal> class is a |
|
|
|
|
@ -1465,7 +1465,7 @@ assertEquals("Added two advisors",
@@ -1465,7 +1465,7 @@ assertEquals("Added two advisors",
|
|
|
|
|
differently to different beans.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-autoproxy-default"> |
|
|
|
|
<section id="classic-aop-api-autoproxy-default"> |
|
|
|
|
<title>DefaultAdvisorAutoProxyCreator</title> |
|
|
|
|
|
|
|
|
|
<para>A more general and extremely powerful auto proxy creator is |
|
|
|
|
@ -1544,7 +1544,7 @@ assertEquals("Added two advisors",
@@ -1544,7 +1544,7 @@ assertEquals("Added two advisors",
|
|
|
|
|
configurable order value; the default setting is unordered.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-autoproxy-abstract"> |
|
|
|
|
<section id="classic-aop-api-autoproxy-abstract"> |
|
|
|
|
<title>AbstractAdvisorAutoProxyCreator</title> |
|
|
|
|
|
|
|
|
|
<para>This is the superclass of DefaultAdvisorAutoProxyCreator. You |
|
|
|
|
@ -1555,7 +1555,7 @@ assertEquals("Added two advisors",
@@ -1555,7 +1555,7 @@ assertEquals("Added two advisors",
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-autoproxy-metadata"> |
|
|
|
|
<section id="classic-aop-autoproxy-metadata"> |
|
|
|
|
<title>Using metadata-driven auto-proxying</title> |
|
|
|
|
|
|
|
|
|
<para>A particularly important type of autoproxying is driven by |
|
|
|
|
@ -1703,7 +1703,7 @@ assertEquals("Added two advisors",
@@ -1703,7 +1703,7 @@ assertEquals("Added two advisors",
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-targetsource"> |
|
|
|
|
<section id="classic-aop-targetsource"> |
|
|
|
|
<title>Using TargetSources</title> |
|
|
|
|
|
|
|
|
|
<para>Spring offers the concept of a <emphasis>TargetSource</emphasis>, |
|
|
|
|
@ -1732,7 +1732,7 @@ assertEquals("Added two advisors",
@@ -1732,7 +1732,7 @@ assertEquals("Added two advisors",
|
|
|
|
|
Spring to create a new target instance when required.</para> |
|
|
|
|
</tip> |
|
|
|
|
|
|
|
|
|
<section id="aop-ts-swap"> |
|
|
|
|
<section id="classic-aop-ts-swap"> |
|
|
|
|
<title>Hot swappable target sources</title> |
|
|
|
|
|
|
|
|
|
<para>The |
|
|
|
|
@ -1773,7 +1773,7 @@ Object oldTarget = swapper.swap(newTarget);</programlisting></para>
@@ -1773,7 +1773,7 @@ Object oldTarget = swapper.swap(newTarget);</programlisting></para>
|
|
|
|
|
with arbitrary advice.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-ts-pool"> |
|
|
|
|
<section id="classic-aop-ts-pool"> |
|
|
|
|
<title>Pooling target sources</title> |
|
|
|
|
|
|
|
|
|
<para>Using a pooling target source provides a similar programming model |
|
|
|
|
@ -1857,7 +1857,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
@@ -1857,7 +1857,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
|
|
|
|
|
set the TargetSources used by any autoproxy creator.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-ts-prototype"> |
|
|
|
|
<section id="classic-aop-ts-prototype"> |
|
|
|
|
<title>Prototype target sources</title> |
|
|
|
|
|
|
|
|
|
<para>Setting up a "prototype" target source is similar to a pooling |
|
|
|
|
@ -1881,7 +1881,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
@@ -1881,7 +1881,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
|
|
|
|
|
must be a prototype bean definition.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-ts-threadlocal"> |
|
|
|
|
<section id="classic-aop-ts-threadlocal"> |
|
|
|
|
<title><classname>ThreadLocal</classname> target sources</title> |
|
|
|
|
|
|
|
|
|
<para><classname>ThreadLocal</classname> target sources are useful if you need an object to be |
|
|
|
|
@ -1912,7 +1912,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
@@ -1912,7 +1912,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
|
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-extensibility"> |
|
|
|
|
<section id="classic-aop-extensibility"> |
|
|
|
|
<title>Defining new <interfacename>Advice</interfacename> types</title> |
|
|
|
|
|
|
|
|
|
<para>Spring AOP is designed to be extensible. While the interception |
|
|
|
|
@ -1931,7 +1931,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
@@ -1931,7 +1931,7 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]></programlisting>
|
|
|
|
|
Javadocs for further information.</para> |
|
|
|
|
</section> |
|
|
|
|
|
|
|
|
|
<section id="aop-api-resources"> |
|
|
|
|
<section id="classic-aop-api-resources"> |
|
|
|
|
<title>Further resources</title> |
|
|
|
|
|
|
|
|
|
<para>Please refer to the Spring sample applications for further examples |
|
|
|
|
|