Remove admonitions surrounding code snippets
This commit is contained in:
@@ -29,7 +29,6 @@ target different advice with the same pointcut.
|
||||
The `org.springframework.aop.Pointcut` interface is the central interface, used to
|
||||
target advices to particular classes and methods. The complete interface follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -41,7 +40,6 @@ target advices to particular classes and methods. The complete interface follows
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
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`"
|
||||
@@ -51,7 +49,6 @@ The `ClassFilter` interface is used to restrict the pointcut to a given set of t
|
||||
classes. If the `matches()` method always returns true, all target classes are
|
||||
matched. The following listing shows the `ClassFilter` interface definition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -60,11 +57,9 @@ matched. The following listing shows the `ClassFilter` interface definition:
|
||||
boolean matches(Class clazz);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `MethodMatcher` interface is normally more important. The complete interface follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -77,7 +72,6 @@ The `MethodMatcher` interface is normally more important. The complete interface
|
||||
boolean matches(Method m, Class targetClass, Object[] args);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `matches(Method, Class)` method is used to test whether this pointcut ever
|
||||
matches a given method on a target class. This evaluation can be performed when an AOP
|
||||
@@ -153,7 +147,6 @@ effectively the union of these pointcuts.)
|
||||
|
||||
The following example shows how to use `JdkRegexpMethodPointcut`:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -167,7 +160,6 @@ The following example shows how to use `JdkRegexpMethodPointcut`:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Spring provides a convenience class named `RegexpMethodPointcutAdvisor`, which lets us
|
||||
also reference an `Advice` (remember that an `Advice` can be an interceptor, before advice,
|
||||
@@ -175,7 +167,6 @@ throws advice, and others). Behind the scenes, Spring uses a `JdkRegexpMethodPoi
|
||||
Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both
|
||||
pointcut and advice, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -192,7 +183,6 @@ pointcut and advice, as the following example shows:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
You can use `RegexpMethodPointcutAdvisor` with any `Advice` type.
|
||||
|
||||
@@ -239,7 +229,6 @@ Because static pointcuts are most useful, you should probably subclass
|
||||
abstract method (although you can override other methods to customize behavior). The
|
||||
following example shows how to subclass `StaticMethodMatcherPointcut`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -250,7 +239,6 @@ following example shows how to subclass `StaticMethodMatcherPointcut`:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
There are also superclasses for dynamic pointcuts.
|
||||
|
||||
@@ -313,7 +301,6 @@ Spring is compliant with the AOP `Alliance` interface for around advice that use
|
||||
interception. Classes that implement `MethodInterceptor` and that implement around advice should also implement the
|
||||
following interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -322,7 +309,6 @@ following interface:
|
||||
Object invoke(MethodInvocation invocation) throws Throwable;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `MethodInvocation` argument to the `invoke()` method exposes the method being
|
||||
invoked, the target join point, the AOP proxy, and the arguments to the method. The
|
||||
@@ -331,7 +317,6 @@ point.
|
||||
|
||||
The following example shows a simple `MethodInterceptor` implementation:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -345,7 +330,6 @@ The following example shows a simple `MethodInterceptor` implementation:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Note the call to the `proceed()` method of `MethodInvocation`. This proceeds down the
|
||||
interceptor chain towards the join point. Most interceptors invoke this method and
|
||||
@@ -374,7 +358,6 @@ interceptor chain.
|
||||
|
||||
The following listing shows the `MethodBeforeAdvice` interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -383,7 +366,6 @@ The following listing shows the `MethodBeforeAdvice` interface:
|
||||
void before(Method m, Object[] args, Object target) throws Throwable;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
(Spring's API design would allow for
|
||||
field before advice, although the usual objects apply to field interception and it is
|
||||
@@ -398,7 +380,6 @@ wrapped in an unchecked exception by the AOP proxy.
|
||||
|
||||
The following example shows a before advice in Spring, which counts all method invocations:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -415,7 +396,6 @@ The following example shows a before advice in Spring, which counts all method i
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
TIP: Before advice can be used with any pointcut.
|
||||
|
||||
@@ -429,13 +409,11 @@ an exception. Spring offers typed throws advice. Note that this means that the
|
||||
tag interface identifying that the given object implements one or more typed throws
|
||||
advice methods. These should be in the following form:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
afterThrowing([Method, args, target], subclassOfThrowable)
|
||||
----
|
||||
====
|
||||
|
||||
Only the last argument is required. The method signatures may have either one or four
|
||||
arguments, depending on whether the advice method is interested in the method and
|
||||
@@ -443,7 +421,6 @@ arguments. The next two listing show classes that are examples of throws advice.
|
||||
|
||||
The following advice is invoked if a `RemoteException` is thrown (including from subclasses):
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -454,13 +431,11 @@ The following advice is invoked if a `RemoteException` is thrown (including from
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Unlike the preceding
|
||||
advice, the next example declares four arguments, so that it has access to the invoked method, method
|
||||
arguments, and target object. The following advice is invoked if a `ServletException` is thrown:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -471,13 +446,11 @@ arguments, and target object. The following advice is invoked if a `ServletExcep
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The final example illustrates how these two methods could be used in a single class
|
||||
that handles both `RemoteException` and `ServletException`. Any number of throws advice
|
||||
methods can be combined in a single class. The following listing shows the final example:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -492,7 +465,6 @@ methods can be combined in a single class. The following listing shows the final
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: If a throws-advice method throws an exception itself, it overrides the
|
||||
original exception (that is, it changes the exception thrown to the user). The overriding
|
||||
@@ -511,7 +483,6 @@ TIP: Throws advice can be used with any pointcut.
|
||||
An after returning advice in Spring must implement the
|
||||
`org.springframework.aop.AfterReturningAdvice` interface, which the following listing shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -521,7 +492,6 @@ An after returning advice in Spring must implement the
|
||||
throws Throwable;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
An after returning advice has access to the return value (which it cannot modify),
|
||||
the invoked method, the method's arguments, and the target.
|
||||
@@ -529,7 +499,6 @@ the invoked method, the method's arguments, and the target.
|
||||
The following after returning advice counts all successful method invocations that have
|
||||
not thrown exceptions:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -547,7 +516,6 @@ not thrown exceptions:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
This advice does not change the execution path. If it throws an exception, it is
|
||||
thrown up the interceptor chain instead of the return value.
|
||||
@@ -563,7 +531,6 @@ Spring treats introduction advice as a special kind of interception advice.
|
||||
Introduction requires an `IntroductionAdvisor` and an `IntroductionInterceptor` that
|
||||
implement the following interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -572,7 +539,6 @@ implement the following interface:
|
||||
boolean implementsInterface(Class intf);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must
|
||||
implement the introduction. That is, if the invoked method is on an introduced
|
||||
@@ -583,7 +549,6 @@ Introduction advice cannot be used with any pointcut, as it applies only at the
|
||||
rather than the method, level. You can only use introduction advice with the
|
||||
`IntroductionAdvisor`, which has the following methods:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -599,7 +564,6 @@ rather than the method, level. You can only use introduction advice with the
|
||||
Class[] getInterfaces();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
There is no `MethodMatcher` and, hence, no `Pointcut` associated with introduction
|
||||
advice. Only class filtering is logical.
|
||||
@@ -612,7 +576,6 @@ introduced interfaces can be implemented by the configured `IntroductionIntercep
|
||||
Consider an example from the Spring test suite and suppose we want to
|
||||
introduce the following interface to one or more objects:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -622,7 +585,6 @@ introduce the following interface to one or more objects:
|
||||
boolean locked();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
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
|
||||
@@ -659,7 +621,6 @@ to that held in the target object.
|
||||
|
||||
The following example shows the example `LockMixin` class:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -688,7 +649,6 @@ The following example shows the example `LockMixin` class:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Often, you need not override the `invoke()` method. The
|
||||
`DelegatingIntroductionInterceptor` implementation (which calls the `delegate` method if
|
||||
@@ -703,7 +663,6 @@ interceptor (which would be defined as a prototype). In this case, there is no
|
||||
configuration relevant for a `LockMixin`, so we create it by using `new`.
|
||||
The following example shows our `LockMixinAdvisor` class:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -714,7 +673,6 @@ The following example shows our `LockMixinAdvisor` class:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
We can apply this advisor very simply, because it requires no configuration. (However, it
|
||||
is impossible to use an `IntroductionInterceptor` without an
|
||||
@@ -904,7 +862,6 @@ Consider a simple example of `ProxyFactoryBean` in action. This example involves
|
||||
|
||||
The following listing shows the example:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -933,7 +890,6 @@ The following listing shows the example:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Note that the `interceptorNames` property takes a list of `String`, which holds the bean names of the
|
||||
interceptors or advisors in the current factory. You can use advisors, interceptors, before, after
|
||||
@@ -948,18 +904,15 @@ an instance of the prototype from the factory. Holding a reference is not suffic
|
||||
The `person` bean definition shown earlier can be used in place of a `Person` implementation, as
|
||||
follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
Person person = (Person) factory.getBean("person");
|
||||
----
|
||||
====
|
||||
|
||||
Other beans in the same IoC context can express a strongly typed dependency on it, as
|
||||
with an ordinary Java object. The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -967,7 +920,6 @@ with an ordinary Java object. The following example shows how to do so:
|
||||
<property name="person"><ref bean="person"/></property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The `PersonUser` class in this example exposes a property of type `Person`. As far as
|
||||
it is concerned, the AOP proxy can be used transparently in place of a "`real`" person
|
||||
@@ -979,7 +931,6 @@ inner bean. Only the `ProxyFactoryBean` definition is different. The
|
||||
advice is included only for completeness. The following example shows how to use an
|
||||
anonymous inner bean:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1006,7 +957,6 @@ anonymous inner bean:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Using an anonymous inner bean has the advantage that there is only one object of type `Person`. This is useful if we want
|
||||
to prevent users of the application context from obtaining a reference to the un-advised
|
||||
@@ -1060,7 +1010,6 @@ the part before the asterisk are added to the advisor chain. This can come in ha
|
||||
if you need to add a standard set of "`global`" advisors. The following example defines
|
||||
two global advisors:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1076,7 +1025,6 @@ two global advisors:
|
||||
<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1090,7 +1038,6 @@ definitions, can result in much cleaner and more concise proxy definitions.
|
||||
|
||||
First, we create a parent, template, bean definition for the proxy, as follows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1104,14 +1051,12 @@ First, we create a parent, template, bean definition for the proxy, as follows:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
This is never instantiated itself, so it can actually be incomplete. Then, each proxy
|
||||
that needs to be created is a child bean definition, which wraps the target of the
|
||||
proxy as an inner bean definition, since the target is never used on its own anyway.
|
||||
The following example shows such a child bean:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1122,12 +1067,10 @@ The following example shows such a child bean:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
You can override properties from the parent template. In the following example,
|
||||
we override the transaction propagation settings:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1146,7 +1089,6 @@ we override the transaction propagation settings:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Note that in the parent bean example, we explicitly marked the parent bean definition as
|
||||
being abstract by setting the `abstract` attribute to `true`, as described
|
||||
@@ -1171,7 +1113,6 @@ The interfaces implemented by the target object are
|
||||
automatically proxied. The following listing shows creation of a proxy for a target object, with one
|
||||
interceptor and one advisor:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1180,7 +1121,6 @@ interceptor and one advisor:
|
||||
factory.addAdvisor(myAdvisor);
|
||||
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
|
||||
----
|
||||
====
|
||||
|
||||
The first step is to construct an object of type
|
||||
`org.springframework.aop.framework.ProxyFactory`. You can create this with a target
|
||||
@@ -1211,7 +1151,6 @@ However you create AOP proxies, you can manipulate them BY using the
|
||||
interface, no matter which other interfaces it implements. This interface includes the
|
||||
following methods:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1235,7 +1174,6 @@ following methods:
|
||||
|
||||
boolean isFrozen();
|
||||
----
|
||||
====
|
||||
|
||||
The `getAdvisors()` method returns an `Advisor` for every advisor, interceptor, or
|
||||
other advice type that has been added to the factory. If you added an `Advisor`, the
|
||||
@@ -1257,7 +1195,6 @@ change. (You can obtain a new proxy from the factory to avoid this problem.)
|
||||
The following example shows casting an AOP proxy to the `Advised` interface and examining and
|
||||
manipulating its advice:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1276,7 +1213,6 @@ manipulating its advice:
|
||||
|
||||
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: It is questionable whether it is advisable (no pun intended) to modify advice on a
|
||||
business object in production, although there are, no doubt, legitimate usage cases.
|
||||
@@ -1333,7 +1269,6 @@ The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically
|
||||
AOP proxies for beans with names that match literal values or wildcards. The following
|
||||
example shows how to create a `BeanNameAutoProxyCreator` bean:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1346,7 +1281,6 @@ example shows how to create a `BeanNameAutoProxyCreator` bean:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list
|
||||
of interceptors, to allow correct behavior for prototype advisors. Named "`interceptors`"
|
||||
@@ -1398,7 +1332,6 @@ bean`" idiom shown earlier also offers this benefit.)
|
||||
The following example creates a `DefaultAdvisorAutoProxyCreator` bean and the other
|
||||
elements discussed in this section:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1416,7 +1349,6 @@ elements discussed in this section:
|
||||
|
||||
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
|
||||
----
|
||||
====
|
||||
|
||||
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,
|
||||
@@ -1470,18 +1402,15 @@ Changing the target source's target takes effect immediately. The
|
||||
|
||||
You can change the target by using the `swap()` method on HotSwappableTargetSource, as the follow example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
|
||||
Object oldTarget = swapper.swap(newTarget);
|
||||
----
|
||||
====
|
||||
|
||||
The following example shows the required XML definitions:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1495,7 +1424,6 @@ The following example shows the required XML definitions:
|
||||
<property name="targetSource" ref="swapper"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding `swap()` call changes the target of the swappable bean. Clients that hold a
|
||||
reference to that bean are unaware of the change but immediately start hitting
|
||||
@@ -1528,7 +1456,6 @@ NOTE: Commons Pool 1.5+ is also supported but is deprecated as of Spring Framewo
|
||||
|
||||
The following listing shows an example configuration:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1547,7 +1474,6 @@ The following listing shows an example configuration:
|
||||
<property name="interceptorNames" value="myInterceptor"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Note that the target object (`businessObjectTarget` in the preceding example) must be a
|
||||
prototype. This lets the `PoolingTargetSource` implementation create new instances
|
||||
@@ -1565,7 +1491,6 @@ You can configure Spring to be able to cast any pooled object to the
|
||||
about the configuration and current size of the pool through an introduction. You
|
||||
need to define an advisor similar to the following:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1574,7 +1499,6 @@ need to define an advisor similar to the following:
|
||||
<property name="targetMethod" value="getPoolingConfigMixin"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
This advisor is obtained by calling a convenience method on the
|
||||
`AbstractPoolingTargetSource` class, hence the use of `MethodInvokingFactoryBean`. This
|
||||
@@ -1583,14 +1507,12 @@ the `ProxyFactoryBean` that exposes the pooled object.
|
||||
|
||||
The cast is defined as follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
|
||||
System.out.println("Max pool size is " + conf.getMaxSize());
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: Pooling stateless service objects is not usually necessary. We do not believe it should
|
||||
be the default choice, as most stateless objects are naturally thread safe, and instance
|
||||
@@ -1613,7 +1535,6 @@ use this approach without very good reason.
|
||||
To do this, you could modify the `poolTargetSource` definition shown earlier as follows
|
||||
(we also changed the name, for clarity):
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1621,7 +1542,6 @@ To do this, you could modify the `poolTargetSource` definition shown earlier as
|
||||
<property name="targetBeanName" ref="businessObjectTarget"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The only property is the name of the target bean. Inheritance is used in the
|
||||
`TargetSource` implementations to ensure consistent naming. As with the pooling target
|
||||
@@ -1638,7 +1558,6 @@ facility to transparently store a resource alongside a thread. Setting up a
|
||||
`ThreadLocalTargetSource` is pretty much the same as was explained for the other types
|
||||
of target source, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1646,7 +1565,6 @@ of target source, as the following example shows:
|
||||
<property name="targetBeanName" value="businessObjectTarget"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: `ThreadLocal` instances come with serious issues (potentially resulting in memory leaks) when
|
||||
incorrectly using them in multi-threaded and multi-classloader environments. You
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,6 @@ To use the tags in the `util` schema, you need to have the following preamble at
|
||||
of your Spring XML configuration file (the text in the snippet references the
|
||||
correct schema so that the tags in the `util` namespace are available to you):
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -35,7 +34,6 @@ correct schema so that the tags in the `util` namespace are available to you):
|
||||
<!-- bean definitions here -->
|
||||
</beans>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +42,6 @@ correct schema so that the tags in the `util` namespace are available to you):
|
||||
|
||||
Consider the following bean definition:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -55,7 +52,6 @@ Consider the following bean definition:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration uses a Spring `FactoryBean` implementation (the
|
||||
`FieldRetrievingFactoryBean`) to set the value of the `isolation` property on a bean
|
||||
@@ -66,7 +62,6 @@ plumbing to the end user.
|
||||
The following XML Schema-based version is more concise, clearly expresses the
|
||||
developer's intent ("`inject this constant value`"), and it reads better:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -76,7 +71,6 @@ developer's intent ("`inject this constant value`"), and it reads better:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +86,6 @@ The following example shows how a `static` field is exposed, by using the
|
||||
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`]
|
||||
property:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -101,26 +94,22 @@ property:
|
||||
<property name="staticField" value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
There is also a convenience usage form where the `static` field is specified as the bean
|
||||
name, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
|
||||
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
|
||||
----
|
||||
====
|
||||
|
||||
This does mean that there is no longer any choice in what the bean `id` is (so any other
|
||||
bean that refers to it also has to use this longer name), but this form is very
|
||||
concise to define and very convenient to use as an inner bean since the `id` does not have
|
||||
to be specified for the bean reference, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -131,7 +120,6 @@ to be specified for the bean reference, as the following example shows:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
You can also access a non-static (instance) field of another bean, as
|
||||
described in the API documentation for the
|
||||
@@ -144,7 +132,6 @@ anything about the Spring internals (or even about classes such as the
|
||||
`FieldRetrievingFactoryBean`). The following example enumeration shows how easy injecting an
|
||||
enum value is:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -156,11 +143,9 @@ enum value is:
|
||||
EXTENDED
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Now consider the following setter of type `PersistenceContextType` and the corresponding bean definition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -183,7 +168,6 @@ Now consider the following setter of type `PersistenceContextType` and the corre
|
||||
<property name="persistenceContextType" value="TRANSACTION"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -192,7 +176,6 @@ Now consider the following setter of type `PersistenceContextType` and the corre
|
||||
|
||||
Consider the following example:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -209,7 +192,6 @@ Consider the following example:
|
||||
<!-- results in 10, which is the value of property 'age' of bean 'testBean' -->
|
||||
<bean id="testBean.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration uses a Spring `FactoryBean` implementation (the
|
||||
`PropertyPathFactoryBean`) to create a bean (of type `int`) called `testBean.age` that
|
||||
@@ -217,7 +199,6 @@ has a value equal to the `age` property of the `testBean` bean.
|
||||
|
||||
Now consider the following example, which adds a `<util:property-path/>` element:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -234,7 +215,6 @@ Now consider the following example, which adds a `<util:property-path/>` element
|
||||
<!-- results in 10, which is the value of property 'age' of bean 'testBean' -->
|
||||
<util:property-path id="name" path="testBean.age"/>
|
||||
----
|
||||
====
|
||||
|
||||
The value of the `path` attribute of the `<property-path/>` element follows the form of
|
||||
`beanName.beanProperty`. In this case, it picks up the `age` property of the bean named
|
||||
@@ -250,7 +230,6 @@ argument.
|
||||
|
||||
The following example shows a path being used against another bean, by name:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -271,11 +250,9 @@ The following example shows a path being used against another bean, by name:
|
||||
<property name="propertyPath" value="spouse.age"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
In the following example, a path is evaluated against an inner bean:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -290,12 +267,10 @@ In the following example, a path is evaluated against an inner bean:
|
||||
<property name="propertyPath" value="age"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
There is also a shortcut form, where the bean name is the property path.
|
||||
The following example shows the shortcut form:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -303,13 +278,11 @@ The following example shows the shortcut form:
|
||||
<bean id="person.age"
|
||||
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
|
||||
----
|
||||
====
|
||||
|
||||
This form does mean that there is no choice in the name of the bean. Any reference to it
|
||||
also has to use the same `id`, which is the path. If used as an inner
|
||||
bean, there is no need to refer to it at all, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -320,7 +293,6 @@ bean, there is no need to refer to it at all, as the following example shows:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
You can specifically set the result type in the actual definition. This is not necessary
|
||||
for most use cases, but it can sometimes be useful. See the javadoc for more info on
|
||||
@@ -332,7 +304,6 @@ this feature.
|
||||
|
||||
Consider the following example:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -341,7 +312,6 @@ Consider the following example:
|
||||
<property name="location" value="classpath:com/foo/jdbc-production.properties"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration uses a Spring `FactoryBean` implementation (the
|
||||
`PropertiesFactoryBean`) to instantiate a `java.util.Properties` instance with values
|
||||
@@ -349,14 +319,12 @@ loaded from the supplied <<core.adoc#resources, `Resource`>> location).
|
||||
|
||||
The following example uses a `util:properties` element to make a more concise representation:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<!-- creates a java.util.Properties instance with values loaded from the supplied location -->
|
||||
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -365,7 +333,6 @@ The following example uses a `util:properties` element to make a more concise re
|
||||
|
||||
Consider the following example:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -381,7 +348,6 @@ Consider the following example:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration uses a Spring `FactoryBean` implementation (the
|
||||
`ListFactoryBean`) to create a `java.util.List` instance and initialize it with values taken
|
||||
@@ -389,7 +355,6 @@ from the supplied `sourceList`.
|
||||
|
||||
The following example uses a `<util:list/>` element to make a more concise representation:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -401,14 +366,12 @@ The following example uses a `<util:list/>` element to make a more concise repre
|
||||
<value>porfiry@gov.org</value>
|
||||
</util:list>
|
||||
----
|
||||
====
|
||||
|
||||
You can also explicitly control the exact type of `List` that is instantiated and
|
||||
populated by using the `list-class` attribute on the `<util:list/>` element. For
|
||||
example, if we really need a `java.util.LinkedList` to be instantiated, we could use the
|
||||
following configuration:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -419,7 +382,6 @@ following configuration:
|
||||
<value>d'Arcachon@nemesis.org</value>
|
||||
</util:list>
|
||||
----
|
||||
====
|
||||
|
||||
If no `list-class` attribute is supplied, the container chooses a `List` implementation.
|
||||
|
||||
@@ -430,7 +392,6 @@ If no `list-class` attribute is supplied, the container chooses a `List` impleme
|
||||
|
||||
Consider the following example:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -446,7 +407,6 @@ Consider the following example:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration uses a Spring `FactoryBean` implementation (the
|
||||
`MapFactoryBean`) to create a `java.util.Map` instance initialized with key-value pairs
|
||||
@@ -454,7 +414,6 @@ taken from the supplied `'sourceMap'`.
|
||||
|
||||
The following example uses a `<util:map/>` element to make a more concise representation:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -466,14 +425,12 @@ The following example uses a `<util:map/>` element to make a more concise repres
|
||||
<entry key="porfiry" value="porfiry@gov.org"/>
|
||||
</util:map>
|
||||
----
|
||||
====
|
||||
|
||||
You can also explicitly control the exact type of `Map` that is instantiated and
|
||||
populated by using the `'map-class'` attribute on the `<util:map/>` element. For
|
||||
example, if we really need a `java.util.TreeMap` to be instantiated, we could use the
|
||||
following configuration:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -484,7 +441,6 @@ following configuration:
|
||||
<entry key="porfiry" value="porfiry@gov.org"/>
|
||||
</util:map>
|
||||
----
|
||||
====
|
||||
|
||||
If no `'map-class'` attribute is supplied, the container chooses a `Map` implementation.
|
||||
|
||||
@@ -495,7 +451,6 @@ If no `'map-class'` attribute is supplied, the container chooses a `Map` impleme
|
||||
|
||||
Consider the following example:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -511,7 +466,6 @@ Consider the following example:
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration uses a Spring `FactoryBean` implementation (the
|
||||
`SetFactoryBean`) to create a `java.util.Set` instance initialized with values taken
|
||||
@@ -519,7 +473,6 @@ from the supplied `sourceSet`.
|
||||
|
||||
The following example uses a `<util:set/>` element to make a more concise representation:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -531,14 +484,12 @@ The following example uses a `<util:set/>` element to make a more concise repres
|
||||
<value>porfiry@gov.org</value>
|
||||
</util:set>
|
||||
----
|
||||
====
|
||||
|
||||
You can also explicitly control the exact type of `Set` that is instantiated and
|
||||
populated by using the `set-class` attribute on the `<util:set/>` element. For
|
||||
example, if we really need a `java.util.TreeSet` to be instantiated, we could use the
|
||||
following configuration:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -549,7 +500,6 @@ following configuration:
|
||||
<value>porfiry@gov.org</value>
|
||||
</util:set>
|
||||
----
|
||||
====
|
||||
|
||||
If no `set-class` attribute is supplied, the container chooses a `Set` implementation.
|
||||
|
||||
@@ -568,7 +518,6 @@ the following preamble at the top of your Spring XML configuration file (the tex
|
||||
snippet references the correct schema so that the tags in the `aop` namespace
|
||||
are available to you):
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -582,7 +531,6 @@ are available to you):
|
||||
<!-- bean definitions here -->
|
||||
</beans>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -595,7 +543,6 @@ a lot of the "`grunt`" work in Spring, such as `BeanfactoryPostProcessors`. The
|
||||
snippet references the correct schema so that the elements in the `context` namespace are
|
||||
available to you:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -609,7 +556,6 @@ available to you:
|
||||
<!-- bean definitions here -->
|
||||
</beans>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -696,7 +642,6 @@ The following example shows the `<meta/>` element in the context of a surroundin
|
||||
(note that, without any logic to interpret it, the metadata is effectively useless
|
||||
as it stands).
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -714,7 +659,7 @@ as it stands).
|
||||
</beans>
|
||||
----
|
||||
<1> This is the example `meta` element
|
||||
====
|
||||
|
||||
|
||||
In the case of the preceding example, you could assume that there is some logic that
|
||||
consumes the bean definition and sets up some caching infrastructure that uses the supplied
|
||||
@@ -749,7 +694,6 @@ XML extension (a custom XML element) that lets us configure objects of the type
|
||||
`SimpleDateFormat` (from the `java.text` package). When we are done,
|
||||
we will be able to define bean definitions of type `SimpleDateFormat` as follows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -757,7 +701,6 @@ we will be able to define bean definitions of type `SimpleDateFormat` as follows
|
||||
pattern="yyyy-MM-dd HH:mm"
|
||||
lenient="true"/>
|
||||
----
|
||||
====
|
||||
|
||||
(We include much more detailed
|
||||
examples follow later in this appendix. The intent of this first simple example is to walk you
|
||||
@@ -772,7 +715,6 @@ Creating an XML configuration extension for use with Spring's IoC container star
|
||||
authoring an XML Schema to describe the extension. For our example, we use the following schema
|
||||
to configure `SimpleDateFormat` objects:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -804,14 +746,12 @@ to configure `SimpleDateFormat` objects:
|
||||
(meaning they have an `id` attribute that we can use as the bean identifier in the
|
||||
container). We can use this attribute because we imported the Spring-provided
|
||||
`beans` namespace.
|
||||
====
|
||||
|
||||
|
||||
The preceding schema lets us configure `SimpleDateFormat` objects directly in an
|
||||
XML application context file by using the `<myns:dateformat/>` element, as the following
|
||||
example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -819,12 +759,10 @@ example shows:
|
||||
pattern="yyyy-MM-dd HH:mm"
|
||||
lenient="true"/>
|
||||
----
|
||||
====
|
||||
|
||||
Note that, after we have created the infrastructure classes, the preceding snippet of XML is
|
||||
essentially the same as the following XML snippet:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -833,7 +771,6 @@ essentially the same as the following XML snippet:
|
||||
<property name="lenient" value="true"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The second of the two preceding snippets
|
||||
creates a bean in the container (identified by the name `dateFormat` of type
|
||||
@@ -876,7 +813,6 @@ element results in a single `SimpleDateFormat` bean definition). Spring features
|
||||
number of convenience classes that support this scenario. In the following example, we
|
||||
use the `NamespaceHandlerSupport` class:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -892,7 +828,6 @@ use the `NamespaceHandlerSupport` class:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
You may notice that there is not actually a whole lot of parsing logic
|
||||
in this class. Indeed, the `NamespaceHandlerSupport` class has a built-in notion of
|
||||
@@ -916,7 +851,6 @@ responsible for parsing one distinct top-level XML element defined in the schema
|
||||
the parser, we' have access to the XML element (and thus to its subelements, too) so that
|
||||
we can parse our custom XML content, as you can see in the following example:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
package org.springframework.samples.xml;
|
||||
@@ -954,7 +888,7 @@ the basic grunt work of creating a single `BeanDefinition`.
|
||||
|
||||
<2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our
|
||||
single `BeanDefinition` represents.
|
||||
====
|
||||
|
||||
|
||||
In this simple case, this is all that we need to do. The creation of our single
|
||||
`BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as
|
||||
@@ -980,13 +914,11 @@ these special properties files, the formats of which are detailed in the next tw
|
||||
The properties file called `spring.handlers` contains a mapping of XML Schema URIs to
|
||||
namespace handler classes. For our example, we need to write the following:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler
|
||||
----
|
||||
====
|
||||
|
||||
(The `:` character is a valid delimiter in the Java properties format, so
|
||||
`:` character in the URI needs to be escaped with a backslash.)
|
||||
@@ -1009,13 +941,11 @@ properties file, Spring searches for the schema (in this case,
|
||||
`myns.xsd` in the `org.springframework.samples.xml` package) on the classpath.
|
||||
The following snippet shows the line we need to add for our custom schema:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
|
||||
----
|
||||
====
|
||||
|
||||
(Remember that the `:` character must be escaped.)
|
||||
|
||||
@@ -1032,7 +962,6 @@ one of the "`custom`" extensions that Spring provides. The following
|
||||
example uses the custom `<dateformat/>` element developed in the previous steps
|
||||
in a Spring XML configuration file:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1057,7 +986,6 @@ in a Spring XML configuration file:
|
||||
</beans>
|
||||
----
|
||||
<1> Our custom bean.
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1074,7 +1002,6 @@ This section presents some more detailed examples of custom XML extensions.
|
||||
The example presented in this section shows how you to write the various artifacts required
|
||||
to satisfy a target of the following configuration:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1096,7 +1023,6 @@ to satisfy a target of the following configuration:
|
||||
|
||||
</beans>
|
||||
----
|
||||
====
|
||||
|
||||
The preceding configuration nests custom extensions within each other. The class
|
||||
that is actually configured by the `<foo:component/>` element is the `Component`
|
||||
@@ -1105,7 +1031,6 @@ setter method for the `components` property. This makes it hard (or rather impos
|
||||
to configure a bean definition for the `Component` class by using setter injection.
|
||||
The following listing shows the `Component` class:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1138,12 +1063,11 @@ The following listing shows the `Component` class:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The typical solution to this issue is to create a custom `FactoryBean` that exposes a
|
||||
setter property for the `components` property. The following listing shows such a custom
|
||||
`FactoryBean`:
|
||||
====
|
||||
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
@@ -1186,7 +1110,6 @@ setter property for the `components` property. The following listing shows such
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
This works nicely, but it exposes a lot of Spring plumbing to the
|
||||
end user. What we are going to do is write a custom extension that hides away all of
|
||||
@@ -1194,7 +1117,6 @@ this Spring plumbing. If we stick to <<xsd-custom-introduction,the steps describ
|
||||
previously>>, we start off by creating the XSD schema to define the structure of our
|
||||
custom tag, as the following listing shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1218,11 +1140,9 @@ custom tag, as the following listing shows:
|
||||
|
||||
</xsd:schema>
|
||||
----
|
||||
====
|
||||
|
||||
Again following <<xsd-custom-introduction,the process described earlier>>, we then create a custom `NamespaceHandler`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1238,13 +1158,11 @@ Again following <<xsd-custom-introduction,the process described earlier>>, we th
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Next up is the custom `BeanDefinitionParser`. Remember that we are creating
|
||||
`BeanDefinition` that describes a `ComponentFactoryBean`. The following listing shows our
|
||||
custom `BeanDefinitionParser`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1295,12 +1213,10 @@ custom `BeanDefinitionParser`:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Finally, the various artifacts need to be registered with the Spring XML infrastructure,
|
||||
by modifying the `META-INF/spring.handlers` and `META-INF/spring.schemas` files, as follows:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1314,7 +1230,6 @@ http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler
|
||||
# in 'META-INF/spring.schemas'
|
||||
http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1333,7 +1248,6 @@ http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the nam
|
||||
JCache instance is eagerly started within the surrounding cluster. The following
|
||||
listing shows such a definition:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1342,7 +1256,6 @@ listing shows such a definition:
|
||||
<!-- other dependencies here... -->
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
We can then create another `BeanDefinition` when the
|
||||
`'jcache:cache-name'` attribute is parsed. This `BeanDefinition` then initializes
|
||||
@@ -1350,7 +1263,6 @@ the named JCache for us. We can also modify the existing `BeanDefinition` for th
|
||||
`'checkingAccountService'` so that it has a dependency on this new
|
||||
JCache-initializing `BeanDefinition`. The following listing shows our `JCacheInitializer`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1370,12 +1282,10 @@ JCache-initializing `BeanDefinition`. The following listing shows our `JCacheIni
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Now we can move onto the custom extension. First, we need to author the XSD schema that describes the
|
||||
custom attribute, as follows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1390,11 +1300,9 @@ custom attribute, as follows:
|
||||
|
||||
</xsd:schema>
|
||||
----
|
||||
====
|
||||
|
||||
Next, we need to create the associated `NamespaceHandler`, as follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1411,13 +1319,11 @@ Next, we need to create the associated `NamespaceHandler`, as follows:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Next, we need to create the parser. Note that, in this case, because we are going to parse an XML
|
||||
attribute, we write a `BeanDefinitionDecorator` rather than a `BeanDefinitionParser`.
|
||||
The following listing shows our `BeanDefinitionDecorator`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1473,12 +1379,10 @@ The following listing shows our `BeanDefinitionDecorator`:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Finally, we need to register the various artifacts with the Spring XML infrastructure
|
||||
by modifying the `META-INF/spring.handlers` and `META-INF/spring.schemas` files, as follows:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1492,4 +1396,3 @@ http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler
|
||||
# in 'META-INF/spring.schemas'
|
||||
http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd
|
||||
----
|
||||
====
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -141,7 +141,6 @@ An `Encoder` allocates data buffers that others must read (and release). So an `
|
||||
doesn't have much to do. However an `Encoder` must take care to release a data buffer if
|
||||
a serialization error occurs while populating the buffer with data. For example:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -158,7 +157,6 @@ a serialization error occurs while populating the buffer with data. For example:
|
||||
}
|
||||
return buffer;
|
||||
----
|
||||
====
|
||||
|
||||
The consumer of an `Encoder` is responsible for releasing the data buffers it receives.
|
||||
In a WebFlux application, the output of the `Encoder` is used to write to the HTTP server
|
||||
|
||||
@@ -65,7 +65,6 @@ The complete language reference can be found in
|
||||
The following code introduces the SpEL API to evaluate the literal string expression,
|
||||
`Hello World`.
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -74,7 +73,7 @@ The following code introduces the SpEL API to evaluate the literal string expres
|
||||
String message = (String) exp.getValue();
|
||||
----
|
||||
<1> The value of the message variable is `'Hello World'`.
|
||||
====
|
||||
|
||||
|
||||
The SpEL classes and interfaces you are most likely to use are located in the
|
||||
`org.springframework.expression` package and its sub-packages, such as `spel.support`.
|
||||
@@ -91,7 +90,6 @@ and calling constructors.
|
||||
|
||||
In the following example of method invocation, we call the `concat` method on the string literal:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -100,11 +98,10 @@ In the following example of method invocation, we call the `concat` method on th
|
||||
String message = (String) exp.getValue();
|
||||
----
|
||||
<1> The value of `message` is now 'Hello World!'.
|
||||
====
|
||||
|
||||
|
||||
The following example of calling a JavaBean property calls the `String` property `Bytes`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -115,13 +112,12 @@ The following example of calling a JavaBean property calls the `String` property
|
||||
byte[] bytes = (byte[]) exp.getValue();
|
||||
----
|
||||
<1> This line converts the literal to a byte array.
|
||||
====
|
||||
|
||||
|
||||
SpEL also supports nested properties by using standard dot notation (such as
|
||||
`prop1.prop2.prop3`) and the setting of property values. Public fields may also be accessed.
|
||||
The following example shows how to use dot notation to get the length of a literal:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -132,12 +128,11 @@ The following example shows how to use dot notation to get the length of a liter
|
||||
int length = (Integer) exp.getValue();
|
||||
----
|
||||
<1> `'Hello World'.bytes.length` gives the length of the literal.
|
||||
====
|
||||
|
||||
|
||||
The String's constructor can be called instead of using a string literal, as the following
|
||||
example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -146,7 +141,7 @@ example shows:
|
||||
String message = exp.getValue(String.class);
|
||||
----
|
||||
<1> Construct a new `String` from the literal and make it be upper case.
|
||||
====
|
||||
|
||||
|
||||
Note the use of the generic method: `public <T> T getValue(Class<T> desiredResultType)`.
|
||||
Using this method removes the need to cast the value of the expression to the desired
|
||||
@@ -158,7 +153,6 @@ against a specific object instance (called the root object). The following examp
|
||||
how to retrieve the `name` property from an instance of the `Inventor` class or
|
||||
create a boolean condition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -180,7 +174,6 @@ create a boolean condition:
|
||||
// result == true
|
||||
----
|
||||
<1> Parse `name` as an expression.
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -228,7 +221,6 @@ to set a `List` property. The type of the property is actually `List<Boolean>`.
|
||||
recognizes that the elements of the list need to be converted to `Boolean` before
|
||||
being placed in it. The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -248,7 +240,6 @@ being placed in it. The following example shows how to do so:
|
||||
// b is false
|
||||
Boolean b = simple.booleanList.get(0);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -265,7 +256,6 @@ and specifying an index that is beyond the end of the current size of the array
|
||||
list, you can automatically grow the array or list to accommodate that index. The following
|
||||
example demonstrates how to automatically grow the list:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -289,7 +279,6 @@ example demonstrates how to automatically grow the list:
|
||||
// demo.list will now be a real collection of 4 entries
|
||||
// Each entry is a new empty String
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -317,11 +306,9 @@ on repeated evaluations.
|
||||
|
||||
Consider the following basic expression:
|
||||
|
||||
====
|
||||
----
|
||||
someArray[0].someProperty.someOtherProperty < 0.1
|
||||
----
|
||||
====
|
||||
|
||||
Because the preceding expression involves array access, some property de-referencing,
|
||||
and numeric operations, the performance gain can be very noticeable. In an example
|
||||
@@ -361,7 +348,6 @@ since part of the expression may be running twice.
|
||||
After selecting a mode, use the `SpelParserConfiguration` to configure the parser. The
|
||||
following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -376,7 +362,6 @@ following example shows how to do so:
|
||||
|
||||
Object payload = expr.getValue(message);
|
||||
----
|
||||
====
|
||||
|
||||
When you specify the compiler mode, you can also specify a classloader (passing null is allowed).
|
||||
Compiled expressions are defined in a child classloader created under any that is supplied.
|
||||
@@ -425,7 +410,6 @@ form `#{ <expression string> }`.
|
||||
A property or constructor argument value can be set by using expressions, as the following
|
||||
example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -435,12 +419,10 @@ example shows:
|
||||
<!-- other properties -->
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The `systemProperties` variable is predefined, so you can use it in your expressions, as
|
||||
the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -450,14 +432,12 @@ the following example shows:
|
||||
<!-- other properties -->
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Note that you do not have to prefix the predefined variable with the `#`
|
||||
symbol in this context.
|
||||
|
||||
You can also refer to other bean properties by name, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -473,7 +453,6 @@ You can also refer to other bean properties by name, as the following example sh
|
||||
<!-- other properties -->
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -485,7 +464,6 @@ parameters.
|
||||
|
||||
The following example sets the default value of a field variable:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -504,11 +482,9 @@ The following example sets the default value of a field variable:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The following example shows the equivalent but on a property setter method:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -527,12 +503,10 @@ The following example shows the equivalent but on a property setter method:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Autowired methods and constructors can also use the `@Value` annotation, as the following
|
||||
examples show:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -571,7 +545,6 @@ examples show:
|
||||
// ...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -611,7 +584,6 @@ The following listing shows simple usage of literals. Typically, they are not us
|
||||
in isolation like this but, rather, as part of a more complex expression -- for example,
|
||||
using a literal on one side of a logical comparison operator.
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -629,7 +601,6 @@ using a literal on one side of a logical comparison operator.
|
||||
|
||||
Object nullValue = parser.parseExpression("null").getValue();
|
||||
----
|
||||
====
|
||||
|
||||
Numbers support the use of the negative sign, exponential notation, and decimal points.
|
||||
By default, real numbers are parsed by using Double.parseDouble().
|
||||
@@ -645,7 +616,6 @@ data listed in the <<expressions-example-classes,Classes used in the examples>>
|
||||
To navigate "`down`" and get Tesla's year of birth and Pupin's city of birth, we use the following
|
||||
expressions:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -654,13 +624,11 @@ expressions:
|
||||
|
||||
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
Case insensitivity is allowed for the first letter of property names. The contents of
|
||||
arrays and lists are obtained by using square bracket notation, as the following example
|
||||
shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -684,13 +652,11 @@ shows:
|
||||
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(
|
||||
context, ieee, String.class);
|
||||
----
|
||||
====
|
||||
|
||||
The contents of maps are obtained by specifying the literal key value within the
|
||||
brackets. In the following example, because keys for the `Officers` map are strings, we can specify
|
||||
string literals:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -707,7 +673,6 @@ string literals:
|
||||
parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(
|
||||
societyContext, "Croatia");
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -716,7 +681,6 @@ string literals:
|
||||
|
||||
You can directly express lists in an expression by using `{}` notation.
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -725,7 +689,6 @@ You can directly express lists in an expression by using `{}` notation.
|
||||
|
||||
List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
`{}` by itself means an empty list. For performance reasons, if the list is itself
|
||||
entirely composed of fixed literals, a constant list is created to represent the
|
||||
@@ -739,7 +702,6 @@ expression (rather than building a new list on each evaluation).
|
||||
You can also directly express maps in an expression by using `{key:value}` notation. The
|
||||
following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -748,7 +710,6 @@ following example shows how to do so:
|
||||
|
||||
Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
`{:}` by itself means an empty map. For performance reasons, if the map is itself composed
|
||||
of fixed literals or other nested constant structures (lists or maps), a constant map is created
|
||||
@@ -763,7 +724,6 @@ is optional. The examples above do not use quoted keys.
|
||||
You can build arrays by using the familiar Java syntax, optionally supplying an initializer
|
||||
to have the array populated at construction time. The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -775,7 +735,6 @@ to have the array populated at construction time. The following example shows ho
|
||||
// Multi dimensional array
|
||||
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
You cannot currently supply an initializer when you construct
|
||||
multi-dimensional array.
|
||||
@@ -789,7 +748,6 @@ You can invoke methods by using typical Java programming syntax. You can also in
|
||||
on literals. Variable arguments are also supported. The following examples show how to
|
||||
invoke methods:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -800,7 +758,6 @@ invoke methods:
|
||||
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
|
||||
societyContext, Boolean.class);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -822,7 +779,6 @@ The relational operators (equal, not equal, less than, less than or equal, great
|
||||
and greater than or equal) are supported by using standard operator notation. The
|
||||
following listing shows a few examples of operators:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -835,7 +791,6 @@ following listing shows a few examples of operators:
|
||||
// evaluates to true
|
||||
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
@@ -851,7 +806,6 @@ in favor of comparisons against zero (for example, `X > 0` or `X < 0`).
|
||||
In addition to the standard relational operators, SpEL supports the `instanceof` and regular
|
||||
expression-based `matches` operator. The following listing shows examples of both:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -867,7 +821,6 @@ expression-based `matches` operator. The following listing shows examples of bot
|
||||
boolean falseValue = parser.parseExpression(
|
||||
"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
|
||||
----
|
||||
====
|
||||
|
||||
CAUTION: Be careful with primitive types, as they are immediately boxed up to the wrapper type,
|
||||
so `1 instanceof T(int)` evaluates to `false` while `1 instanceof T(Integer)`
|
||||
@@ -901,7 +854,6 @@ SpEL supports the following logical operators:
|
||||
|
||||
The following example shows how to use the logical operators
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -932,7 +884,6 @@ The following example shows how to use the logical operators
|
||||
String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
|
||||
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[expressions-operators-mathematical]]
|
||||
@@ -943,7 +894,6 @@ and division operators only on numbers. You can also use
|
||||
the modulus (%) and exponential power (^) operators. Standard operator precedence is enforced. The
|
||||
following example shows the mathematical operators in use:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -976,7 +926,6 @@ following example shows the mathematical operators in use:
|
||||
// Operator precedence
|
||||
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[expressions-assignment]]
|
||||
@@ -986,7 +935,6 @@ To setting a property, use the assignment operator (`=`). This is typically
|
||||
done within a call to `setValue` but can also be done inside a call to `getValue`. The
|
||||
following listing shows both ways to use the assignment operator:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -999,7 +947,6 @@ following listing shows both ways to use the assignment operator:
|
||||
String aleks = parser.parseExpression(
|
||||
"Name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1014,7 +961,6 @@ type). Static methods are invoked by using this operator as well. The
|
||||
fully qualified, but all other type references must be. The following example shows how
|
||||
to use the `T` operator:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1026,7 +972,6 @@ to use the `T` operator:
|
||||
"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
|
||||
.getValue(Boolean.class);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1037,7 +982,6 @@ You can invoke constructors by using the `new` operator. You should use the full
|
||||
for all but the primitive types (`int`, `float`, and so on) and String. The following
|
||||
example shows how to use the `new` operator to invoke constructors:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1050,7 +994,6 @@ example shows how to use the `new` operator to invoke constructors:
|
||||
"Members.add(new org.spring.samples.spel.inventor.Inventor(
|
||||
'Albert Einstein', 'German'))").getValue(societyContext);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1061,7 +1004,6 @@ You can reference variables in the expression by using the `#variableName` synta
|
||||
are set by using the `setVariable` method on `EvaluationContext` implementations. The
|
||||
following example shows how to use variables:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1073,7 +1015,6 @@ following example shows how to use variables:
|
||||
parser.parseExpression("Name = #newName").getValue(context, tesla);
|
||||
System.out.println(tesla.getName()) // "Mike Tesla"
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[expressions-this-root]]
|
||||
@@ -1085,7 +1026,6 @@ defined and refers to the root context object. Although `#this` may vary as comp
|
||||
an expression are evaluated, `#root` always refers to the root. The following examples
|
||||
show how to use the `#this` and `#root` variables:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1103,7 +1043,6 @@ show how to use the `#this` and `#root` variables:
|
||||
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
|
||||
"#primes.?[#this>10]").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1114,7 +1053,6 @@ You can extend SpEL by registering user-defined functions that can be called wit
|
||||
expression string. The function is registered through the `EvaluationContext`. The
|
||||
following example shows how to register a user-defined function:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1123,11 +1061,9 @@ following example shows how to register a user-defined function:
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
context.setVariable("myFunction", method);
|
||||
----
|
||||
====
|
||||
|
||||
For example, consider the following utility method that reverses a string:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1142,11 +1078,9 @@ For example, consider the following utility method that reverses a string:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
You can then register and use the preceding method, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1159,7 +1093,6 @@ You can then register and use the preceding method, as the following example sho
|
||||
String helloWorldReversed = parser.parseExpression(
|
||||
"#reverseString('hello')").getValue(context, String.class);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1170,7 +1103,6 @@ If the evaluation context has been configured with a bean resolver, you can
|
||||
look up beans from an expression by using the `@` symbol. The following example shows how
|
||||
to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1181,12 +1113,10 @@ to do so:
|
||||
// This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
|
||||
Object bean = parser.parseExpression("@something").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
To access a factory bean itself, you should instead prefix the bean name with an `&` symbol.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1197,7 +1127,6 @@ The following example shows how to do so:
|
||||
// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
|
||||
Object bean = parser.parseExpression("&foo").getValue(context);
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1207,19 +1136,16 @@ The following example shows how to do so:
|
||||
You can use the ternary operator for performing if-then-else conditional logic inside
|
||||
the expression. The following listing shows a minimal example:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
String falseString = parser.parseExpression(
|
||||
"false ? 'trueExp' : 'falseExp'").getValue(String.class);
|
||||
----
|
||||
====
|
||||
|
||||
In this case, the boolean `false` results in returning the string value `'falseExp'`. A more
|
||||
realistic example follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1233,7 +1159,6 @@ realistic example follows:
|
||||
.getValue(societyContext, String.class);
|
||||
// queryResultString = "Nikola Tesla is a member of the IEEE Society"
|
||||
----
|
||||
====
|
||||
|
||||
See the next section on the Elvis operator for an even shorter syntax for the
|
||||
ternary operator.
|
||||
@@ -1248,19 +1173,16 @@ http://www.groovy-lang.org/operators.html#_elvis_operator[Groovy] language.
|
||||
With the ternary operator syntax, you usually have to repeat a variable twice, as the
|
||||
following example shows:
|
||||
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
String name = "Elvis Presley";
|
||||
String displayName = (name != null ? name : "Unknown");
|
||||
----
|
||||
====
|
||||
|
||||
Instead, you can use the Elvis operator (named for the resemblance to Elvis' hair style).
|
||||
The following example shows how to use the Elvis operator:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1269,11 +1191,9 @@ The following example shows how to use the Elvis operator:
|
||||
String name = parser.parseExpression("name?:'Unknown'").getValue(String.class);
|
||||
System.out.println(name); // 'Unknown'
|
||||
----
|
||||
====
|
||||
|
||||
The following listing shows A more complex example:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1288,14 +1208,12 @@ The following listing shows A more complex example:
|
||||
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
|
||||
System.out.println(name); // Elvis Presley
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
=====
|
||||
You can use the Elvis operator to apply default values in expressions. The folloiwng
|
||||
example shows how to use the Elvis operator in a `@Value` expression:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1303,11 +1221,9 @@ example shows how to use the Elvis operator in a `@Value` expression:
|
||||
----
|
||||
|
||||
This will inject a system property `pop3.port` if it is defined or 25 if not.
|
||||
====
|
||||
=====
|
||||
|
||||
|
||||
|
||||
[[expressions-operator-safe-navigation]]
|
||||
=== Safe Navigation Operator
|
||||
|
||||
@@ -1318,7 +1234,6 @@ it is not null before accessing methods or properties of the object. To avoid th
|
||||
safe navigation operator returns null instead of throwing an exception. The following
|
||||
example shows how to use the safe navigation operator:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1335,7 +1250,6 @@ example shows how to use the safe navigation operator:
|
||||
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
||||
System.out.println(city); // null - does not throw NullPointerException!!!
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1349,14 +1263,12 @@ Selection uses a syntax of `.?[selectionExpression]`. It filters the collection
|
||||
returns a new collection that contain a subset of the original elements. For example,
|
||||
selection lets us easily get a list of Serbian inventors, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
List<Inventor> list = (List<Inventor>) parser.parseExpression(
|
||||
"Members.?[Nationality == 'Serbian']").getValue(societyContext);
|
||||
----
|
||||
====
|
||||
|
||||
Selection is possible upon both lists and maps. For a list, the selection
|
||||
criteria is evaluated against each individual list element. Against a map, the
|
||||
@@ -1367,13 +1279,11 @@ the selection.
|
||||
The following expression returns a new map that consists of those elements of the original map
|
||||
where the entry value is less than 27:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
Map newMap = parser.parseExpression("map.?[value<27]").getValue();
|
||||
----
|
||||
====
|
||||
|
||||
In addition to returning all the selected elements, you can retrieve only the
|
||||
first or the last value. To obtain the first entry matching the selection, the syntax is
|
||||
@@ -1391,14 +1301,12 @@ example, suppose we have a list of inventors but want the list of
|
||||
cities where they were born. Effectively, we want to evaluate 'placeOfBirth.city' for
|
||||
every entry in the inventor list. The following example uses projection to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
// returns ['Smiljan', 'Idvor' ]
|
||||
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");
|
||||
----
|
||||
====
|
||||
|
||||
You can also use a map to drive projection and, in this case, the projection expression is
|
||||
evaluated against each entry in the map (represented as a Java `Map.Entry`). The result
|
||||
@@ -1415,7 +1323,6 @@ Each evaluation block is delimited with prefix and suffix characters that you ca
|
||||
define. A common choice is to use `#{ }` as the delimiters, as the following example
|
||||
shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1425,7 +1332,6 @@ shows:
|
||||
|
||||
// evaluates to "random number is 0.7038186818312008"
|
||||
----
|
||||
====
|
||||
|
||||
The string is evaluated by concatenating the literal text `'random number is '` with the
|
||||
result of evaluating the expression inside the `#{ }` delimiter (in this case, the result
|
||||
@@ -1434,7 +1340,6 @@ is of the type `ParserContext`. The `ParserContext` interface is used to influen
|
||||
the expression is parsed in order to support the expression templating functionality.
|
||||
The definition of `TemplateParserContext` follows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1453,7 +1358,6 @@ The definition of `TemplateParserContext` follows:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1464,7 +1368,6 @@ The definition of `TemplateParserContext` follows:
|
||||
This section lists the classes used in the examples throughout this chapter.
|
||||
|
||||
.Inventor.java
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1538,10 +1441,8 @@ This section lists the classes used in the examples throughout this chapter.
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
.PlaceOfBirth.java
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1579,10 +1480,8 @@ This section lists the classes used in the examples throughout this chapter.
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
.Society.java
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1627,4 +1526,3 @@ This section lists the classes used in the examples throughout this chapter.
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
@@ -37,7 +37,6 @@ Spring's `Resource` interface is meant to be a more capable interface for abstra
|
||||
access to low-level resources. The following listing shows the `Resource` interface
|
||||
definition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -59,13 +58,11 @@ definition:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
As the definition of the `Resource` interface shows, it extends the `InputStreamSource`
|
||||
interface. The following listing shows the definition of the `InputStreamSource`
|
||||
interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -75,7 +72,6 @@ interface:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Some of the most important methods from the `Resource` interface are:
|
||||
|
||||
@@ -227,7 +223,6 @@ The `ResourceLoader` interface is meant to be implemented by objects that can re
|
||||
(that is, load) `Resource` instances. The following listing shows the `ResourceLoader`
|
||||
interface definition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -237,7 +232,6 @@ interface definition:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
All application contexts implement the `ResourceLoader` interface. Therefore, all
|
||||
application contexts may be used to obtain `Resource` instances.
|
||||
@@ -247,13 +241,11 @@ specified doesn't have a specific prefix, you get back a `Resource` type that is
|
||||
appropriate to that particular application context. For example, assume the following
|
||||
snippet of code was executed against a `ClassPathXmlApplicationContext` instance:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
|
||||
----
|
||||
====
|
||||
|
||||
Against a `ClassPathXmlApplicationContext`, that code returns a `ClassPathResource`. If the same method were executed
|
||||
against a `FileSystemXmlApplicationContext` instance, it would return a
|
||||
@@ -267,19 +259,16 @@ On the other hand, you may also force `ClassPathResource` to be used, regardless
|
||||
application context type, by specifying the special `classpath:` prefix, as the following
|
||||
example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
|
||||
----
|
||||
====
|
||||
|
||||
Similarly, you can force a `UrlResource` to be used by specifying any of the standard
|
||||
`java.net.URL` prefixes. The following pair of examples use the `file` and `http`
|
||||
prefixes:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -291,7 +280,6 @@ prefixes:
|
||||
----
|
||||
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
|
||||
----
|
||||
====
|
||||
|
||||
The following table summarizes the strategy for converting `String` objects to `Resource` objects:
|
||||
|
||||
@@ -327,7 +315,6 @@ The `ResourceLoaderAware` interface is a special marker interface that identifie
|
||||
that expect to be provided with a `ResourceLoader` reference. The following listing shows
|
||||
the definition of the `ResourceLoaderAware` interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -336,7 +323,6 @@ the definition of the `ResourceLoaderAware` interface:
|
||||
void setResourceLoader(ResourceLoader resourceLoader);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
When a class implements `ResourceLoaderAware` and is deployed into an application
|
||||
context (as a Spring-managed bean), it is recognized as `ResourceLoaderAware` by the
|
||||
@@ -381,7 +367,6 @@ register and use a special JavaBeans `PropertyEditor`, which can convert `String
|
||||
to `Resource` objects. So, if `myBean` has a template property of type `Resource`, it can
|
||||
be configured with a simple string for that resource, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -389,7 +374,6 @@ be configured with a simple string for that resource, as the following example s
|
||||
<property name="template" value="some/resource/path/myTemplate.txt"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
Note that the resource path has no prefix. Consequently, because the application context itself is
|
||||
going to be used as the `ResourceLoader`, the resource itself is loaded through a
|
||||
@@ -400,7 +384,6 @@ If you need to force a specific `Resource` type to be used, you can use a prefix
|
||||
The following two examples show how to force a `ClassPathResource` and a
|
||||
`UrlResource` (the latter being used to access a filesystem file):
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -412,7 +395,6 @@ The following two examples show how to force a `ClassPathResource` and a
|
||||
----
|
||||
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -437,25 +419,21 @@ that path and used to load the bean definitions depends on and is appropriate to
|
||||
specific application context. For example, consider the following example, which creates a
|
||||
`ClassPathXmlApplicationContext`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
|
||||
----
|
||||
====
|
||||
|
||||
The bean definitions are loaded from the classpath, because a `ClassPathResource` is
|
||||
used. However, consider the following example, which creates a `FileSystemXmlApplicationContext`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext ctx =
|
||||
new FileSystemXmlApplicationContext("conf/appContext.xml");
|
||||
----
|
||||
====
|
||||
|
||||
Now the bean definition is loaded from a filesystem location (in this case, relative to
|
||||
the current working directory).
|
||||
@@ -487,7 +465,6 @@ then derives the path information from the supplied class.
|
||||
|
||||
Consider the following directory layout:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -497,19 +474,16 @@ com/
|
||||
daos.xml
|
||||
MessengerService.class
|
||||
----
|
||||
====
|
||||
|
||||
The following example shows how a `ClassPathXmlApplicationContext` instance composed of the beans defined in
|
||||
files named `services.xml` and `daos.xml` (which are on the classpath) can be instantiated:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext(
|
||||
new String[] {"services.xml", "daos.xml"}, MessengerService.class);
|
||||
----
|
||||
====
|
||||
|
||||
See the {api-spring-framework}/jca/context/SpringContextResourceAdapter.html[`ClassPathXmlApplicationContext`]
|
||||
javadoc for details on the various constructors.
|
||||
@@ -542,7 +516,6 @@ a resource points to just one resource at a time.
|
||||
|
||||
Path locations can contain Ant-style patterns, as the following example shows:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -551,7 +524,6 @@ com/mycompany/**/applicationContext.xml
|
||||
file:C:/some/path/*-context.xml
|
||||
classpath:com/mycompany/**/applicationContext.xml
|
||||
----
|
||||
====
|
||||
|
||||
When the path location contains an Ant-style pattern, the resolver follows a more complex procedure to try to resolve the
|
||||
wildcard. It produces a `Resource` for the path up to the last non-wildcard segment and
|
||||
@@ -590,14 +562,12 @@ coming from jars be thoroughly tested in your specific environment before you re
|
||||
When constructing an XML-based application context, a location string may use the
|
||||
special `classpath*:` prefix, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
|
||||
----
|
||||
====
|
||||
|
||||
This special prefix specifies that all classpath resources that match the given name
|
||||
must be obtained (internally, this essentially happens through a call to
|
||||
@@ -655,13 +625,11 @@ Ant-style patterns with `classpath:` resources are not guaranteed to find matchi
|
||||
resources if the root package to search is available in multiple class path locations.
|
||||
Consider the following example of a resource location:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
com/mycompany/package1/service-context.xml
|
||||
----
|
||||
====
|
||||
|
||||
Now consider an Ant-style path that someone might use to try to find that file:
|
||||
|
||||
@@ -695,7 +663,6 @@ For backwards compatibility (historical) reasons however, this changes when the
|
||||
to treat all location paths as relative, whether they start with a leading slash or not.
|
||||
In practice, this means the following examples are equivalent:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -709,12 +676,10 @@ In practice, this means the following examples are equivalent:
|
||||
ApplicationContext ctx =
|
||||
new FileSystemXmlApplicationContext("/conf/context.xml");
|
||||
----
|
||||
====
|
||||
|
||||
The following examples are also equivalent (even though it would make sense for them to be different, as one
|
||||
case is relative and the other absolute):
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -728,14 +693,12 @@ case is relative and the other absolute):
|
||||
FileSystemXmlApplicationContext ctx = ...;
|
||||
ctx.getResource("/some/resource/path/myTemplate.txt");
|
||||
----
|
||||
====
|
||||
|
||||
In practice, if you need true absolute filesystem paths, you should avoid using
|
||||
absolute paths with `FileSystemResource` or `FileSystemXmlApplicationContext` and
|
||||
force the use of a `UrlResource` by using the `file:` URL prefix. The following examples
|
||||
show how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -750,4 +713,3 @@ show how to do so:
|
||||
ApplicationContext ctx =
|
||||
new FileSystemXmlApplicationContext("file:///conf/context.xml");
|
||||
----
|
||||
====
|
||||
|
||||
@@ -53,7 +53,6 @@ validators can report validation failures to the `Errors` object.
|
||||
|
||||
Consider the following example of a small data object:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -65,7 +64,6 @@ Consider the following example of a small data object:
|
||||
// the usual getters and setters...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The next example provides validation behavior for the `Person` class by implementing the
|
||||
following two methods of the `org.springframework.validation.Validator` interface:
|
||||
@@ -78,7 +76,6 @@ Implementing a `Validator` is fairly straightforward, especially when you know o
|
||||
`ValidationUtils` helper class that the Spring Framework also provides. The following
|
||||
example implements `Validator` for `Person` instances:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim"]
|
||||
----
|
||||
@@ -102,7 +99,6 @@ example implements `Validator` for `Person` instances:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `static` `rejectIfEmpty(..)` method on the `ValidationUtils` class is used to
|
||||
reject the `name` property if it is `null` or the empty string. Have a look at the
|
||||
@@ -120,7 +116,6 @@ within the `AddressValidator` class without resorting to copy-and-paste, you can
|
||||
dependency-inject or instantiate an `AddressValidator` within your `CustomerValidator`,
|
||||
as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -160,7 +155,6 @@ as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Validation errors are reported to the `Errors` object passed to the validator. In the case
|
||||
of Spring Web MVC, you can use the `<spring:bind/>` tag to inspect the error messages, but
|
||||
@@ -265,7 +259,6 @@ and their default implementations, you should skip ahead to the <<beans-beans-co
|
||||
The following two example classes use the `BeanWrapper` to get and set
|
||||
properties:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -318,12 +311,10 @@ properties:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The following code snippets show some examples of how to retrieve and manipulate some of
|
||||
the properties of instantiated `Companies` and `Employees`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -342,7 +333,6 @@ the properties of instantiated `Companies` and `Employees`:
|
||||
// retrieving the salary of the managingDirector through the company
|
||||
Float salary = (Float) company.getPropertyValue("managingDirector.salary");
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -453,7 +443,6 @@ name as that class, with `Editor` appended. For example, one could have the foll
|
||||
class and package structure, which would be sufficient for the `SomethingEditor` class to be
|
||||
recognized and used as the `PropertyEditor` for `Something`-typed properties.
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -463,7 +452,6 @@ com
|
||||
Something
|
||||
SomethingEditor // the PropertyEditor for the Something class
|
||||
----
|
||||
====
|
||||
|
||||
Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well
|
||||
(described to some extent
|
||||
@@ -472,7 +460,6 @@ here]). The following example use the `BeanInfo` mechanism to
|
||||
explicitly register one or more `PropertyEditor` instances with the properties of an
|
||||
associated class:
|
||||
|
||||
====
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -482,12 +469,10 @@ com
|
||||
Something
|
||||
SomethingBeanInfo // the BeanInfo for the Something class
|
||||
----
|
||||
====
|
||||
|
||||
The following Java source code for the referenced `SomethingBeanInfo` class
|
||||
associates a `CustomNumberEditor` with the `age` property of the `Something` class:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -509,7 +494,6 @@ associates a `CustomNumberEditor` with the `age` property of the `Something` cla
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[beans-beans-conversion-customeditor-registration]]
|
||||
@@ -549,7 +533,6 @@ support for additional `PropertyEditor` instances to an `ApplicationContext`.
|
||||
Consider the following example, which defines a user class called `ExoticType` and another class called `DependsOnExoticType`, which needs
|
||||
`ExoticType` set as a property:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -573,13 +556,11 @@ Consider the following example, which defines a user class called `ExoticType` a
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
When things are properly set up, we want to be able to assign the type property as a
|
||||
string, which a `PropertyEditor` converts into an actual
|
||||
`ExoticType` instance. The following bean definition shows how to set up this relationship:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -587,11 +568,9 @@ string, which a `PropertyEditor` converts into an actual
|
||||
<property name="type" value="aNameForExoticType"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
The `PropertyEditor` implementation could look similar to the following:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -605,12 +584,10 @@ The `PropertyEditor` implementation could look similar to the following:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Finally, the following example shows how to use `CustomEditorConfigurer` to register the new `PropertyEditor` with the
|
||||
`ApplicationContext`, which will then be able to use it as needed:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -622,7 +599,6 @@ Finally, the following example shows how to use `CustomEditorConfigurer` to regi
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
[[beans-beans-conversion-customeditor-registration-per]]
|
||||
===== Using `PropertyEditorRegistrar`
|
||||
@@ -643,7 +619,6 @@ instances for each bean creation attempt.
|
||||
|
||||
The following example shows how to create your own `PropertyEditorRegistrar` implementation:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -660,7 +635,6 @@ The following example shows how to create your own `PropertyEditorRegistrar` imp
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an example
|
||||
`PropertyEditorRegistrar` implementation. Notice how in its implementation of the
|
||||
@@ -669,7 +643,6 @@ See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an
|
||||
The next example shows how to configure a `CustomEditorConfigurer` and inject an instance of our
|
||||
`CustomPropertyEditorRegistrar` into it:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -684,7 +657,6 @@ The next example shows how to configure a `CustomEditorConfigurer` and inject an
|
||||
<bean id="customPropertyEditorRegistrar"
|
||||
class="com.foo.editors.spring.CustomPropertyEditorRegistrar"/>
|
||||
----
|
||||
====
|
||||
|
||||
Finally (and in a bit of a departure from the focus of this chapter for those of you
|
||||
using <<web.adoc#mvc,Spring's MVC web framework>>), using `PropertyEditorRegistrars` in
|
||||
@@ -692,7 +664,6 @@ conjunction with data-binding `Controllers` (such as `SimpleFormController`) can
|
||||
convenient. The following example uses a `PropertyEditorRegistrar` in the
|
||||
implementation of an `initBinder(..)` method:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -712,7 +683,6 @@ implementation of an `initBinder(..)` method:
|
||||
// other methods to do with registering a User
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
This style of `PropertyEditor` registration can lead to concise code (the implementation
|
||||
of `initBinder(..)` is only one line long) and lets common `PropertyEditor`
|
||||
@@ -740,7 +710,6 @@ application where type conversion is needed.
|
||||
The SPI to implement type conversion logic is simple and strongly typed, as the following
|
||||
interface definition shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -751,7 +720,6 @@ interface definition shows:
|
||||
T convert(S source);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
To create your own converter, implement the `Converter` interface and parameterize `S`
|
||||
as the type you are converting from and `T` as the type you are converting to. You can also transparently apply such a
|
||||
@@ -768,7 +736,6 @@ Several converter implementations are provided in the `core.convert.support` pac
|
||||
a convenience. These include converters from strings to numbers and other common types.
|
||||
The following listing shows the `StringToInteger` class, which is a typical `Converter` implementation:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -781,7 +748,6 @@ The following listing shows the `StringToInteger` class, which is a typical `Con
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -792,7 +758,6 @@ When you need to centralize the conversion logic for an entire class hierarchy
|
||||
(for example, when converting from `String` to `Enum` objects), you can implement
|
||||
`ConverterFactory`, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -803,7 +768,6 @@ When you need to centralize the conversion logic for an entire class hierarchy
|
||||
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Parameterize S to be the type you are converting from and R to be the base type defining
|
||||
the __range__ of classes you can convert to. Then implement `getConverter(Class<T>)`,
|
||||
@@ -811,7 +775,6 @@ where T is a subclass of R.
|
||||
|
||||
Consider the `StringToEnumConverterFactory` as an example:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -837,7 +800,6 @@ Consider the `StringToEnumConverterFactory` as an example:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -852,7 +814,6 @@ context that you can use when you implement your conversion logic. Such context
|
||||
type conversion be driven by a field annotation or by generic information declared on a
|
||||
field signature. The following listing shows the interface definition of `GenericConverter`:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -865,7 +826,6 @@ field signature. The following listing shows the interface definition of `Generi
|
||||
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
To implement a `GenericConverter`, have `getConvertibleTypes()` return the supported
|
||||
source->target type pairs. Then implement `convert(Object, TypeDescriptor,
|
||||
@@ -894,7 +854,6 @@ on the target field, or you might want to run a `Converter` only if a specific m
|
||||
`ConditionalGenericConverter` is the union of the `GenericConverter` and
|
||||
`ConditionalConverter` interfaces that lets you define such custom matching criteria:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -906,7 +865,6 @@ on the target field, or you might want to run a `Converter` only if a specific m
|
||||
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
A good example of a `ConditionalGenericConverter` is an `EntityConverter` that converts
|
||||
between a persistent entity identifier and an entity reference. Such an `EntityConverter`
|
||||
@@ -922,7 +880,6 @@ might match only if the target entity type declares a static finder method (for
|
||||
`ConversionService` defines a unified API for executing type conversion logic at
|
||||
runtime. Converters are often executed behind the following facade interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -940,7 +897,6 @@ runtime. Converters are often executed behind the following facade interface:
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Most `ConversionService` implementations also implement `ConverterRegistry`, which
|
||||
provides an SPI for registering converters. Internally, a `ConversionService`
|
||||
@@ -969,21 +925,18 @@ system is used.
|
||||
To register a default `ConversionService` with Spring, add the following bean definition
|
||||
with an `id` of `conversionService`:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="conversionService"
|
||||
class="org.springframework.context.support.ConversionServiceFactoryBean"/>
|
||||
----
|
||||
====
|
||||
|
||||
A default `ConversionService` can convert between strings, numbers, enums, collections,
|
||||
maps, and other common types. To supplement or override the default converters with your
|
||||
own custom converters, set the `converters` property. Property values can implement
|
||||
any of the `Converter`, `ConverterFactory`, or `GenericConverter` interfaces.
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -996,7 +949,6 @@ any of the `Converter`, `ConverterFactory`, or `GenericConverter` interfaces.
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
It is also common to use a `ConversionService` within a Spring MVC application. See
|
||||
<<web.adoc#mvc-config-conversion, Conversion and Formatting>> in the Spring MVC chapter.
|
||||
@@ -1013,7 +965,6 @@ In certain situations, you may wish to apply formatting during conversion. See
|
||||
To work with a `ConversionService` instance programmatically, you can inject a reference to
|
||||
it like you would for any other bean. The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1030,7 +981,6 @@ it like you would for any other bean. The following example shows how to do so:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
For most use cases, you can use the `convert` method that specifies the `targetType`, but it
|
||||
does not work with more complex types, such as a collection of a parameterized element.
|
||||
@@ -1040,7 +990,6 @@ you need to provide a formal definition of the source and target types.
|
||||
Fortunately, `TypeDescriptor` provides various options to make doing so straightforward,
|
||||
as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1051,7 +1000,6 @@ as the following example shows:
|
||||
TypeDescriptor.forObject(input), // List<Integer> type descriptor
|
||||
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));
|
||||
----
|
||||
====
|
||||
|
||||
Note that `DefaultConversionService` automatically registers converters that are
|
||||
appropriate for most environments. This includes collection converters, scalar
|
||||
@@ -1100,7 +1048,6 @@ provides a unified type conversion API for both SPIs.
|
||||
The `Formatter` SPI to implement field formatting logic is simple and strongly typed. The
|
||||
following listing shows the `Formatter` interface definition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1109,12 +1056,10 @@ following listing shows the `Formatter` interface definition:
|
||||
public interface Formatter<T> extends Printer<T>, Parser<T> {
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
`Formatter` extends from the `Printer` and `Parser` building-block interfaces. The
|
||||
following listing shows the definitions of those two interfaces:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1134,7 +1079,6 @@ following listing shows the definitions of those two interfaces:
|
||||
T parse(String clientValue, Locale locale) throws ParseException;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
To create your own `Formatter`, implement the `Formatter` interface shown earlier.
|
||||
Parameterize `T` to be the type of object you wish to format -- for example,
|
||||
@@ -1153,7 +1097,6 @@ formatting support based on the http://joda-time.sourceforge.net[Joda-Time libra
|
||||
|
||||
The following `DateFormatter` is an example `Formatter` implementation:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1188,7 +1131,6 @@ The following `DateFormatter` is an example `Formatter` implementation:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The Spring team welcomes community-driven `Formatter` contributionsSee
|
||||
https://jira.spring.io/browse/SPR[jira.spring.io] to contribute.
|
||||
@@ -1202,7 +1144,6 @@ Field formatting can be configured by field type or annotation. To bind
|
||||
an annotation to a `Formatter`, implement `AnnotationFormatterFactory`. The following
|
||||
listing shows the definition of the `AnnotationFormatterFactory` interface:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1217,7 +1158,6 @@ listing shows the definition of the `AnnotationFormatterFactory` interface:
|
||||
Parser<?> getParser(A annotation, Class<?> fieldType);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
To create an implementation:
|
||||
. Parameterize A to be the field `annotationType` with which you wish to associate
|
||||
@@ -1230,7 +1170,6 @@ The following example `AnnotationFormatterFactory` implementation binds the `@Nu
|
||||
annotation to a formatter to let a number style or pattern be
|
||||
specified:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1267,12 +1206,10 @@ specified:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
To trigger formatting, you can annotate fields with @NumberFormat, as the following
|
||||
example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1282,7 +1219,6 @@ example shows:
|
||||
private BigDecimal decimal;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1297,7 +1233,6 @@ package. You can use `@NumberFormat` to format `Number` fields such as `Double`
|
||||
The following example uses `@DateTimeFormat` to format a `java.util.Date` as an ISO Date
|
||||
(yyyy-MM-dd):
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1307,7 +1242,6 @@ The following example uses `@DateTimeFormat` to format a `java.util.Date` as an
|
||||
private Date date;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -1323,7 +1257,6 @@ for use with Spring's `DataBinder` and the Spring Expression Language (SpEL).
|
||||
|
||||
The following listing shows the `FormatterRegistry` SPI:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1340,7 +1273,6 @@ The following listing shows the `FormatterRegistry` SPI:
|
||||
void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
As shown in the preceding listing, you can register formatters by field type or by annotation.
|
||||
|
||||
@@ -1358,7 +1290,6 @@ these rules once, and they are applied whenever formatting is needed.
|
||||
`FormatterRegistrar` is an SPI for registering formatters and converters through the
|
||||
FormatterRegistry. The following listing shows its interface definition:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1369,7 +1300,6 @@ FormatterRegistry. The following listing shows its interface definition:
|
||||
void registerFormatters(FormatterRegistry registry);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
A `FormatterRegistrar` is useful when registering multiple related converters and
|
||||
formatters for a given formatting category, such as date formatting. It can also be
|
||||
@@ -1404,7 +1334,6 @@ you use the Joda-Time library.
|
||||
For example, the following Java configuration registers a global `yyyyMMdd`
|
||||
format (this example does not depend on the Joda-Time library):
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1429,13 +1358,11 @@ format (this example does not depend on the Joda-Time library):
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you prefer XML-based configuration, you can use a
|
||||
`FormattingConversionServiceFactoryBean`. The following example shows how to do so (this time using Joda
|
||||
Time):
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1467,7 +1394,6 @@ Time):
|
||||
</bean>
|
||||
</beans>
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: Joda-Time provides separate distinct types to represent `date`, `time`, and `date-time`
|
||||
values. The `dateFormatter`, `timeFormatter`, and `dateTimeFormatter` properties of the
|
||||
@@ -1504,7 +1430,6 @@ constraints. You can also define your own custom constraints.
|
||||
|
||||
Consider the following example, which shows a simple `PersonForm` model with two properties:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1513,12 +1438,10 @@ Consider the following example, which shows a simple `PersonForm` model with two
|
||||
private int age;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
JSR-303 lets you define declarative validation constraints against such properties, as the
|
||||
following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1532,7 +1455,6 @@ following example shows:
|
||||
private int age;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
When a JSR-303 Validator validates an instance of this class, these constraints
|
||||
are enforced.
|
||||
@@ -1556,14 +1478,12 @@ wherever validation is needed in your application.
|
||||
You can use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring bean,
|
||||
as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="validator"
|
||||
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
|
||||
----
|
||||
====
|
||||
|
||||
The basic configuration in the preceding example triggers bean validation to initialize by using its
|
||||
default bootstrap mechanism. A JSR-303 or JSR-349 provider, such as the Hibernate Validator,
|
||||
@@ -1581,7 +1501,6 @@ these interfaces into beans that need to invoke validation logic.
|
||||
You can inject a reference to `javax.validation.Validator` if you prefer to work with the Bean
|
||||
Validation API directly, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1593,12 +1512,10 @@ Validation API directly, as the following example shows:
|
||||
@Autowired
|
||||
private Validator validator;
|
||||
----
|
||||
====
|
||||
|
||||
You can inject a reference to `org.springframework.validation.Validator` if your bean requires
|
||||
the Spring Validation API, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1611,7 +1528,6 @@ the Spring Validation API, as the following example shows:
|
||||
private Validator validator;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[validation-beanvalidation-spring-constraints]]
|
||||
@@ -1636,7 +1552,6 @@ that uses Spring to create `ConstraintValidator` instances. This lets your custo
|
||||
The following example shows a custom `@Constraint` declaration followed by an associated
|
||||
`ConstraintValidator` implementation that uses Spring for dependency injection:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1660,7 +1575,6 @@ The following example shows a custom `@Constraint` declaration followed by an as
|
||||
...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
As the preceding example shows, a `ConstraintValidator` implementation can have its dependencies
|
||||
`@Autowired` as any other Spring bean.
|
||||
@@ -1673,13 +1587,11 @@ You can integrate the method validation feature supported by Bean Validation 1.1
|
||||
extension, also by Hibernate Validator 4.3) into a Spring context
|
||||
through a `MethodValidationPostProcessor` bean definition, as follows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
|
||||
----
|
||||
====
|
||||
|
||||
To be eligible for Spring-driven method validation, all target classes need to be annotated with
|
||||
Spring's `@Validated` annotation. (Optionally, you can also declare the validation groups to use.)
|
||||
@@ -1708,7 +1620,6 @@ configured, you can invoke the `Validator` by calling `binder.validate()`. Any v
|
||||
The following example shows how to use a `DataBinder` programmatically to invoke validation
|
||||
logic after binding to a target object:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -1725,7 +1636,6 @@ logic after binding to a target object:
|
||||
// get BindingResult that includes any validation errors
|
||||
BindingResult results = binder.getBindingResult();
|
||||
----
|
||||
====
|
||||
|
||||
You can also configure a `DataBinder` with multiple `Validator` instances through
|
||||
`dataBinder.addValidators` and `dataBinder.replaceValidators`. This is useful when
|
||||
|
||||
Reference in New Issue
Block a user