| | + title | Ref. /chapter[1]/title[1] |
| Original | Traduction | Spring AOP: Aspect Oriented Programming with Spring |
| sect1
| | + title | Ref. /chapter[1]/sect1[1]/title[1] |
| Original | Traduction | Concepts |
|
| + para | Ref. /chapter[1]/sect1[1]/para[1] |
| Original | Traduction | Aspect-Oriented Programming
(AOP) complements OOP by providing another way of
thinking about program structure. While OO decomposes applications into a
hierarchy of objects, AOP decomposes programs into
aspects or concerns. This
enables modularization of concerns such as transaction management that
would otherwise cut across multiple objects. (Such concerns are often
termed crosscutting concerns.) |
|
| + para | Ref. /chapter[1]/sect1[1]/para[2] |
| Original | Traduction | One of the key components of Spring is the AOP
framework. While the Spring IoC containers (BeanFactory and
ApplicationContext) do 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. |
|
| + para | Ref. /chapter[1]/sect1[1]/para[3] |
| Original | Traduction | AOP is used in Spring: |
|
| + para | Ref. /chapter[1]/sect1[1]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | 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 Spring's transaction abstraction. |
|
| + para | Ref. /chapter[1]/sect1[1]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | To allow users to implement custom aspects, complementing their
use of OOP with AOP. |
|
| + para | Ref. /chapter[1]/sect1[1]/para[4] |
| Original | Traduction | Thus you can view Spring AOP as either an enabling technology that
allows Spring to provide declarative transaction management without EJB;
or use the full power of the Spring AOP framework to implement custom
aspects. |
|
| + remark | Ref. /chapter[1]/sect1[1]/remark[1] |
| Original | Traduction | 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. |
| sect2
| | + title | Ref. /chapter[1]/sect1[1]/sect2[1]/title[1] |
| Original | Traduction | AOP concepts |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/para[1] |
| Original | Traduction | 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. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Aspect: A modularization of a concern for
which the implementation might otherwise cut across multiple
objects. Transaction management is a good example of a crosscutting
concern in J2EE applications. Aspects are implemented using Spring
as Advisors or interceptors. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | Joinpoint: Point during the execution of
a program, such as a method invocation or a particular exception
being thrown. In Spring AOP, a joinpoint is always method
invocation. Spring does not use the term joinpoint prominently;
joinpoint information is accessible through methods on the
MethodInvocation argument passed to interceptors,
and is evaluated by implementations of the
org.springframework.aop.Pointcut
interface. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[3]/para[1] |
| Original | Traduction | Advice: Action taken by the AOP framework
at a particular joinpoint. Different types of advice include
"around," "before" and "throws" advice. Advice types are discussed
below. Many AOP frameworks, including Spring, model an advice as an
interceptor, maintaining a chain of
interceptors "around" the joinpoint. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[4]/para[1] |
| Original | Traduction | Pointcut: A set of joinpoints specifying
when an advice should fire. An AOP framework must allow developers
to specify pointcuts: for example, using regular expressions. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[5]/para[1] |
| Original | Traduction | Introduction: Adding methods or fields to
an advised class. Spring allows you to introduce new interfaces to
any advised object. For example, you could use an introduction to
make any object implement an IsModified
interface, to simplify caching. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[6]/para[1] |
| Original | Traduction | Target object: Object containing the
joinpoint. Also referred to as advised or
proxied object. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[7]/para[1] |
| Original | Traduction | AOP proxy: Object created by the AOP
framework, including advice. In Spring, an AOP proxy will be a JDK
dynamic proxy or a CGLIB proxy. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[1]/listitem[8]/para[1] |
| Original | Traduction | Weaving: Assembling aspects to create an
advised object. This can be done at compile time (using the AspectJ
compiler, for example), or at runtime. Spring, like other pure Java
AOP frameworks, performs weaving at runtime. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/para[2] |
| Original | Traduction | Different advice types include: |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[2]/listitem[1]/para[1] |
| Original | Traduction | Around advice: Advice that surrounds a
joinpoint such as a method invocation. This is the most powerful
kind of advice. Around advices will perform custom behavior before
and after the method invocation. They are responsible for choosing
whether to proceed to the joinpoint or to shortcut executing by
returning their own return value or throwing an exception. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[2]/listitem[2]/para[1] |
| Original | Traduction | Before advice: Advice that executes
before a joinpoint, but which does not have the ability to prevent
execution flow proceeding to the joinpoint (unless it throws an
exception). |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[2]/listitem[3]/para[1] |
| Original | Traduction | Throws advice: Advice to be executed if a
method throws an exception. Spring provides strongly typed throws
advice, so you can write code that catches the exception (and
subclasses) you're interested in, without needing to cast from
Throwable or Exception. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/itemizedlist[2]/listitem[4]/para[1] |
| Original | Traduction | After returning advice: Advice to be
executed after a joinpoint completes normally: for example, if a
method returns without throwing an exception. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/para[3] |
| Original | Traduction | Around advice is the most general kind of advice. Most
interception-based AOP frameworks, such as Nanning Aspects, provide only
around advice. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/para[4] |
| Original | Traduction | As Spring, 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 don't need to invoke the proceed()
method on the MethodInvocation used for around advice, and hence can't
fail to invoke it. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[1]/para[5] |
| Original | Traduction | The pointcut concept is the key to AOP, distinguishing AOP from
older technologies offering interception. Pointcuts enable advice to be
targeted independently of the OO hierarchy. For example, an around
advice providing declarative transaction management can be applied to a
set of methods spanning multiple objects. Thus pointcuts provide the
structural element of AOP. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[1]/sect2[2]/title[1] |
| Original | Traduction | Spring AOP capabilities and goals |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[1] |
| Original | Traduction | 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. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[2] |
| Original | Traduction | Spring currently supports interception of method invocations.
Field interception is not implemented, although support for field
interception could be added without breaking the core Spring AOP
APIs. |
|
| + remark | Ref. /chapter[1]/sect1[1]/sect2[2]/remark[1] |
| Original | Traduction | Field interception arguably violates OO encapsulation. We don't
believe it is wise in application development. If you require field
interception, consider using AspectJ. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[3] |
| Original | Traduction | Spring provides classes to represent pointcuts and different
advice types. Spring uses the term advisor for an
object representing an aspect, including both an advice and a pointcut
targeting it to specific joinpoints. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[4] |
| Original | Traduction | Different advice types are MethodInterceptor
(from the AOP Alliance interception API); and the advice interfaces
defined in the org.springframework.aop package. All
advices must implement the org.aopalliance.aop.Advice
tag interface. Advices supported out the box are
MethodInterceptor ; ThrowsAdvice;
BeforeAdvice; and
AfterReturningAdvice. We'll discuss advice types in
detail below. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[5] |
| Original | Traduction | Spring implements the AOP Alliance
interception interfaces (http://www.sourceforge.net/projects/aopalliance).
Around advice must implement the AOP Alliance
org.aopalliance.intercept.MethodInterceptor
interface. Implementations of this interface can run in Spring or any
other AOP Alliance compliant implementation. Currently JAC implements
the AOP Alliance interfaces, and Nanning and Dynaop are likely to in
early 2004. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[6] |
| Original | Traduction | Spring'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. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[7] |
| Original | Traduction | Thus, for example, Spring's AOP functionality is normally used in
conjunction with a Spring IoC container. AOP advice is specified using
normal bean definition syntax (although this allows powerful
"autoproxying" capabilities); advice and pointcuts are themselves
managed by Spring IoC: a crucial difference from other AOP
implementations. There are some things you can't do easily or
efficiently with Spring AOP, such as advise very fine-grained objects.
AspectJ is probably 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. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[2]/para[8] |
| Original | Traduction | Spring AOP will never strive to compete with AspectJ or
AspectWerkz to provide a comprehensive AOP solution. We believe that
both proxy-based frameworks like Spring and full-blown frameworks such
as AspectJ are valuable, and that they are complementary, rather than in
competition. Thus a major priority for Spring 1.1 will be seamlessly
integrating 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 will not affect the Spring AOP API or the
AOP Alliance API; Spring AOP will remain backward-compatible. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[1]/sect2[3]/title[1] |
| Original | Traduction | AOP Proxies in Spring |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[3]/para[1] |
| Original | Traduction | Spring defaults to using J2SE dynamic proxies
for AOP proxies. This enables any interface or set of interfaces to be
proxied. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[3]/para[2] |
| Original | Traduction | Spring can also use CGLIB proxies. This is necessary to proxy
classes, rather than interfaces. CGLIB is used by default if a business
object doesn't implement an interface. As it's good practice to
program to interfaces rather than classes, business
objects normally will implement one or more business interfaces. |
|
| + para | Ref. /chapter[1]/sect1[1]/sect2[3]/para[3] |
| Original | Traduction | It is possible to force the use of CGLIB: we'll discuss this
below, and explain why you'd want to do this. |
|
| + remark | Ref. /chapter[1]/sect1[1]/sect2[3]/remark[1] |
| Original | Traduction | Beyond Spring 1.0, Spring may offer additional types of AOP
proxy, including wholly generated classes. This won't affect the
programming model. |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[2]/title[1] |
| Original | Traduction | Pointcuts in Spring |
|
| + para | Ref. /chapter[1]/sect1[2]/para[1] |
| Original | Traduction | Let's look at how Spring handles the crucial pointcut
concept. |
| sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[1]/title[1] |
| Original | Traduction | Concepts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[1] |
| Original | Traduction | Spring's pointcut model enables pointcut reuse independent of
advice types. It's possible to target different advice using the same
pointcut. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[2] |
| Original | Traduction | The org.springframework.aop.Pointcut interface
is the central interface, used to target advices to particular classes
and methods. The complete interface is shown below: |
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[1]/programlisting[1] |
| Original | Traduction | public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
} |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[3] |
| Original | Traduction | Splitting the Pointcut interface into two parts
allows reuse of class and method matching parts, and fine-grained
composition operations (such as performing a "union" with another method
matcher). |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[4] |
| Original | Traduction | The ClassFilter interface is used to restrict
the pointcut to a given set of target classes. If the
matches() method always returns true, all target
classes will be matched: |
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[1]/programlisting[2] |
| Original | Traduction | public interface ClassFilter {
boolean matches(Class clazz);
} |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[5] |
| Original | Traduction | The MethodMatcher interface is normally more
important. The complete interface is shown below: |
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[1]/programlisting[3] |
| Original | Traduction | public interface MethodMatcher {
boolean matches(Method m, Class targetClass);
boolean isRuntime();
boolean matches(Method m, Class targetClass, Object[] args);
} |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[6] |
| Original | Traduction | The matches(Method, Class) method is used to
test whether this pointcut will ever match a given method on a target
class. This evaluation can be performed when an AOP proxy is created, to
avoid the need for a test on every method invocation. If the 2-argument
matches method returns true for a given method, and the
isRuntime() method for the MethodMatcher returns
true, the 3-argument matches method will be invoked on every method
invocation. This enables a pointcut to look at the arguments passed to
the method invocation immediately before the target advice is to
execute. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[1]/para[7] |
| Original | Traduction | Most MethodMatchers are static, meaning that their
isRuntime() method returns false. In this case, the
3-argument matches method will never be invoked. |
|
| + remark | Ref. /chapter[1]/sect1[2]/sect2[1]/remark[1] |
| Original | Traduction | If possible, try to make pointcuts static, allowing the AOP
framework to cache the results of pointcut evaluation when an AOP proxy
is created. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[2]/title[1] |
| Original | Traduction | Operations on pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[1] |
| Original | Traduction | Spring supports operations on pointcuts: notably,
union and intersection. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[2] |
| Original | Traduction | Union means the methods that either pointcut matches. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[3] |
| Original | Traduction | Intersection means the methods that both pointcuts match. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[4] |
| Original | Traduction | Union is usually more useful. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[2]/para[5] |
| Original | Traduction | Pointcuts can be composed using the static methods in the
org.springframework.aop.support.Pointcuts class, or
using the ComposablePointcut class in the same
package. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[3]/title[1] |
| Original | Traduction | Convenience pointcut implementations |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/para[1] |
| Original | Traduction | Spring provides several convenient pointcut implementations. Some
can be used out of the box; others are intended to be subclassed in
application-specific pointcuts. |
|
| + title | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/title[1] |
| Original | Traduction | Static pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/para[1] |
| Original | Traduction | Static pointcuts are based on method and target class, and
cannot take into account the method's arguments. Static pointcuts are
sufficient--and best--for most usages. It's possible for Spring to
evaluate a static pointcut only once, when a method is first invoked:
after that, there is no need to evaluate the pointcut again with each
method invocation. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/para[2] |
| Original | Traduction | Let's consider some static pointcut implementations included
with Spring. |
|
| + title | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/title[1] |
| Original | Traduction | Regular expression pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[1] |
| Original | Traduction | One obvious way to specific static pointcuts is regular
expressions. Several AOP frameworks besides Spring make this
possible.
org.springframework.aop.support.RegexpMethodPointcut
is a generic regular expression pointcut, using Perl 5 regular
expression syntax. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[2] |
| Original | Traduction | Using this class, you can provide a list of pattern Strings.
If any of these is a match, the pointcut will evaluate to true. (So
the result is effectively the union of these pointcuts.) |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[3] |
| Original | Traduction | The usage is shown below: |
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[4]/programlisting[1] |
| Original | Traduction | <bean id="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.RegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*get.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[5] |
| Original | Traduction | A convenience subclass of
RegexpMethodPointcut,
RegexpMethodPointcutAdvisor, allows us to
reference an Advice also. (Remember that an Advice can be an
interceptor, before advice, throws advice etc.) This simplifies
wiring, as the one bean serves as both pointcut and advisor, as
shown below: |
|
| + programlisting | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[6]/programlisting[1] |
| Original | Traduction | <bean id="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="beanNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*get.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/para[7] |
| Original | Traduction | RegexpMethodPointcutAdvisor can be used
with any Advice type. |
|
| + remark | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[1]/remark[1] |
| Original | Traduction | The RegexpMethodPointcut class requires the Jakarta ORO
regular expression package. |
|
| + title | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[2]/title[1] |
| Original | Traduction | Attribute-driven pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[1]/sect4[2]/para[1] |
| Original | Traduction | An important type of static pointcut is a
metadata-driven pointcut. This uses the values
of metadata attributes: typically, source-level metadata. |
|
| + title | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[2]/title[1] |
| Original | Traduction | Dynamic pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[2]/para[1] |
| Original | Traduction | Dynamic pointcuts are costlier to evaluate than static
pointcuts. They take into account method
arguments, as well as static information. This
means that they must be evaluated with every method invocation; the
result cannot be cached, as arguments will vary. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[2]/para[2] |
| Original | Traduction | The main example is the control flow
pointcut. |
|
| + title | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[2]/sect4[1]/title[1] |
| Original | Traduction | Control flow pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[2]/sect4[1]/para[1] |
| Original | Traduction | Spring control flow pointcuts are conceptually similar to
AspectJ cflow pointcuts, although less
powerful. (There is currently no way to specify that a pointcut
executes below another pointcut.) A control flow pointcut matches
the current call stack. For example, it might fire if the joinpoint
was invoked by a method in the com.mycompany.web
package, or by the SomeCaller class. Control flow
pointcuts are specified using the
org.springframework.aop.support.ControlFlowPointcut
class.
| + para | Ref. /chapter[1]/sect1[2]/sect2[3]/sect3[2]/sect4[1]/para[1]/note[1]/para[1] |
| Original | Traduction | Control flow pointcuts are significantly more expensive to
evaluate at runtime than even other dynamic pointcuts. In Java
1.4, the cost is about 5 times that of other dynamic pointcuts;
in Java 1.3 more than 10. |
|
|
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[4]/title[1] |
| Original | Traduction | Pointcut superclasses |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[4]/para[1] |
| Original | Traduction | Spring provides useful pointcut superclasses to help you to
implement your own pointcuts. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[4]/para[2] |
| Original | Traduction | Because static pointcuts are most useful, you'll probably subclass
StaticMethodMatcherPointcut, as shown below. This requires implemented
just one abstract method (although it's possible to override other
methods to customize behavior): |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[4]/para[3] |
| Original | Traduction | | + programlisting | Ref. /chapter[1]/sect1[2]/sect2[4]/para[3]/programlisting[1] |
| Original | Traduction | class TestStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
// return true if custom criteria match
}
} |
| There are also superclasses for dynamic pointcuts. |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[4]/para[4] |
| Original | Traduction | You can use custom pointcuts with any advice type in Spring 1.0
RC2 and above. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[2]/sect2[5]/title[1] |
| Original | Traduction | Custom pointcuts |
|
| + para | Ref. /chapter[1]/sect1[2]/sect2[5]/para[1] |
| Original | Traduction | Because pointcuts in Spring are Java classes, rather than language
features (as in AspectJ) it's possible to declare custom pointcuts,
whether static or dynamic. However, there is no support out of the box
for the sophisticated pointcut expressions that can be coded in AspectJ
syntax. However, custom pointcuts in Spring can be arbitrarily
complex. |
|
| + remark | Ref. /chapter[1]/sect1[2]/sect2[5]/remark[1] |
| Original | Traduction | Later versions of Spring may offer support for "semantic
pointcuts" as offered by JAC: for example, "all methods that change
instance variables in the target object." |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[3]/title[1] |
| Original | Traduction | Advice types in Spring |
|
| + para | Ref. /chapter[1]/sect1[3]/para[1] |
| Original | Traduction | Let's now look at how Spring AOP handles advice. |
| sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[1]/title[1] |
| Original | Traduction | Advice lifecycles |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[1] |
| Original | Traduction | Spring advices can be shared across all advised objects, or unique
to each advised object. This corresponds to
per-class or per-instance
advice. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[2] |
| Original | Traduction | Per-class advice is used most often. It is appropriate for generic
advice such as transaction advisors. These do not depend on the state of
the proxied object or add new state; they merely act on the method and
arguments. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[3] |
| Original | Traduction | Per-instance advice is appropriate for introductions, to support
mixins. In this case, the advice adds state to the proxied
object. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[1]/para[4] |
| Original | Traduction | It's possible to use a mix of shared and per-instance advice in
the same AOP proxy. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[3]/sect2[2]/title[1] |
| Original | Traduction | Advice types in Spring |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/para[1] |
| Original | Traduction | 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. |
|
| + title | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/title[1] |
| Original | Traduction | Interception around advice |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/para[1] |
| Original | Traduction | The most fundamental advice type in Spring is
interception around advice. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/para[2] |
| Original | Traduction | Spring is compliant with the AOP Alliance interface for around
advice using method interception. MethodInterceptors implementing
around advice should implement the following interface: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/programlisting[1] |
| Original | Traduction | public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/para[3] |
| Original | Traduction | The MethodInvocation argument to the
invoke() method exposes the method being invoked;
the target joinpoint; the AOP proxy; and the arguments to the method.
The invoke() method should return the
invocation's result: the return value of the joinpoint. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/para[4] |
| Original | Traduction | A simple MethodInterceptor implementation
looks as follows: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/programlisting[2] |
| Original | Traduction | public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before: invocation=[" + invocation + "]");
Object rval = invocation.proceed();
System.out.println("Invocation returned");
return rval;
}
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/para[5] |
| Original | Traduction | Note the call to the MethodInvocation's
proceed() method. This proceeds down the
interceptor chain towards the joinpoint. Most interceptors will invoke
this method, and return its return value. However, a
MethodInterceptor, like any around advice, can return a different
value or throw an exception rather than invoke the proceed method.
However, you don't want to do this without good reason! |
|
| + remark | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[1]/remark[1] |
| Original | Traduction | MethodInterceptors offer interoperability with other AOP
Alliance-compliant AOP implementations. The other advice types
discussed in the remainder of this section implement common AOP
concepts, but in a Spring-specific way. While there is an advantage in
using the most specific advice type, stick with MethodInterceptor
around advice if you are likely to want to run the aspect in another
AOP framework. Note that pointcuts are not currently interoperable
between frameworks, and the AOP Alliance does not currently define
pointcut interfaces. |
|
| + title | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/title[1] |
| Original | Traduction | Before advice |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/para[1] |
| Original | Traduction | A simpler advice type is a before
advice. This does not need a
MethodInvocation object, since it will only be
called before entering the method. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/para[2] |
| Original | Traduction | The main advantage of a before advice is that there is no need
to invoke the proceed() method, and therefore no
possibility of inadvertently failing to proceed down the interceptor
chain. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/para[3] |
| Original | Traduction | The MethodBeforeAdvice interface is shown
below. (Spring's API design would allow for field before advice,
although the usual objects apply to field interception and it's
unlikely that Spring will ever implement it). |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/programlisting[1] |
| Original | Traduction | public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method m, Object[] args, Object target) throws Throwable;
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/para[4] |
| Original | Traduction | Note the the return type is void. Before
advice can insert custom behavior before the joinpoint executes, but
cannot change the return value. If a before advice throws an
exception, this will abort further execution of the interceptor chain.
The exception will propagate back up the interceptor chain. If it is
unchecked, or on the signature of the invoked method, it will be
passed directly to the client; otherwise it will be wrapped in an
unchecked exception by the AOP proxy. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/para[5] |
| Original | Traduction | An example of a before advice in Spring, which counts all
methods that return normally: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/programlisting[2] |
| Original | Traduction | public class CountingBeforeAdvice implements MethodBeforeAdvice {
private int count;
public void before(Method m, Object[] args, Object target) throws Throwable {
++count;
}
public int getCount() {
return count;
}
} |
|
| + remark | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[2]/remark[1] |
| Original | Traduction | Before advice can be used with any pointcut. |
|
| + title | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/title[1] |
| Original | Traduction | Throws advice |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/para[1] |
| Original | Traduction | Throws advice is invoked after
the return of the joinpoint if the joinpoint threw an exception.
Spring offers typed throws advice. Note that this means that the
org.springframework.aop.ThrowsAdvice interface does
not contain any methods: it is a tag interface identifying that the
given object implements one or more typed throws advice methods. These
should be of form |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/programlisting[1] |
| Original | Traduction | afterThrowing([Method], [args], [target], subclassOfThrowable) |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/para[2] |
| Original | Traduction | Only the last argument is required. Thus there from one to four
arguments, depending on whether the advice method is interested in the
method and arguments. The following are examples of throws
advices. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/para[3] |
| Original | Traduction | This advice will be invoked if a
RemoteException is thrown (including
subclasses): |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/programlisting[2] |
| Original | Traduction | public class RemoteThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/para[4] |
| Original | Traduction | The following advice is invoked if a
ServletException is thrown. Unlike the above
advice, it declares 4 arguments, so that it has access to the invoked
method, method arguments and target object: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/programlisting[3] |
| Original | Traduction | public static class ServletThrowsAdviceWithArguments implements ThrowsAdvice {
public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
// Do something will all arguments
}
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/para[5] |
| Original | Traduction | The final example illustrates how these two methods could be
used in a single class, which handles both
RemoteException and
ServletException. Any number of throws advice
methods can be combined in a single class. |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/programlisting[4] |
| Original | Traduction | public static class CombinedThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
// Do something will all arguments
}
} |
|
| + remark | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[3]/remark[1] |
| Original | Traduction | Throws advice can be used with any pointcut. |
|
| + title | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/title[1] |
| Original | Traduction | After Returning advice |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/para[1] |
| Original | Traduction | An after returning advice in Spring must implement the
org.springframework.aop.AfterReturningAdvice
interface, shown below: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/programlisting[1] |
| Original | Traduction | public interface AfterReturningAdvice extends Advice {
void afterReturning(Object returnValue, Method m, Object[] args, Object target)
throws Throwable;
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/para[2] |
| Original | Traduction | An after returning advice has access to the return value (which
it cannot modify), invoked method, methods arguments and
target. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/para[3] |
| Original | Traduction | The following after returning advice counts all successful
method invocations that have not thrown exceptions: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/programlisting[2] |
| Original | Traduction | public class CountingAfterReturningAdvice implements AfterReturningAdvice {
private int count;
public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable {
++count;
}
public int getCount() {
return count;
}
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/para[4] |
| Original | Traduction | This advice doesn't change the execution path. If it throws an
exception, this will be thrown up the interceptor chain instead of the
return value. |
|
| + remark | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[4]/remark[1] |
| Original | Traduction | After returning advice can be used with any pointcut. |
|
| + title | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/title[1] |
| Original | Traduction | Introduction advice |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[1] |
| Original | Traduction | Spring treats introduction advice as a special kind of
interception advice. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[2] |
| Original | Traduction | Introduction requires an IntroductionAdvisor,
and an IntroductionInterceptor, implementing the
following interface: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/programlisting[1] |
| Original | Traduction | public interface IntroductionInterceptor extends MethodInterceptor {
boolean implementsInterface(Class intf);
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[3] |
| Original | Traduction | The invoke() method inherited from the AOP
Alliance MethodInterceptor interface must implement
the introduction: that is, if the invoked method is on an introduced
interface, the introduction interceptor is responsible for handling
the method call--it cannot invoke proceed(). |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[4] |
| Original | Traduction | Introduction advice cannot be used with any pointcut, as it
applies only at class, rather than method, level. You can only use
introduction advice with the InterceptionIntroductionAdvisor, which
has the following methods: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/programlisting[2] |
| Original | Traduction | public interface InterceptionIntroductionAdvisor extends InterceptionAdvisor {
ClassFilter getClassFilter();
IntroductionInterceptor getIntroductionInterceptor();
Class[] getInterfaces();
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[5] |
| Original | Traduction | There is no MethodMatcher, and hence no
Pointcut, associated with introduction advice. Only
class filtering is logical. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[6] |
| Original | Traduction | The getInterfaces() method returns the
interfaces introduced by this advisor. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[7] |
| Original | Traduction | Let's look at a simple example from the Spring test suite. Let's
suppose we want to introduce the following interface to one or more
objects: |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[8]/programlisting[1] |
| Original | Traduction | public interface Lockable {
void lock();
void unlock();
boolean locked();
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[9] |
| Original | Traduction | This illustrates a mixin. We
want to be able to cast advised objects to Lockable, whatever their
type, and call lock and unlock methods. If we call the lock() method,
we want all setter methods to throw a
LockedException. Thus we can add an aspect that
provides the ability to make objects immutable, without them having
any knowledge of it: a good example of AOP. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[10] |
| Original | Traduction | Firstly, we'll need an
IntroductionInterceptor that does the heavy
lifting. In this case, we extend the
org.springframework.aop.support.DelegatingIntroductionInterceptor
convenience class. We could implement IntroductionInterceptor
directly, but using
DelegatingIntroductionInterceptor is best for most
cases. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[11] |
| Original | Traduction | The DelegatingIntroductionInterceptor is
designed to delegate an introduction to an actual implementation of
the introduced interface(s), concealing the use of interception to do
so. The delegate can be set to any object using a constructor
argument; the default delegate (when the no-arg constructor is used)
is this. Thus in the example below, the delegate is the
LockMixin subclass of
DelegatingIntroductionInterceptor. Given a delegate
(by default itself) a
DelegatingIntroductionInterceptor instance looks
for all interfaces implemented by the delegate (other than
IntroductionInterceptor), and will support introductions against any
of them. It's possible for subclasses such as
LockMixin to call the
suppressInterflace(Class intf) method to suppress
interfaces that should not be exposed. However, no matter how many
interfaces an IntroductionInterceptor is prepared
to support, the IntroductionAdvisor used will
control which interfaces are actually exposed. An introduced interface
will conceal any implementation of the same interface by the
target. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[12] |
| Original | Traduction | Thus LockMixin subclasses
DelegatingIntroductionInterceptor and implements
Lockable itself. The superclass automatically picks up that Lockable
can be supported for introduction, so we don't need to specify that.
We could introduce any number of interfaces in this way. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[13] |
| Original | Traduction | Note the use of the locked instance variable.
This effectively adds additional state to that held in the target
object. |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[14]/programlisting[1] |
| Original | Traduction | public class LockMixin extends DelegatingIntroductionInterceptor
implements Lockable {
private boolean locked;
public void lock() {
this.locked = true;
}
public void unlock() {
this.locked = false;
}
public boolean locked() {
return this.locked;
}
public Object invoke(MethodInvocation invocation) throws Throwable {
if (locked() && invocation.getMethod().getName().indexOf("set") == 0)
throw new LockedException();
return super.invoke(invocation);
}
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[15] |
| Original | Traduction | Often it isn't necessary to override the invoke()
method: the
DelegatingIntroductionInterceptor
implementation--which calls the delegate method if the method is
introduced, otherwise proceeds towards the joinpoint--is usually
sufficient. In the present case, we need to add a check: no setter
method can be invoked if in locked mode. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[16] |
| Original | Traduction | The introduction advisor required is simple. All it needs to do
is hold a distinct LockMixin instance, and specify
the introduced interfaces--in this case, just
Lockable. A more complex example might take a
reference to the introduction interceptor (which would be defined as a
prototype): in this case, there's no configuration relevant for a
LockMixin, so we simply create it using
new. |
|
| + programlisting | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[17]/programlisting[1] |
| Original | Traduction | public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
public LockMixinAdvisor() {
super(new LockMixin(), Lockable.class);
}
} |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[18] |
| Original | Traduction | We can apply this advisor very simply: it requires no
configuration. (However, it is necessary: It's
impossible to use an IntroductionInterceptor
without an IntroductionAdvisor.) As usual with
introductions, the advisor must be per-instance, as it is stateful. We
need a different instance of LockMixinAdvisor, and
hence LockMixin, for each advised object. The
advisor comprises part of the advised object's state. |
|
| + para | Ref. /chapter[1]/sect1[3]/sect2[2]/sect3[5]/para[19] |
| Original | Traduction | We can apply this advisor programmatically, using the
Advised.addAdvisor() method, or (the recommended
way) in XML configuration, like any other advisor. All proxy creation
choices discussed below, including "auto proxy creators," correctly
handle introductions and stateful mixins. |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[4]/title[1] |
| Original | Traduction | Advisors in Spring |
|
| + para | Ref. /chapter[1]/sect1[4]/para[1] |
| Original | Traduction | In Spring, an Advisor is a modularization of an aspect. Advisors
typically incorporate both an advice and a pointcut. |
|
| + para | Ref. /chapter[1]/sect1[4]/para[2] |
| Original | Traduction | Apart from the special case of introductions, any advisor can be
used with any advice.
org.springframework.aop.support.DefaultPointcutAdvisor
is the most commonly used advisor class. For example, it can be used with
a MethodInterceptor, BeforeAdvice or
ThrowsAdvice. |
|
| + para | Ref. /chapter[1]/sect1[4]/para[3] |
| Original | Traduction | It is possible to mix advisor and advice types in Spring in the same
AOP proxy. For example, you could use a interception around advice, throws
advice and before advice in one proxy configuration: Spring will
automatically create the necessary create interceptor chain. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[5]/title[1] |
| Original | Traduction | Using the ProxyFactoryBean to create AOP proxies |
|
| + para | Ref. /chapter[1]/sect1[5]/para[1] |
| Original | Traduction | If you're using the Spring IoC container (an ApplicationContext or
BeanFactory) for your business objects--and you should be!--you will want
to use one of Spring's AOP FactoryBeans. (Remember that a factory bean
introduces a layer of indirection, enabling it to create objects of a
different type). |
|
| + para | Ref. /chapter[1]/sect1[5]/para[2] |
| Original | Traduction | The basic way to create an AOP proxy in Spring is to use the
org.springframework.aop.framework.ProxyFactoryBean.
This gives complete control over the pointcuts and advice that will apply,
and their ordering. However, there are simpler options that are preferable
if you don't need such control. |
| sect2
| | + title | Ref. /chapter[1]/sect1[5]/sect2[1]/title[1] |
| Original | Traduction | Basics |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[1]/para[1] |
| Original | Traduction | The ProxyFactoryBean, like other Spring
FactoryBean implementations, introduces a level of
indirection. If you define a ProxyFactoryBean with
name foo, what objects referencing
foo see is not the
ProxyFactoryBean instance itself, but an object
created by the ProxyFactoryBean's implementation of
the getObject() method. This method will create an
AOP proxy wrapping a target object. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[1]/para[2] |
| Original | Traduction | One of the most important benefits of using a
ProxyFactoryBean or other IoC-aware class to create
AOP proxies, is that it means that advices and pointcuts can also be
managed by IoC. This is a powerful feature, enabling certain approaches
that are hard to achieve with other AOP frameworks. For example, an
advice may itself reference application objects (besides the target,
which should be available in any AOP framework), benefiting from all the
pluggability provided by Dependency Injection. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[5]/sect2[2]/title[1] |
| Original | Traduction | JavaBean properties |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/para[1] |
| Original | Traduction | Like most FactoryBean implementations provided with Spring,
ProxyFactoryBean is itself a JavaBean. Its properties
are used to: |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Specify the target you want to proxy |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | Specify whether to use CGLIB |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/para[2] |
| Original | Traduction | Some key properties are inherited from
org.springframework.aop.framework.ProxyConfig: the
superclass for all AOP proxy factories. These include: |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[2]/listitem[1]/para[1] |
| Original | Traduction | proxyTargetClass: true if we should proxy
the target class, rather than its interfaces. If this is true we
need to use CGLIB. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[2]/listitem[2]/para[1] |
| Original | Traduction | optimize: whether to apply aggressive
optimization to created proxies. Don't use this setting unless you
understand how the relevant AOP proxy handles optimization. This is
currently used only for CGLIB proxies; it has no effect with JDK
dynamic proxies (the default). |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[2]/listitem[3]/para[1] |
| Original | Traduction | frozen: whether advice changes should be
disallowed once the proxy factory has been configured. Default is
false. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[2]/listitem[4]/para[1] |
| Original | Traduction | exposeProxy: whether the current proxy
should be exposed in a ThreadLocal so that it can be accessed by the
target. (It's available via the MethodInvocation without the need
for a ThreadLocal.) If a target needs to obtain the proxy and
exposeProxy is true, the target can use the
AopContext.currentProxy() method. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[2]/listitem[5]/para[1] |
| Original | Traduction | aopProxyFactory: the implementation of
AopProxyFactory to use. Offers a way of customizing whether to use
dynamic proxies, CGLIB or any other proxy strategy. The default
implementation will choose dynamic proxies or CGLIB appropriately.
There should be no need to use this property; it's intended to allow
the addition of new proxy types in Spring 1.1. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/para[3] |
| Original | Traduction | Other properties specific to ProxyFactoryBean
include: |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[3]/listitem[1]/para[1] |
| Original | Traduction | proxyInterfaces: array of String interface
names. If this isn't supplied, a CGLIB proxy for the target class
will be used |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[3]/listitem[2]/para[1] |
| Original | Traduction | interceptorNames: String array of Advisor,
interceptor or other advice names to apply. Ordering is significant.
The names are bean names in the current factory, including bean
names from ancestor factories. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[2]/itemizedlist[3]/listitem[3]/para[1] |
| Original | Traduction | singleton: whether or not the factory should return a single
object, no matter how often the getObject()
method is called. Several FactoryBean
implementations offer such a method. Default value is true. If you
want to use stateful advice--for example, for stateful mixins--use
prototype advices along with a singleton value of false. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[5]/sect2[3]/title[1] |
| Original | Traduction | Proxying interfaces |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[1] |
| Original | Traduction | Let's look at a simple example of ProxyFactoryBean in action. This
example involves: |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | A target bean that will be proxied. This
is the "personTarget" bean definition in the example below. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | An Advisor and an Interceptor used to provide advice. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/itemizedlist[1]/listitem[3]/para[1] |
| Original | Traduction | An AOP proxy bean definition specifying the target object (the
personTarget bean) and the interfaces to proxy, along with the
advices to apply. |
|
| + programlisting | Ref. /chapter[1]/sect1[5]/sect2[3]/para[2]/programlisting[1] |
| Original | Traduction | <bean id="personTarget" class="com.mycompany.PersonImpl">
<property name="name"><value>Tony</value></property>
<property name="age"><value>51</value></property>
</bean>
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty"><value>Custom string property value</value></property>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>
<bean id="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>com.mycompany.Person</value></property>
<property name="target"><ref local="personTarget"/></property>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[3] |
| Original | Traduction | Note that the interceptorNames property takes a
list of String: the bean names of the interceptor or advisors in the
current factory. Advisors, interceptors, before, after returning and
throws advice objects can be used. The ordering of advisors is
significant. |
|
| + remark | Ref. /chapter[1]/sect1[5]/sect2[3]/remark[1] |
| Original | Traduction | You might be wondering why the list doesn't hold bean
references. The reason for this is that if the ProxyFactoryBean's
singleton property is set to false, it must be able to return
independent proxy instances. If any of the advisors is itself a
prototype, an independent instance would need to be returned, so it's
necessary to be able to obtain an instance of the prototype from the
factory; holding a reference isn't sufficient. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[4] |
| Original | Traduction | The "person" bean definition above can be used in place of a
Person implementation, as follows: |
|
| + programlisting | Ref. /chapter[1]/sect1[5]/sect2[3]/programlisting[1] |
| Original | Traduction | Person person = (Person) factory.getBean("person"); |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[5] |
| Original | Traduction | Other beans in the same IoC context can express a strongly typed
dependency on it, as with an ordinary Java object: |
|
| + programlisting | Ref. /chapter[1]/sect1[5]/sect2[3]/para[6]/programlisting[1] |
| Original | Traduction | <bean id="personUser" class="com.mycompany.PersonUser">
<property name="person"><ref local="person" /></property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[7] |
| Original | Traduction | The PersonUser class in this example would
expose a property of type Person. As far as it's concerned, the AOP
proxy can be used transparently in place of a "real" person
implementation. However, its class would be a dynamic proxy class. It
would be possible to cast it to the Advised interface
(discussed below). |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[8] |
| Original | Traduction | It's possible to conceal the distinction between target and proxy
using an anonymous inner bean, as follows. Only the
ProxyFactoryBean definition is different; the advice
is included only for completeness: |
|
| + programlisting | Ref. /chapter[1]/sect1[5]/sect2[3]/para[9]/programlisting[1] |
| Original | Traduction | <bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty"><value>Custom string property value</value></property>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>
<bean id="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>com.mycompany.Person</value></property>
<!-- Use inner bean, not local reference to target -->
<property name="target">
<bean class="com.mycompany.PersonImpl">
<property name="name"><value>Tony</value></property>
<property name="age"><value>51</value></property>
</bean>
</property>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[3]/para[10] |
| Original | Traduction | This has the advantage that there's only one object of type
Person: useful if we want to prevent users of the
application context obtaining a reference to the un-advised object, or
need to avoid any ambiguity with Spring IoC
autowiring. There's also arguably an advantage in
that the ProxyFactoryBean definition is self-contained. However, there
are times when being able to obtain the un-advised target from the
factory might actually be an advantage: for
example, in certain test scenarios. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[5]/sect2[4]/title[1] |
| Original | Traduction | Proxying classes |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/para[1] |
| Original | Traduction | What if you need to proxy a class, rather than one or more
interfaces? |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/para[2] |
| Original | Traduction | Imagine that in our example above, there was no
Person interface: we needed to advise a class called
Person that didn't implement any business interface.
In this case, you can configure Spring to use CGLIB proxying, rather
than dynamic proxies. Simply set the proxyTargetClass
property on the ProxyFactoryBean above to true. While it's best to
program to interfaces, rather than classes, the ability to advise
classes that don't implement interfaces can be useful when working with
legacy code. (In general, Spring isn't prescriptive. While it makes it
easy to apply good practices, it avoids forcing a particular
approach.) |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/para[3] |
| Original | Traduction | If you want to you can force the use of CGLIB in any case, even if
you do have interfaces. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/para[4] |
| Original | Traduction | CGLIB proxying works by generating a subclass of the target class
at runtime. Spring configures this generated subclass to delegate method
calls to the original target: the subclass is used to implement the
Decorator pattern, weaving in the advice. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/para[5] |
| Original | Traduction | CGLIB proxying should generally be transparent to users. However,
there are some issues to consider: |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Final methods can't be advised, as they
can't be overridden. |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | You'll need the CGLIB 2 binaries on your classpath; dynamic
proxies are available with the JDK |
|
| + para | Ref. /chapter[1]/sect1[5]/sect2[4]/para[6] |
| Original | Traduction | There's 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. Performance should not be a
decisive consideration in this case. |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[6]/title[1] |
| Original | Traduction | Convenient proxy creation |
|
| + para | Ref. /chapter[1]/sect1[6]/para[1] |
| Original | Traduction | Often we don't need the full power of the
ProxyFactoryBean, because we're only interested in one
aspect: For example, transaction management. |
|
| + para | Ref. /chapter[1]/sect1[6]/para[2] |
| Original | Traduction | There are a number of convenience factories we can use to create AOP
proxies when we want to focus on a specific aspect. These are discussed in
other chapters, so we'll just provide a quick survey of some of them
here. |
| sect2
| | + title | Ref. /chapter[1]/sect1[6]/sect2[1]/title[1] |
| Original | Traduction | TransactionProxyFactoryBean |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[1] |
| Original | Traduction | The jPetStore sample application
shipped with Spring shows the use of the
TransactionProxyFactoryBean. |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[2] |
| Original | Traduction | The TransactionProxyFactoryBean is a subclass
of ProxyConfig, so basic configuration is shared with
ProxyFactoryBean. (See list of
ProxyConfig properties above.) |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[3] |
| Original | Traduction | The following example from the jPetStore illustrates how this
works. As with a ProxyFactoryBean, there is a target
bean definition. Dependencies should be expressed on the proxied factory
bean definition ("petStore" here), rather than the target POJO
("petStoreTarget"). |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[4] |
| Original | Traduction | The TransactionProxyFactoryBean requires a
target, and information about "transaction attributes," specifying which
methods should be transactional and the required propagation and other
settings: |
|
| + programlisting | Ref. /chapter[1]/sect1[6]/sect2[1]/para[5]/programlisting[1] |
| Original | Traduction | <bean id="petStoreTarget" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
<property name="accountDao"><ref bean="accountDao"/></property>
<!-- Other dependencies omitted -->
</bean>
<bean id="petStore"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref local="petStoreTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[6] |
| Original | Traduction | As with the ProxyFactoryBean, we might choose
to use an inner bean to set the value of target
property, instead of a reference to a top-level target bean. |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[7] |
| Original | Traduction | The TransactionProxyFactoryBean automatically
creates a transaction advisor, including a pointcut based on the
transaction attributes, so only transactional methods are
advised. |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[8] |
| Original | Traduction | The TransactionProxyFactoryBean allows the
specification of "pre" and "post" advice, using the preInterceptors and
postInterceptors properties. These take Object arrays of interceptors,
other advice or Advisors to place in the interception chain before or
after the transaction interceptor. These can be populated using a
<list> element in XML bean definitions, as follows: |
|
| + programlisting | Ref. /chapter[1]/sect1[6]/sect2[1]/para[9]/programlisting[1] |
| Original | Traduction | <property name="preInterceptors">
<list>
<ref local="authorizationInterceptor"/>
<ref local="notificationBeforeAdvice"/>
</list>
</property>
<property name="postInterceptors">
<list>
<ref local="myAdvisor"/>
</list>
</property> |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[10] |
| Original | Traduction | These properties could be added to the "petStore" bean definition
above. A common usage is to combine transactionality with declarative
security: a similar approach to that offered by EJB. |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[11] |
| Original | Traduction | Because of the use of actual instance references, rather than bean
names as in ProxyFactoryBean, pre and post
interceptors can be used only for shared-instance advice. Thus they are
not useful for stateful advice: for example, in mixins. This is
consistent with the TransactionProxyFactoryBean's purpose. It provides a
simple way of doing common transaction setup. If you need more complex,
customized, AOP, consider using the generic
ProxyFactoryBean, or an auto proxy creator (see
below). |
|
| + remark | Ref. /chapter[1]/sect1[6]/sect2[1]/remark[1] |
| Original | Traduction | Especially if we view Spring AOP as, in many cases, a
replacement for EJB, we find that most advice is fairly generic and uses
a shared-instance model. Declarative transaction management and security
checks are classic examples. |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[1]/para[12] |
| Original | Traduction | The TransactionProxyFactoryBean depends on a
PlatformTransactionManager implementation via its
transactionManager JavaBean property. This allows for
pluggable transaction implementation, based on JTA, JDBC or other
strategies. This relates to the Spring transaction abstraction, rather
than AOP. We'll discuss the transaction infrastructure in the next
chapter. |
|
| + remark | Ref. /chapter[1]/sect1[6]/sect2[1]/remark[2] |
| Original | Traduction | If you're interested only in declarative transaction management,
the TransactionProxyFactoryBean is a good solution, and simpler than
using a ProxyFactoryBean. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[6]/sect2[2]/title[1] |
| Original | Traduction | EJB proxies |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[2]/para[1] |
| Original | Traduction | Other dedicated proxies create proxies for EJBs, enabling the EJB
"business methods" interface to be used directly by calling code.
Calling code does not need to perform JNDI lookups or use EJB create
methods: A significant improvement in readability and architectural
flexibility. |
|
| + para | Ref. /chapter[1]/sect1[6]/sect2[2]/para[2] |
| Original | Traduction | See the chapter on Spring EJB services in this manual for further
information. |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[7]/title[1] |
| Original | Traduction | Concise proxy definitions |
|
| + para | Ref. /chapter[1]/sect1[7]/para[1] |
| Original | Traduction | Especially when defining transactional proxies, you may end up with
many similar proxy definitions. The use of parent and child bean
definitions, along with inner bean definitions, can result in much cleaner
and more concise proxy definitions. |
|
| + para | Ref. /chapter[1]/sect1[7]/para[2] |
| Original | Traduction | First a parent, template, bean definition is
created for the proxy: |
|
| + programlisting | Ref. /chapter[1]/sect1[7]/para[3]/programlisting[1] |
| Original | Traduction | <bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></ref></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[7]/para[4] |
| Original | Traduction | This will never be instantiated itself, so may actually be
incomplete. Then each proxy which needs to be created is just a child bean
definition, which to wraps the target of the proxy as an inner bean
definition, since the target will never be used on its own
anyways. | + programlisting | Ref. /chapter[1]/sect1[7]/para[4]/programlisting[1] |
| Original | Traduction | <bean id="myService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MyServiceImpl">
</bean>
</property>
</bean> |
|
|
|
| + para | Ref. /chapter[1]/sect1[7]/para[5] |
| Original | Traduction | It is of course possible to override properties from the parent
template, such as in this case, the transaction propagation
settings: | + programlisting | Ref. /chapter[1]/sect1[7]/para[5]/programlisting[1] |
| Original | Traduction | <bean id="mySpecialService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MySpecialServiceImpl">
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean> |
|
|
|
| + para | Ref. /chapter[1]/sect1[7]/para[6] |
| Original | Traduction | Note that in the example above, we have explicitly marked the parent
bean definition as abstract by using the
abstract attribute, as described previously, so that it may
not actually ever be instantiated. Application contexts (but not
simple bean factories) will by default pre-instantiate all singletons.
Therefore it is important (at least for singleton beans) that if you have
a (parent) bean definition which you intend to use only as a template, and
this definition specifies a class, you must make sure to set the
abstract attribute to true,
otherwise the application context will actually try to pre-instantiate it. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[8]/title[1] |
| Original | Traduction | Creating AOP proxies programmatically with the ProxyFactory |
|
| + para | Ref. /chapter[1]/sect1[8]/para[1] |
| Original | Traduction | It's easy to create AOP proxies programmatically using Spring. This
enables you to use Spring AOP without dependency on Spring IoC. |
|
| + para | Ref. /chapter[1]/sect1[8]/para[2] |
| Original | Traduction | The following listing shows creation of a proxy for a target object,
with one interceptor and one advisor. The interfaces implemented by the
target object will automatically be proxied: |
|
| + programlisting | Ref. /chapter[1]/sect1[8]/para[3]/programlisting[1] |
| Original | Traduction | ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addInterceptor(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); |
|
| + para | Ref. /chapter[1]/sect1[8]/para[4] |
| Original | Traduction | The first step is to construct a object of type
org.springframework.aop.framework.ProxyFactory. You can
create this with a target object, as in the above example, or specify the
interfaces to be proxied in an alternate constructor. |
|
| + para | Ref. /chapter[1]/sect1[8]/para[5] |
| Original | Traduction | You can add interceptors or advisors, and manipulate them for the
life of the ProxyFactory. If you add an
IntroductionInterceptionAroundAdvisor you can cause the proxy to implement
additional interfaces. |
|
| + para | Ref. /chapter[1]/sect1[8]/para[6] |
| Original | Traduction | There are also convenience methods on ProxyFactory (inherited from
AdvisedSupport) allowing you to add other advice types such as before and
throws advice. AdvisedSupport is the superclass of both ProxyFactory and
ProxyFactoryBean. |
|
| + remark | Ref. /chapter[1]/sect1[8]/remark[1] |
| Original | Traduction | Integrating AOP proxy creation with the IoC framework is best
practice in most applications. We recommend that you externalize
configuration from Java code with AOP, as in general. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[9]/title[1] |
| Original | Traduction | Manipulating advised objects |
|
| + para | Ref. /chapter[1]/sect1[9]/para[1] |
| Original | Traduction | However you create AOP proxies, you can manipulate them using the
org.springframework.aop.framework.Advised interface.
Any AOP proxy can be cast to this interface, whatever other interfaces it
implements. This interface includes the following methods: |
|
| + programlisting | Ref. /chapter[1]/sect1[9]/programlisting[1] |
| Original | Traduction | Advisor[] getAdvisors();
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice)
throws AopConfigException;
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
int indexOf(Advisor advisor);
boolean removeAdvisor(Advisor advisor) throws AopConfigException;
void removeAdvisor(int index) throws AopConfigException;
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
boolean isFrozen(); |
|
| + para | Ref. /chapter[1]/sect1[9]/para[2] |
| Original | Traduction | The getAdvisors() method will return an Advisor
for every advisor, interceptor or other advice type that has been added to
the factory. If you added an Advisor, the returned advisor at this index
will be the object that you added. If you added an interceptor or other
advice type, Spring will have wrapped this in an advisor with a pointcut
that always returns true. Thus if you added a
MethodInterceptor, the advisor returned for this index
will be an DefaultPointcutAdvisor returning your
MethodInterceptor and a pointcut that matches all
classes and methods. |
|
| + para | Ref. /chapter[1]/sect1[9]/para[3] |
| Original | Traduction | The addAdvisor() methods can be used to add any
Advisor. Usually the advisor holding pointcut and advice will be the
generic DefaultPointcutAdvisor, which can be used with
any advice or pointcut (but not for introduction). |
|
| + para | Ref. /chapter[1]/sect1[9]/para[4] |
| Original | Traduction | By default, it's possible to add or remove advisors or interceptors
even once a proxy has been created. The only restriction is that it's
impossible to add or remove an introduction advisor, as existing proxies
from the factory will not show the interface change. (You can obtain a new
proxy from the factory to avoid this problem.) |
|
| + para | Ref. /chapter[1]/sect1[9]/para[5] |
| Original | Traduction | A simple example of casting an AOP proxy to the
Advised interface and examining and manipulating its
advice: |
|
| + programlisting | Ref. /chapter[1]/sect1[9]/para[6]/programlisting[1] |
| Original | Traduction | Advised advised = (Advised) myObject;
Advisor[] advisors = advised.getAdvisors();
int oldAdvisorCount = advisors.length;
System.out.println(oldAdvisorCount + " advisors");
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(new DebugInterceptor());
// Add selective advice using a pointcut
advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
assertEquals("Added two advisors",
oldAdvisorCount + 2, advised.getAdvisors().length); |
|
| + remark | Ref. /chapter[1]/sect1[9]/remark[1] |
| Original | Traduction | It's questionable whether it's advisable (no pun intended) to
modify advice on a business object in production, although there are no
doubt legitimate usage cases. However, it can be very useful in
development: for example, in tests. I have sometimes found it very useful
to be able to add test code in the form of an interceptor or other advice,
getting inside a method invocation I want to test. (For example, the
advice can get inside a transaction created for that method: for example,
to run SQL to check that a database was correctly updated, before marking
the transaction for roll back.) |
|
| + para | Ref. /chapter[1]/sect1[9]/para[7] |
| Original | Traduction | Depending on how you created the proxy, you can usually set a
frozen flag, in which case the
Advised isFrozen() method will
return true, and any attempts to modify advice through addition or removal
will result 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. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[10]/title[1] |
| Original | Traduction | Using the "autoproxy" facility |
|
| + para | Ref. /chapter[1]/sect1[10]/para[1] |
| Original | Traduction | So far we've considered explicit creation of AOP proxies using a
ProxyFactoryBean or similar factory bean. |
|
| + para | Ref. /chapter[1]/sect1[10]/para[2] |
| Original | Traduction | Spring also allows us to use "autoproxy" bean definitions, which can
automatically proxy selected bean definitions. This is built on Spring
"bean post processor" infrastructure, which enables modification of any
bean definition as the container loads. |
|
| + para | Ref. /chapter[1]/sect1[10]/para[3] |
| Original | Traduction | In this model, you set up some special bean definitions in your XML
bean definition file configuring the auto proxy infrastructure. This
allows you just to declare the targets eligible for autoproxying: you
don't need to use ProxyFactoryBean. |
|
| + para | Ref. /chapter[1]/sect1[10]/para[4] |
| Original | Traduction | There are two ways to do this: |
|
| + para | Ref. /chapter[1]/sect1[10]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Using an autoproxy creator that refers to specific beans in the
current context |
|
| + para | Ref. /chapter[1]/sect1[10]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | A special case of autoproxy creation that deserves to be
considered separately; autoproxy creation driven by source-level
metadata attributes |
|
sect2
| | + title | Ref. /chapter[1]/sect1[10]/sect2[1]/title[1] |
| Original | Traduction | Autoproxy bean definitions |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/para[1] |
| Original | Traduction | The org.springframework.aop.framework.autoproxy
package provides the following standard autoproxy creators. |
|
| + title | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[1]/title[1] |
| Original | Traduction | BeanNameAutoProxyCreator |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[1]/para[1] |
| Original | Traduction | The BeanNameAutoProxyCreator automatically creates AOP proxies
for beans with names matching literal values or wildcards. |
|
| + programlisting | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[1]/para[2]/programlisting[1] |
| Original | Traduction | <bean id="jdkBeanNameProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames"><value>jdk*,onlyJdk</value></property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[1]/para[3] |
| Original | Traduction | As with ProxyFactoryBean, there is an
interceptorNames property rather than a list of interceptor, to allow
correct behavior for prototype advisors. Named "interceptors" can be
advisors or any advice type. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[1]/para[4] |
| Original | Traduction | As with auto proxying in general, the main point of using
BeanNameAutoProxyCreator is to apply the same
configuration consistently to multiple objects, and with minimal
volume of configuration. It is a popular choice for applying
declarative transactions to multiple objects. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[1]/para[5] |
| Original | Traduction | Bean definitions whose names match, such as "jdkMyBean" and
"onlyJdk" in the above example, are plain old bean definitions with
the target class. An AOP proxy will be created automatically by the
BeanNameAutoProxyCreator. The same advice will be
applied to all matching beans. Note that if advisors are used (rather
than the interceptor in the above example), the pointcuts may apply
differently to different beans. |
|
| + title | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/title[1] |
| Original | Traduction | DefaultAdvisorAutoProxyCreator |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[1] |
| Original | Traduction | A more general and extremely powerful auto proxy creator is
DefaultAdvisorAutoProxyCreator. This will
automagically apply eligible advisors in the current context, without
the need to include specific bean names in the autoproxy advisor's
bean definition. It offers the same merit of consistent configuration
and avoidance of duplication as
BeanNameAutoProxyCreator. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[2] |
| Original | Traduction | Using this mechanism involves: |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Specifying a
DefaultAdvisorAutoProxyCreator bean
definition |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | Specifying any number of Advisors in the same or related
contexts. Note that these must be Advisors,
not just interceptors or other advices. This is necessary because
there must be a pointcut to evaluate, to check the eligibility of
each advice to candidate bean definitions. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[3] |
| Original | Traduction | The DefaultAdvisorAutoProxyCreator will
automatically evaluate the pointcut contained in each advisor, to see
what (if any) advice it should apply to each business object (such as
"businessObject1" and "businessObject2" in the example). |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[4] |
| Original | Traduction | This means that any number of advisors can be applied
automatically to each business object. If no pointcut in any of the
advisors matches any method in a business object, the object will not
be proxied. As bean definitions are added for new business objects,
they will automatically be proxied if necessary. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[5] |
| Original | Traduction | Autoproxying in general has the advantage of making it
impossible for callers or dependencies to obtain an un-advised object.
Calling getBean("businessObject1") on this ApplicationContext will
return an AOP proxy, not the target business object. (The "inner bean"
idiom shown earlier also offers this benefit.) |
|
| + programlisting | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[6]/programlisting[1] |
| Original | Traduction | <bean id="autoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>
<bean id="txAdvisor"
autowire="constructor"
class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="order"><value>1</value></property>
</bean>
<bean id="customAdvisor"
class="com.mycompany.MyAdvisor">
</bean>
<bean id="businessObject1"
class="com.mycompany.BusinessObject1">
<!-- Properties omitted -->
</bean>
<bean id="businessObject2"
class="com.mycompany.BusinessObject2">
</bean> |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[7] |
| Original | Traduction | The DefaultAdvisorAutoProxyCreator is very
useful if you want to apply the same advice consistently to many
business objects. Once the infrastructure definitions are in place,
you can simply add new business objects without including specific
proxy configuration. You can also drop in additional aspects very
easily--for example, tracing or performance monitoring aspects--with
minimal change to configuration. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[2]/para[8] |
| Original | Traduction | The DefaultAdvisorAutoProxyCreator offers support for filtering
(using a naming convention so that only certain advisors are
evaluated, allowing use of multiple, differently configured,
AdvisorAutoProxyCreators in the same factory) and ordering. Advisors
can implement the org.springframework.core.Ordered
interface to ensure correct ordering if this is an issue. The
TransactionAttributeSourceAdvisor used in the above example has a
configurable order value; default is unordered. |
|
| + title | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[3]/title[1] |
| Original | Traduction | AbstractAdvisorAutoProxyCreator |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[1]/sect3[3]/para[1] |
| Original | Traduction | This is the superclass of DefaultAdvisorAutoProxyCreator. You
can create your own autoproxy creators by subclassing this class, in
the unlikely event that advisor definitions offer insufficient
customization to the behavior of the framework
DefaultAdvisorAutoProxyCreator. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[10]/sect2[2]/title[1] |
| Original | Traduction | Using metadata-driven auto-proxying |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[1] |
| Original | Traduction | A particularly important type of autoproxying is driven by
metadata. This produces a similar programming model to .NET
ServicedComponents. Instead of using XML deployment
descriptors as in EJB, configuration for transaction management and
other enterprise services is held in source-level attributes. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[2] |
| Original | Traduction | In this case, you use the
DefaultAdvisorAutoProxyCreator, in combination with
Advisors that understand metadata attributes. The metadata specifics are
held in the pointcut part of the candidate advisors, rather than in the
autoproxy creation class itself. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[3] |
| Original | Traduction | This is really a special case of the
DefaultAdvisorAutoProxyCreator, but deserves
consideration on its own. (The metadata-aware code is in the pointcuts
contained in the advisors, not the AOP framework itself.) |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[4] |
| Original | Traduction | The /attributes directory of the jPetStore
sample application shows the use of attribute-driven autoproxying. In
this case, there's no need to use the
TransactionProxyFactoryBean. Simply defining
transactional attributes on business objects is sufficient, because of
the use of metadata-aware pointcuts. The bean definitions include the
following code, in /WEB-INF/declarativeServices.xml.
Note that this is generic, and can be used outside the jPetStore: |
|
| + programlisting | Ref. /chapter[1]/sect1[10]/sect2[2]/para[5]/programlisting[1] |
| Original | Traduction | <bean id="autoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>
<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource"
autowire="constructor">
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"
autowire="byType">
</bean>
<bean id="transactionAdvisor"
class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"
autowire="constructor" >
</bean>
<bean id="attributes"
class="org.springframework.metadata.commons.CommonsAttributes"
/> |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[6] |
| Original | Traduction | The DefaultAdvisorAutoProxyCreator bean
definition--called "autoProxyCreator" in this case, but the name is
not significant (it could even be omitted)--will pick up all eligible
pointcuts in the current application context. In this case, the
"transactionAdvisor" bean definition, of type
TransactionAttributeSourceAdvisor, will apply to
classes or methods carrying a transaction attribute. The
TransactionAttributeSourceAdvisor depends on a TransactionInterceptor,
via constructor dependency. The example resolves this via autowiring.
The AttributesTransactionAttributeSource depends on
an implementation of the
org.springframework.metadata.Attributes interface. In
this fragment, the "attributes" bean satisfies this, using the Jakarta
Commons Attributes API to obtain attribute information. (The application
code must have been compiled using the Commons Attributes compilation
task.) |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[7] |
| Original | Traduction | The TransactionInterceptor defined here depends
on a PlatformTransactionManager definition, which is
not included in this generic file (although it could be) because it will
be specific to the application's transaction requirements (typically
JTA, as in this example, or Hibernate, JDO or JDBC): |
|
| + programlisting | Ref. /chapter[1]/sect1[10]/sect2[2]/programlisting[1] |
| Original | Traduction | <bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/> |
|
| + remark | Ref. /chapter[1]/sect1[10]/sect2[2]/remark[1] |
| Original | Traduction | If you require only declarative transaction management, using
these generic XML definitions will result in Spring automatically
proxying all classes or methods with transaction attributes. You won't
need to work directly with AOP, and the programming model is similar to
that of .NET ServicedComponents. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[8] |
| Original | Traduction | This mechanism is extensible. It's possible to do autoproxying
based on custom attributes. You need to: |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Define your custom attribute. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | Specify an Advisor with the necessary advice, including a
pointcut that is triggered by the presence of the custom attribute
on a class or method. You may be able to use an existing advice,
merely implementing a static pointcut that picks up the custom
attribute. |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[9] |
| Original | Traduction | It's possible for such advisors to be unique to each advised class
(for example, mixins): they simply need to be defined as prototype,
rather than singleton, bean definitions. For example, the
LockMixin introduction interceptor from the Spring
test suite, shown above, could be used in conjunction with an
attribute-driven pointcut to target a mixin, as shown here. We use the
generic DefaultPointcutAdvisor, configured using
JavaBean properties: |
|
| + programlisting | Ref. /chapter[1]/sect1[10]/sect2[2]/para[10]/programlisting[1] |
| Original | Traduction | <bean id="lockMixin"
class="org.springframework.aop.LockMixin"
singleton="false"
/>
<bean id="lockableAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor"
singleton="false"
>
<property name="pointcut">
<ref local="myAttributeAwarePointcut"/>
</property>
<property name="advice">
<ref local="lockMixin"/>
</property>
</bean>
<bean id="anyBean" class="anyclass" ... |
|
| + para | Ref. /chapter[1]/sect1[10]/sect2[2]/para[11] |
| Original | Traduction | If the attribute aware pointcut matches any methods in the
anyBean or other bean definitions, the mixin will be
applied. Note that both lockMixin and
lockableAdvisor definitions are prototypes. The
myAttributeAwarePointcut pointcut can be a singleton
definition, as it doesn't hold state for individual advised
objects. |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[11]/title[1] |
| Original | Traduction | Using TargetSources |
|
| + para | Ref. /chapter[1]/sect1[11]/para[1] |
| Original | Traduction | Spring offers the concept of a TargetSource,
expressed in the org.springframework.aop.TargetSource
interface. This interface is responsible for returning the "target object"
implementing the joinpoint. The TargetSource
implementation is asked for a target instance each time the AOP proxy
handles a method invocation. |
|
| + para | Ref. /chapter[1]/sect1[11]/para[2] |
| Original | Traduction | Developers using Spring AOP don't normally need to work directly
with TargetSources, but this provides a powerful means of supporting
pooling, hot swappable and other sophisticated targets. For example, a
pooling TargetSource can return a different target instance for each
invocation, using a pool to manage instances. |
|
| + para | Ref. /chapter[1]/sect1[11]/para[3] |
| Original | Traduction | If you do not specify a TargetSource, a default implementation is
used that wraps a local object. The same target is returned for each
invocation (as you would expect). |
|
| + para | Ref. /chapter[1]/sect1[11]/para[4] |
| Original | Traduction | Let's look at the standard target sources provided with Spring, and
how you can use them. |
|
| + remark | Ref. /chapter[1]/sect1[11]/remark[1] |
| Original | Traduction | When using a custom target source, your target will usually need
to be a prototype rather than a singleton bean definition. This allows
Spring to create a new target instance when required. |
| sect2
| | + title | Ref. /chapter[1]/sect1[11]/sect2[1]/title[1] |
| Original | Traduction | Hot swappable target sources |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[1]/para[1] |
| Original | Traduction | The
org.springframework.aop.target.HotSwappableTargetSource
exists to allow the target of an AOP proxy to be switched while allowing
callers to keep their references to it. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[1]/para[2] |
| Original | Traduction | Changing the target source's target takes effect immediately. The
HotSwappableTargetSource is threadsafe. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[1]/para[3] |
| Original | Traduction | You can change the target via the swap() method
on HotSwappableTargetSource as follows: |
|
| + programlisting | Ref. /chapter[1]/sect1[11]/sect2[1]/para[4]/programlisting[1] |
| Original | Traduction | HotSwappableTargetSource swapper =
(HotSwappableTargetSource) beanFactory.getBean("swapper");
Object oldTarget = swapper.swap(newTarget); |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[1]/para[5] |
| Original | Traduction | The XML definitions required look as follows: |
|
| + programlisting | Ref. /chapter[1]/sect1[11]/sect2[1]/para[6]/programlisting[1] |
| Original | Traduction | <bean id="initialTarget" class="mycompany.OldTarget">
</bean>
<bean id="swapper"
class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg><ref local="initialTarget"/></constructor-arg>
</bean>
<bean id="swappable"
class="org.springframework.aop.framework.ProxyFactoryBean"
>
<property name="targetSource">
<ref local="swapper"/>
</property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[1]/para[7] |
| Original | Traduction | The above swap() call changes the target of the
swappable bean. Clients who hold a reference to that bean will be
unaware of the change, but will immediately start hitting the new
target. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[1]/para[8] |
| Original | Traduction | Although this example doesn't add any advice--and it's not
necessary to add advice to use a TargetSource--of
course any TargetSource can be used in conjunction
with arbitrary advice. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[11]/sect2[2]/title[1] |
| Original | Traduction | Pooling target sources |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[1] |
| Original | Traduction | Using a pooling target source provides a similar programming model
to stateless session EJBs, in which a pool of identical instances is
maintained, with method invocations going to free objects in the
pool. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[2] |
| Original | Traduction | A crucial difference between Spring pooling and SLSB pooling is
that Spring pooling can be applied to any POJO. As with Spring in
general, this service can be applied in a non-invasive way. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[3] |
| Original | Traduction | Spring provides out-of-the-box support for Jakarta Commons Pool
1.1, which provides a fairly efficient pooling implementation. You'll
need the commons-pool Jar on your application's classpath to use this
feature. It's also possible to subclass
org.springframework.aop.target.AbstractPoolingTargetSource
to support any other pooling API. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[4] |
| Original | Traduction | Sample configuration is shown below: |
|
| + programlisting | Ref. /chapter[1]/sect1[11]/sect2[2]/para[5]/programlisting[1] |
| Original | Traduction | <bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject"
singleton="false">
... properties omitted
</bean>
<bean id="poolTargetSource"
class="org.springframework.aop.target.CommonsPoolTargetSource">
<property name="targetBeanName"><value>businessObjectTarget</value></property>
<property name="maxSize"><value>25</value></property>
</bean>
<bean id="businessObject"
class="org.springframework.aop.framework.ProxyFactoryBean"
>
<property name="targetSource"><ref local="poolTargetSource"/></property>
<property name="interceptorNames"><value>myInterceptor</value></property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[6] |
| Original | Traduction | Note that the target object--"businessObjectTarget" in the
example--must be a prototype. This allows the
PoolingTargetSource implementation to create new
instances of the target to grow the pool as necessary. See the Javadoc
for AbstractPoolingTargetSource and the concrete
subclass you wish to use for information about it's properties: maxSize
is the most basic, and always guaranteed to be present. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[7] |
| Original | Traduction | In this case, "myInterceptor" is the name of an interceptor that
would need to be defined in the same IoC context. However, it isn't
necessary to specify interceptors to use pooling. If you want only
pooling, and no other advice, don't set the interceptorNames property at
all. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[8] |
| Original | Traduction | It's possible to configure Spring so as to be able to cast any
pooled object to the
org.springframework.aop.target.PoolingConfig
interface, which exposes information about the configuration and current
size of the pool through an introduction. You'll need to define an
advisor like this: |
|
| + programlisting | Ref. /chapter[1]/sect1[11]/sect2[2]/para[9]/programlisting[1] |
| Original | Traduction | <bean id="poolConfigAdvisor"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="poolTargetSource" /></property>
<property name="targetMethod"><value>getPoolingConfigMixin</value></property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[10] |
| Original | Traduction | This advisor is obtained by calling a convenience method on the
AbstractPoolingTargetSource class, hence the use of
MethodInvokingFactoryBean. This advisor's name ("poolConfigAdvisor"
here) must be in the list of interceptors names in the ProxyFactoryBean
exposing the pooled object. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[11] |
| Original | Traduction | The cast will look as follows: |
|
| + programlisting | Ref. /chapter[1]/sect1[11]/sect2[2]/para[12]/programlisting[1] |
| Original | Traduction | PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
System.out.println("Max pool size is " + conf.getMaxSize()); |
|
| + remark | Ref. /chapter[1]/sect1[11]/sect2[2]/remark[1] |
| Original | Traduction | Pooling stateless service objects is not usually necessary. We
don't believe it should be the default choice, as most stateless objects
are naturally thread safe, and instance pooling is problematic if
resources are cached. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[2]/para[13] |
| Original | Traduction | Simpler pooling is available using autoproxying. It's possible to
set the TargetSources used by any autoproxy creator. |
|
| | sect2
| | + title | Ref. /chapter[1]/sect1[11]/sect2[3]/title[1] |
| Original | Traduction | Prototype" target sources |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[3]/para[1] |
| Original | Traduction | Setting up a "prototype" target source is similar to a pooling
TargetSource. In this case, a new instance of the target will be created
on every method invocation. Although the cost of creating a new object
isn't high in a modern JVM, the cost of wiring up the new object
(satisfying its IoC dependencies) may be more expensive. Thus you
shouldn't use this approach without very good reason. |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[3]/para[2] |
| Original | Traduction | To do this, you could modify the
poolTargetSource definition shown above as follows.
(I've also changed the name, for clarity.) |
|
| + programlisting | Ref. /chapter[1]/sect1[11]/sect2[3]/para[3]/programlisting[1] |
| Original | Traduction | <bean id="prototypeTargetSource"
class="org.springframework.aop.target.PrototypeTargetSource">
<property name="targetBeanName"><value>businessObjectTarget</value></property>
</bean> |
|
| + para | Ref. /chapter[1]/sect1[11]/sect2[3]/para[4] |
| Original | Traduction | There's only one property: the name of the target bean.
Inheritance is used in the TargetSource implementations to ensure
consistent naming. As with the pooling target source, the target bean
must be a prototype bean definition. |
|
| |
| | sect1
| | + title | Ref. /chapter[1]/sect1[12]/title[1] |
| Original | Traduction | Defining new Advice types |
|
| + para | Ref. /chapter[1]/sect1[12]/para[1] |
| Original | Traduction | Spring AOP is designed to be extensible. While the interception
implementation strategy is presently used internally, it is possible to
support arbitrary advice types in addition to interception around advice,
before, throws advice and after returning advice, which are supported out
of the box. |
|
| + para | Ref. /chapter[1]/sect1[12]/para[2] |
| Original | Traduction | The org.springframework.aop.framework.adapter
package is an SPI package allowing support for new custom advice types to
be added without changing the core framework. The only constraint on a
custom Advice type is that it must implement the
org.aopalliance.aop.Advice tag interface. |
|
| + para | Ref. /chapter[1]/sect1[12]/para[3] |
| Original | Traduction | Please refer to the
org.springframework.aop.framework.adapter package's
Javadocs for further information |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[13]/title[1] |
| Original | Traduction | Further reading and resources |
|
| + para | Ref. /chapter[1]/sect1[13]/para[1] |
| Original | Traduction | I recommend the excellent AspectJ in Action by
Ramnivas Laddad (Manning, 2003) for an introduction to AOP. |
|
| + para | Ref. /chapter[1]/sect1[13]/para[2] |
| Original | Traduction | Please refer to the Spring sample applications for further examples
of Spring AOP: |
|
| + para | Ref. /chapter[1]/sect1[13]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | The JPetStore's default configuration illustrates the use of the
TransactionProxyFactoryBean for declarative transaction
management |
|
| + para | Ref. /chapter[1]/sect1[13]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | The /attributes directory of the JPetStore
illustrates the use of attribute-driven declarative transaction
management |
|
| + para | Ref. /chapter[1]/sect1[13]/para[3] |
| Original | Traduction | If you are interested in more advanced capabilities of Spring AOP,
take a look at the test suite. The test coverage is over 90%, and this
illustrates advanced features not discussed in this document. |
|
| | sect1
| | + title | Ref. /chapter[1]/sect1[14]/title[1] |
| Original | Traduction | Roadmap |
|
| + para | Ref. /chapter[1]/sect1[14]/para[1] |
| Original | Traduction | Spring AOP, like the rest of Spring, is actively developed. The core
API is stable. Like the rest of Spring, the AOP framework is very modular,
enabling extension while preserving the fundamental design. Several
improvements are planned in the Spring 1.1 time frame, which will preserve
backward compatibility. These include: |
|
| + para | Ref. /chapter[1]/sect1[14]/itemizedlist[1]/listitem[1]/para[1] |
| Original | Traduction | Performance improvements: The creation of
AOP proxies is handled by a factory via a Strategy interface. Thus we
can support additional AopProxy types without impacting user code or
the core implementation. Significant performance optimizations for
CGLIB proxying are scheduled for the 1.0.3 release, with further
optimizations by Spring 1.1 in cases where advice will not change at
runtime. This should produce a significant reduction in the overhead
of the AOP framework. Note, however, that the overhead of the AOP
framework is not an issue in normal usage. |
|
| + para | Ref. /chapter[1]/sect1[14]/itemizedlist[1]/listitem[2]/para[1] |
| Original | Traduction | More expressive pointcuts: Spring presently
offers an expressive Pointcut interface, but we can add value through
adding more Pointcut implementations. We are looking at an integration
with AspectJ that will allow AspectJ pointcut expressions to be used
in Spring configuration files. And if you wish to contribute a useful
Pointcut, please do! |
|
| + para | Ref. /chapter[1]/sect1[14]/para[2] |
| Original | Traduction | The most significant enhancements are likely to concern integration
with AspectJ, which will be done in cooperation with the AspectJ
community. We believe that this will provide significant benefits for both
Spring and AspectJ users, in the following areas: |
|
| + para | Ref. /chapter[1]/sect1[14]/itemizedlist[2]/listitem[1]/para[1] |
| Original | Traduction | Allowing AspectJ aspects to be configured using Spring IoC. This
has the potential to integrate AspectJ aspects into applications where
appropriate, in the same way as Spring aspects are integrated into
application IoC contexts. |
|
| + para | Ref. /chapter[1]/sect1[14]/itemizedlist[2]/listitem[2]/para[1] |
| Original | Traduction | Allowing the use of AspectJ pointcut expressions within Spring
configuration to target Spring advice. This has significant benefits
over devising our own pointcut expression language; AspectJ is both
well thought out and well documented. |
|
| + para | Ref. /chapter[1]/sect1[14]/para[3] |
| Original | Traduction | Both these integrations should be available in Spring 1.1. |
|
| |
|