Remove admonitions surrounding code snippets

This commit is contained in:
Brian Clozel
2018-11-26 23:15:55 +01:00
parent 8c768e48fa
commit 33cbe2e77a
29 changed files with 139 additions and 3191 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.
}
----
====

View File

@@ -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");
----
====

View File

@@ -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