diff --git a/src/asciidoc/appendix.adoc b/src/asciidoc/appendix.adoc
index c57b66cc50..ec1ed61e82 100644
--- a/src/asciidoc/appendix.adoc
+++ b/src/asciidoc/appendix.adoc
@@ -40,33 +40,33 @@ property setter. The following snippets show a DAO definition in a Spring contai
referencing the above defined `SessionFactory`, and an example for a DAO method
implementation.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ProductDaoImpl implements ProductDao {
+ public class ProductDaoImpl implements ProductDao {
- private HibernateTemplate hibernateTemplate;
+ private HibernateTemplate hibernateTemplate;
- public void setSessionFactory(SessionFactory sessionFactory) {
- this.hibernateTemplate = new HibernateTemplate(sessionFactory);
- }
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ this.hibernateTemplate = new HibernateTemplate(sessionFactory);
+ }
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
- }
-}
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
+ }
+ }
----
The `HibernateTemplate` class provides many methods that mirror the methods exposed on
@@ -75,29 +75,29 @@ as the one shown above. If you need access to the `Session` to invoke methods th
not exposed on the `HibernateTemplate`, you can always drop down to a callback-based
approach like so.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ProductDaoImpl implements ProductDao {
+ public class ProductDaoImpl implements ProductDao {
- private HibernateTemplate hibernateTemplate;
+ private HibernateTemplate hibernateTemplate;
- public void setSessionFactory(SessionFactory sessionFactory) {
- this.hibernateTemplate = new HibernateTemplate(sessionFactory);
- }
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ this.hibernateTemplate = new HibernateTemplate(sessionFactory);
+ }
- public Collection loadProductsByCategory(final String category) throws DataAccessException {
- return this.hibernateTemplate.execute(new HibernateCallback() {
+ public Collection loadProductsByCategory(final String category) throws DataAccessException {
+ return this.hibernateTemplate.execute(new HibernateCallback() {
+ public Object doInHibernate(Session session) {
+ Criteria criteria = session.createCriteria(Product.class);
+ criteria.add(Expression.eq("category", category));
+ criteria.setMaxResults(6);
+ return criteria.list();
+ }
+ };
+ }
- public Object doInHibernate(Session session) {
- Criteria criteria = session.createCriteria(Product.class);
- criteria.add(Expression.eq("category", category));
- criteria.setMaxResults(6);
- return criteria.list();
- }
- };
- }
-}
+ }
----
A callback implementation effectively can be used for any Hibernate data access.
@@ -112,16 +112,17 @@ receiving a `SessionFactory`, and `getSessionFactory()` and `getHibernateTemplat
use by subclasses. In combination, this allows for very simple DAO implementations for
typical requirements:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
+ public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- return this.getHibernateTemplate().find(
- "from test.Product product where product.category=?", category);
- }
-}
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ return this.getHibernateTemplate().find(
+ "from test.Product product where product.category=?", category);
+ }
+
+ }
----
@@ -138,27 +139,27 @@ methods ' `allowCreate`' argument, to enforce running within a transaction (whic
the need to close the returned `Session`, as its lifecycle is managed by the
transaction).
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {
+ public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {
- public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
- Session session = getSession(false);
- try {
- Query query = session.createQuery("from test.Product product where product.category=?");
- query.setString(0, category);
- List result = query.list();
- if (result == null) {
- throw new MyException("No search results.");
- }
- return result;
- }
- catch (HibernateException ex) {
- throw convertHibernateAccessException(ex);
- }
- }
-}
+ public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
+ Session session = getSession(false);
+ try {
+ Query query = session.createQuery("from test.Product product where product.category=?");
+ query.setString(0, category);
+ List result = query.list();
+ if (result == null) {
+ throw new MyException("No search results.");
+ }
+ return result;
+ }
+ catch (HibernateException ex) {
+ throw convertHibernateAccessException(ex);
+ }
+ }
+ }
----
The advantage of such direct Hibernate access code is that it allows __any__ checked
@@ -177,48 +178,49 @@ For the currently recommended usage patterns for JDO see <>
[[orm-jdo-template]]
-===== JdoTemplate and `JdoDaoSupport`
+===== JdoTemplate and `JdoDaoSupport`
Each JDO-based DAO will then receive the `PersistenceManagerFactory` through dependency
injection. Such a DAO could be coded against plain JDO API, working with the given
`PersistenceManagerFactory`, but will usually rather be used with the Spring Framework's
`JdoTemplate`:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ProductDaoImpl implements ProductDao {
+ public class ProductDaoImpl implements ProductDao {
- private JdoTemplate jdoTemplate;
+ private JdoTemplate jdoTemplate;
- public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
- this.jdoTemplate = new JdoTemplate(pmf);
- }
+ public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
+ this.jdoTemplate = new JdoTemplate(pmf);
+ }
- public Collection loadProductsByCategory(final String category) throws DataAccessException {
- return (Collection) this.jdoTemplate.execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
- Query query = pm.newQuery(Product.class, "category = pCategory");
- query.declareParameters("String pCategory");
- List result = query.execute(category);
- // do some further stuff with the result list
- return result;
- }
- });
- }
-}
+ public Collection loadProductsByCategory(final String category) throws DataAccessException {
+ return (Collection) this.jdoTemplate.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) throws JDOException {
+ Query query = pm.newQuery(Product.class, "category = pCategory");
+ query.declareParameters("String pCategory");
+ List result = query.execute(category);
+ // do some further stuff with the result list
+ return result;
+ }
+ });
+ }
+
+ }
----
A callback implementation can effectively be used for any JDO data access. `JdoTemplate`
@@ -233,16 +235,17 @@ receiving a `PersistenceManagerFactory`, and `getPersistenceManagerFactory()` an
`getJdoTemplate()` for use by subclasses. In combination, this allows for very simple
DAO implementations for typical requirements:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
+ public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- return getJdoTemplate().find(
- Product.class, "category = pCategory", "String category", new Object[] {category});
- }
-}
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ return getJdoTemplate().find(Product.class,
+ "category = pCategory", "String category", new Object[] {category});
+ }
+
+ }
----
As alternative to working with Spring's `JdoTemplate`, you can also code Spring-based
@@ -260,47 +263,48 @@ For the currently recommended usage patterns for JPA see <>
[[orm-jpa-template]]
-===== JpaTemplate and `JpaDaoSupport`
+===== JpaTemplate and `JpaDaoSupport`
Each JPA-based DAO will then receive a `EntityManagerFactory` via dependency injection.
Such a DAO can be coded against plain JPA and work with the given `EntityManagerFactory`
or through Spring's `JpaTemplate`:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class JpaProductDao implements ProductDao {
+ public class JpaProductDao implements ProductDao {
- private JpaTemplate jpaTemplate;
+ private JpaTemplate jpaTemplate;
- public void setEntityManagerFactory(EntityManagerFactory emf) {
- this.jpaTemplate = new JpaTemplate(emf);
- }
+ public void setEntityManagerFactory(EntityManagerFactory emf) {
+ this.jpaTemplate = new JpaTemplate(emf);
+ }
- public Collection loadProductsByCategory(final String category) throws DataAccessException {
- return (Collection) this.jpaTemplate.execute(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
- Query query = em.createQuery("from Product as p where p.category = :category");
- query.setParameter("category", category);
- List result = query.getResultList();
- // do some further processing with the result list
- return result;
- }
- });
- }
-}
+ public Collection loadProductsByCategory(final String category) throws DataAccessException {
+ return (Collection) this.jpaTemplate.execute(new JpaCallback() {
+ public Object doInJpa(EntityManager em) throws PersistenceException {
+ Query query = em.createQuery("from Product as p where p.category = :category");
+ query.setParameter("category", category);
+ List result = query.getResultList();
+ // do some further processing with the result list
+ return result;
+ }
+ });
+ }
+
+ }
----
The `JpaCallback` implementation allows any type of JPA data access. The `JpaTemplate`
@@ -315,17 +319,18 @@ one line callback implementations.
Furthermore, Spring provides a convenient `JpaDaoSupport` base class that provides the
`get/setEntityManagerFactory` and `getJpaTemplate()` to be used by subclasses:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
+ public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- Map params = new HashMap();
- params.put("category", category);
- return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
- }
-}
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ Map params = new HashMap();
+ params.put("category", category);
+ return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
+ }
+
+ }
----
Besides working with Spring's `JpaTemplate`, one can also code Spring-based DAOs against
@@ -455,16 +460,16 @@ possible to target different advice using 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 is shown below:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface Pointcut {
+ public interface Pointcut {
- ClassFilter getClassFilter();
+ ClassFilter getClassFilter();
- MethodMatcher getMethodMatcher();
+ MethodMatcher getMethodMatcher();
-}
+ }
----
Splitting the `Pointcut` interface into two parts allows reuse of class and method
@@ -475,29 +480,31 @@ 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 will be
matched:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface ClassFilter {
+ public interface ClassFilter {
- boolean matches(Class clazz);
-}
+ boolean matches(Class clazz);
+
+ }
----
The `MethodMatcher` interface is normally more important. The complete interface is
shown below:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface MethodMatcher {
+ public interface MethodMatcher {
- boolean matches(Method m, Class targetClass);
+ boolean matches(Method m, Class targetClass);
- boolean isRuntime();
+ boolean isRuntime();
- boolean matches(Method m, Class targetClass, Object[] args);
-}
+ boolean matches(Method m, Class targetClass, Object[] args);
+
+ }
----
The `matches(Method, Class)` method is used to test whether this pointcut will ever
@@ -576,18 +583,18 @@ effectively the union of these pointcuts.)
The usage is shown below:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
- .*set.*
- .*absquatulate
-
-
-
+
+
+
+ .*set.*
+ .*absquatulate
+
+
+
----
Spring provides a convenience class, `RegexpMethodPointcutAdvisor`, that allows us to
@@ -596,21 +603,21 @@ throws advice etc.). Behind the scenes, Spring will use a `JdkRegexpMethodPointc
Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both
pointcut and advice, as shown below:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
- .*set.*
- .*absquatulate
-
-
-
+
+
+
+
+
+
+ .*set.*
+ .*absquatulate
+
+
+
----
__RegexpMethodPointcutAdvisor__ can be used with any Advice type.
@@ -655,15 +662,16 @@ Because static pointcuts are most useful, you'll probably subclass
StaticMethodMatcherPointcut, as shown below. This requires implementing just one
abstract method (although it's possible to override other methods to customize behavior):
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-class TestStaticPointcut extends StaticMethodMatcherPointcut {
+ class TestStaticPointcut extends StaticMethodMatcherPointcut {
- public boolean matches(Method m, Class targetClass) {
- // return true if custom criteria match
- }
-}
+ public boolean matches(Method m, Class targetClass) {
+ // return true if custom criteria match
+ }
+
+ }
----
There are also superclasses for dynamic pointcuts.
@@ -725,13 +733,14 @@ Spring is compliant with the AOP Alliance interface for around advice using meth
interception. MethodInterceptors implementing around advice should implement the
following interface:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface MethodInterceptor extends Interceptor {
+ public interface MethodInterceptor extends Interceptor {
- Object invoke(MethodInvocation invocation) throws Throwable;
-}
+ Object invoke(MethodInvocation invocation) throws Throwable;
+
+ }
----
The `MethodInvocation` argument to the `invoke()` method exposes the method being
@@ -741,18 +750,19 @@ point.
A simple `MethodInterceptor` implementation looks as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class DebugInterceptor implements MethodInterceptor {
+ public class DebugInterceptor implements MethodInterceptor {
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("Before: invocation=[" + invocation + "]");
- Object rval = invocation.proceed();
- System.out.println("Invocation returned");
- return rval;
- }
-}
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ System.out.println("Before: invocation=[" + invocation + "]");
+ Object rval = invocation.proceed();
+ System.out.println("Invocation returned");
+ return rval;
+ }
+
+ }
----
Note the call to the MethodInvocation's `proceed()` method. This proceeds down the
@@ -786,13 +796,14 @@ The `MethodBeforeAdvice` interface is shown below. (Spring's API design would al
field before advice, although the usual objects apply to field interception and it's
unlikely that Spring will ever implement it).
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface MethodBeforeAdvice extends BeforeAdvice {
+ public interface MethodBeforeAdvice extends BeforeAdvice {
- void before(Method m, Object[] args, Object target) throws Throwable;
-}
+ void before(Method m, Object[] args, Object target) throws Throwable;
+
+ }
----
Note the return type is `void`. Before advice can insert custom behavior before the join
@@ -804,21 +815,21 @@ wrapped in an unchecked exception by the AOP proxy.
An example of a before advice in Spring, which counts all method invocations:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class CountingBeforeAdvice implements MethodBeforeAdvice {
+ public class CountingBeforeAdvice implements MethodBeforeAdvice {
- private int count;
+ private int count;
- public void before(Method m, Object[] args, Object target) throws Throwable {
- ++count;
- }
+ public void before(Method m, Object[] args, Object target) throws Throwable {
+ ++count;
+ }
- public int getCount() {
- return count;
- }
-}
+ public int getCount() {
+ return count;
+ }
+ }
----
[TIP]
@@ -836,10 +847,10 @@ 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 form of:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-afterThrowing([Method, args, target], subclassOfThrowable)
+ afterThrowing([Method, args, target], subclassOfThrowable)
----
Only the last argument is required. The method signatures may have either one or four
@@ -848,49 +859,51 @@ arguments. The following classes are examples of throws advice.
The advice below is invoked if a `RemoteException` is thrown (including subclasses):
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class RemoteThrowsAdvice implements ThrowsAdvice {
+ public class RemoteThrowsAdvice implements ThrowsAdvice {
- public void afterThrowing(RemoteException ex) throws Throwable {
- // Do something with remote exception
- }
-}
+ public void afterThrowing(RemoteException ex) throws Throwable {
+ // Do something with remote exception
+ }
+
+ }
----
The following advice is invoked if a `ServletException` is thrown. Unlike the above
advice, it declares 4 arguments, so that it has access to the invoked method, method
arguments and target object:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ServletThrowsAdviceWithArguments implements ThrowsAdvice {
+ public class ServletThrowsAdviceWithArguments implements ThrowsAdvice {
- public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
- // Do something with all arguments
- }
-}
+ public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
+ // Do something with all arguments
+ }
+
+ }
----
The final example illustrates how these two methods could be used in a single class,
which handles both `RemoteException` and `ServletException`. Any number of throws advice
methods can be combined in a single class.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static class CombinedThrowsAdvice implements ThrowsAdvice {
+ public static class CombinedThrowsAdvice implements ThrowsAdvice {
- public void afterThrowing(RemoteException ex) throws Throwable {
- // Do something with remote exception
- }
+ public void afterThrowing(RemoteException ex) throws Throwable {
+ // Do something with remote exception
+ }
- public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
- // Do something with all arguments
- }
-}
+ public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
+ // Do something with all arguments
+ }
+ }
----
__Note:__ If a throws-advice method throws an exception itself, it will override the
@@ -913,14 +926,15 @@ Throws advice can be used with any pointcut.
An after returning advice in Spring must implement the
__org.springframework.aop.AfterReturningAdvice__ interface, shown below:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface AfterReturningAdvice extends Advice {
+ public interface AfterReturningAdvice extends Advice {
- void afterReturning(Object returnValue, Method m, Object[] args, Object target)
- throws Throwable;
-}
+ void afterReturning(Object returnValue, Method m, Object[] args,
+ Object target) throws Throwable;
+
+ }
----
An after returning advice has access to the return value (which it cannot modify),
@@ -929,22 +943,23 @@ invoked method, methods arguments and target.
The following after returning advice counts all successful method invocations that have
not thrown exceptions:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class CountingAfterReturningAdvice implements AfterReturningAdvice {
+ public class CountingAfterReturningAdvice implements AfterReturningAdvice {
- private int count;
+ private int count;
- public void afterReturning(Object returnValue, Method m, Object[] args, Object target)
- throws Throwable {
- ++count;
- }
+ public void afterReturning(Object returnValue, Method m, Object[] args,
+ Object target) throws Throwable {
+ ++count;
+ }
- public int getCount() {
- return count;
- }
-}
+ public int getCount() {
+ return count;
+ }
+
+ }
----
This advice doesn't change the execution path. If it throws an exception, this will be
@@ -964,13 +979,14 @@ Spring treats introduction advice as a special kind of interception advice.
Introduction requires an `IntroductionAdvisor`, and an `IntroductionInterceptor`,
implementing the following interface:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface IntroductionInterceptor extends MethodInterceptor {
+ public interface IntroductionInterceptor extends MethodInterceptor {
- boolean implementsInterface(Class intf);
-}
+ boolean implementsInterface(Class intf);
+
+ }
----
The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must
@@ -982,20 +998,22 @@ Introduction advice cannot be used with any pointcut, as it applies only at clas
rather than method, level. You can only use introduction advice with the
`IntroductionAdvisor`, which has the following methods:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
+ public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
- ClassFilter getClassFilter();
+ ClassFilter getClassFilter();
- void validateInterfaces() throws IllegalArgumentException;
-}
+ void validateInterfaces() throws IllegalArgumentException;
-public interface IntroductionInfo {
+ }
- Class[] getInterfaces();
-}
+ public interface IntroductionInfo {
+
+ Class[] getInterfaces();
+
+ }
----
There is no `MethodMatcher`, and hence no `Pointcut`, associated with introduction
@@ -1009,14 +1027,18 @@ introduced interfaces can be implemented by the configured `IntroductionIntercep
Let's look at a simple example from the Spring test suite. Let's suppose we want to
introduce the following interface to one or more objects:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface Lockable {
- void lock();
- void unlock();
- boolean locked();
-}
+ public interface Lockable {
+
+ void lock();
+
+ void unlock();
+
+ boolean locked();
+
+ }
----
This illustrates a __mixin__. We want to be able to cast advised objects to Lockable,
@@ -1052,33 +1074,33 @@ interfaces in this way.
Note the use of the `locked` instance variable. This effectively adds additional state
to that held in the target object.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class LockMixin extends DelegatingIntroductionInterceptor
- implements Lockable {
+ public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {
- private boolean locked;
+ private boolean locked;
- public void lock() {
- this.locked = true;
- }
+ public void lock() {
+ this.locked = true;
+ }
- public void unlock() {
- this.locked = false;
- }
+ public void unlock() {
+ this.locked = false;
+ }
- public boolean locked() {
- return this.locked;
- }
+ public boolean locked() {
+ return this.locked;
+ }
- public Object invoke(MethodInvocation invocation) throws Throwable {
- if (locked() && invocation.getMethod().getName().indexOf("set") == 0)
- throw new LockedException();
- return super.invoke(invocation);
- }
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ if (locked() && invocation.getMethod().getName().indexOf("set") == 0) {
+ throw new LockedException();
+ }
+ return super.invoke(invocation);
+ }
-}
+ }
----
Often it isn't necessary to override the `invoke()` method: the
@@ -1093,15 +1115,16 @@ The introduction advisor required is simple. All it needs to do is hold a distin
interceptor (which would be defined as a prototype): in this case, there's no
configuration relevant for a `LockMixin`, so we simply create it using `new`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
+ public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
- public LockMixinAdvisor() {
- super(new LockMixin(), Lockable.class);
- }
-}
+ public LockMixinAdvisor() {
+ super(new LockMixin(), Lockable.class);
+ }
+
+ }
----
We can apply this advisor very simply: it requires no configuration. (However, it __is__
@@ -1293,33 +1316,31 @@ Let's look at a simple example of `ProxyFactoryBean` in action. This example inv
* An AOP proxy bean definition specifying the target object (the personTarget bean) and
the interfaces to proxy, along with the advices to apply.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- Tony
- 51
-
+
+ Tony
+ 51
+
-
- Custom string property value
-
+
+ Custom string property value
+
-
-
+
+
-
- com.mycompany.Person
-
-
-
-
- myAdvisor
- debugInterceptor
-
-
-
+
+ com.mycompany.Person
+
+
+
+ myAdvisor
+ debugInterceptor
+
+
+
----
Note that the `interceptorNames` property takes a list of String: the bean names of the
@@ -1338,21 +1359,21 @@ an instance of the prototype from the factory; holding a reference isn't suffici
The "person" bean definition above can be used in place of a Person implementation, as
follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Person person = (Person) factory.getBean("person");
+ 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:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
The `PersonUser` class in this example would expose a property of type Person. As far as
@@ -1364,31 +1385,31 @@ It's possible to conceal the distinction between target and proxy using an anony
__inner bean__, as follows. Only the `ProxyFactoryBean` definition is different; the
advice is included only for completeness:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- Custom string property value
-
+
+ Custom string property value
+
-
+
-
- com.mycompany.Person
-
-
-
- Tony
- 51
-
-
-
-
- myAdvisor
- debugInterceptor
-
-
-
+
+ com.mycompany.Person
+
+
+
+ Tony
+ 51
+
+
+
+
+ myAdvisor
+ debugInterceptor
+
+
+
----
This has the advantage that there's only one object of type `Person`: useful if we want
@@ -1441,20 +1462,20 @@ By appending an asterisk to an interceptor name, all advisors with bean names ma
the part before the asterisk, will be added to the advisor chain. This can come in handy
if you need to add a standard set of 'global' advisors:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- global*
-
-
-
+
+
+
+
+ global*
+
+
+
-
-
+
+
----
@@ -1468,55 +1489,55 @@ definitions, can result in much cleaner and more concise proxy definitions.
First a parent, __template__, bean definition is created for the proxy:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- PROPAGATION_REQUIRED
-
-
-
+
+
+
+
+ PROPAGATION_REQUIRED
+
+
+
----
This will never be instantiated itself, so may actually be incomplete. Then each proxy
which needs to be created is just a child bean definition, which wraps the target of the
proxy as an inner bean definition, since the target will never be used on its own anyway.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
+
+
+
+
+
+
----
It is of course possible to override properties from the parent template, such as in
this case, the transaction propagation settings:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
- PROPAGATION_REQUIRED,readOnly
- PROPAGATION_REQUIRED,readOnly
- PROPAGATION_REQUIRED,readOnly
- PROPAGATION_REQUIRED
-
-
-
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED,readOnly
+ PROPAGATION_REQUIRED,readOnly
+ PROPAGATION_REQUIRED,readOnly
+ PROPAGATION_REQUIRED
+
+
+
----
Note that in the example above, we have explicitly marked the parent bean definition as
@@ -1541,13 +1562,13 @@ The following listing shows creation of a proxy for a target object, with one
interceptor and one advisor. The interfaces implemented by the target object will
automatically be proxied:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
-factory.addInterceptor(myMethodInterceptor);
-factory.addAdvisor(myAdvisor);
-MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
+ ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
+ factory.addInterceptor(myMethodInterceptor);
+ factory.addAdvisor(myAdvisor);
+ MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
----
The first step is to construct an object of type
@@ -1581,29 +1602,28 @@ However you create AOP proxies, you can manipulate them using the
interface, whichever other interfaces it implements. This interface includes the
following methods:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Advisor[] getAdvisors();
+ Advisor[] getAdvisors();
-void addAdvice(Advice advice) throws AopConfigException;
+ void addAdvice(Advice advice) throws AopConfigException;
-void addAdvice(int pos, Advice advice)
- throws AopConfigException;
+ void addAdvice(int pos, Advice advice) throws AopConfigException;
-void addAdvisor(Advisor advisor) throws AopConfigException;
+ void addAdvisor(Advisor advisor) throws AopConfigException;
-void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
+ void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
-int indexOf(Advisor advisor);
+ int indexOf(Advisor advisor);
-boolean removeAdvisor(Advisor advisor) throws AopConfigException;
+ boolean removeAdvisor(Advisor advisor) throws AopConfigException;
-void removeAdvisor(int index) throws AopConfigException;
+ void removeAdvisor(int index) throws AopConfigException;
-boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
+ boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
-boolean isFrozen();
+ boolean isFrozen();
----
The `getAdvisors()` method will return an Advisor for every advisor, interceptor or
@@ -1626,24 +1646,23 @@ change. (You can obtain a new proxy from the factory to avoid this problem.)
A simple example of casting an AOP proxy to the `Advised` interface and examining and
manipulating its advice:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Advised advised = (Advised) myObject;
-Advisor[] advisors = advised.getAdvisors();
-int oldAdvisorCount = advisors.length;
-System.out.println(oldAdvisorCount + " advisors");
+ Advised advised = (Advised) myObject;
+ Advisor[] advisors = advised.getAdvisors();
+ int oldAdvisorCount = advisors.length;
+ System.out.println(oldAdvisorCount + " advisors");
-// Add an advice like an interceptor without a pointcut
-// Will match all proxied methods
-// Can use for interceptors, before, after returning or throws advice
-advised.addAdvice(new DebugInterceptor());
+ // Add an advice like an interceptor without a pointcut
+ // Will match all proxied methods
+ // Can use for interceptors, before, after returning or throws advice
+ advised.addAdvice(new DebugInterceptor());
-// Add selective advice using a pointcut
-advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
+ // Add selective advice using a pointcut
+ advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
-assertEquals("Added two advisors",
- oldAdvisorCount + 2, advised.getAdvisors().length);
+ assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
----
[NOTE]
@@ -1700,17 +1719,17 @@ standard autoproxy creators.
The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates
AOP proxies for beans with names matching literal values or wildcards.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- jdk*,onlyJdk
-
-
- myInterceptor
-
-
-
+
+ jdk*,onlyJdk
+
+
+ myInterceptor
+
+
+
----
As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list
@@ -1759,22 +1778,22 @@ dependencies to obtain an un-advised object. Calling getBean("businessObject1")
ApplicationContext will return an AOP proxy, not the target business object. (The "inner
bean" idiom shown earlier also offers this benefit.)
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
----
The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice
@@ -1822,26 +1841,26 @@ objects is sufficient, because of the use of metadata-aware pointcuts. The bean
definitions include the following code, in `/WEB-INF/declarativeServices.xml`. Note that
this is generic, and can be used outside the JPetStore:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
----
The `DefaultAdvisorAutoProxyCreator` bean definition (the name is not significant, hence
@@ -1861,22 +1880,22 @@ example for auto-proxying driven by JDK 1.5+ annotations. The following configur
enables automatic detection of Spring's `Transactional` annotation, leading to implicit
proxies for beans containing that annotation:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
----
The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager`
@@ -1884,11 +1903,11 @@ definition, which is not included in this generic file (although it could be) be
will be specific to the application's transaction requirements (typically JTA, as in
this example, or Hibernate, JDO or JDBC):
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
[TIP]
@@ -1916,19 +1935,19 @@ suite, shown above, could be used in conjunction with an attribute-driven pointc
target a mixin, as shown here. We use the generic `DefaultPointcutAdvisor`, configured
using JavaBean properties:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
-
+
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
----
The above `swap()` call changes the target of the swappable bean. Clients who hold a
@@ -2029,23 +2047,22 @@ pooling API.
Sample configuration is shown below:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- ... properties omitted
-
+
+ ... properties omitted
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
----
Note that the target object - "businessObjectTarget" in the example - __must__ be a
@@ -2064,13 +2081,13 @@ It's possible to configure Spring so as to be able to cast any pooled object to
about the configuration and current size of the pool through an introduction. You'll
need to define an advisor like this:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
This advisor is obtained by calling a convenience method on the
@@ -2080,11 +2097,11 @@ the ProxyFactoryBean exposing the pooled object.
The cast will look as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
-System.out.println("Max pool size is " + conf.getMaxSize());
+ PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
+ System.out.println("Max pool size is " + conf.getMaxSize());
----
[NOTE]
@@ -2110,12 +2127,12 @@ use this approach without very good reason.
To do this, you could modify the `poolTargetSource` definition shown above as follows.
(I've also changed the name, for clarity.)
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
There's only one property: the name of the target bean. Inheritance is used in the
@@ -2125,7 +2142,7 @@ source, the target bean must be a prototype bean definition.
[[classic-aop-ts-threadlocal]]
-==== ThreadLocal target sources
+==== ThreadLocal target sources
`ThreadLocal` target sources are useful if you need an object to be created for each
incoming request (per thread that is). The concept of a `ThreadLocal` provide a JDK-wide
@@ -2133,12 +2150,12 @@ facility to transparently store resource alongside a thread. Setting up a
`ThreadLocalTargetSource` is pretty much the same as was explained for the other types
of target source:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
[NOTE]
@@ -2158,7 +2175,7 @@ ThreadLocals without other proper handling code.
[[classic-aop-extensibility]]
-=== Defining new Advice types
+=== Defining new Advice types
Spring AOP is designed to be extensible. While the interception implementation strategy
is presently used internally, it is possible to support arbitrary advice types in
@@ -2186,260 +2203,10 @@ Please refer to the Spring sample applications for further examples of Spring AO
declarative transaction management.
-
-
-
-[[migration-3.1]]
-== Migrating to Spring Framework 3.1
-In this appendix we discuss what users will want to know when upgrading to Spring
-Framework 3.1. For a general overview of features, please see<>
-
-
-
-
-[[migration-3.1-component-scan]]
-=== Component scanning against the "org" base package
-Spring Framework 3.1 introduces a number of `@Configuration` classes such as
-`org.springframework.cache.annotation.ProxyCachingConfiguration` and
-`org.springframework.scheduling.annotation.ProxyAsyncConfiguration`. Because
-`@Configuration` is ultimately meta-annotated with Spring's `@Component` annotation,
-these classes will inadvertently be scanned and processed by the container for any
-component-scanning directive against the unqualified "org" package, e.g.:
-
-[source,xml]
-[subs="verbatim,quotes"]
-----
-
-----
-
-Therefore, in order to avoid errors like the one reported in
-https://jira.springsource.org/browse/SPR-9843[SPR-9843], any such directives should be
-updated to at least one more level of qualification e.g.:
-
-[source,xml]
-[subs="verbatim,quotes"]
-----
-
-----
-
-Alternatively, an `exclude-filter` may be used. See <> documentation for details.
-
-
-
-
-
-[[migration-3.2]]
-== Migrating to Spring Framework 3.2
-In this appendix we discuss what users will want to know when upgrading to Spring
-Framework 3.2. For a general overview of features, please see<>
-
-
-
-
-[[migration-3.2-new-optional-deps]]
-=== Newly optional dependencies
-Certain inter-module dependencies are now `optional` at the Maven POM level where they
-were once required. For example, `spring-tx` and its dependence on `spring-context`.
-This may result in `ClassNotFoundErrors` or other similar problems for users that have
-been relying on transitive dependency management to pull in affected downstream
-`spring-*`. To resolve this problem, simply add the appropriate missing jars to your
-build configuration.
-
-
-
-
-[[migration-3.2-ehcache-support]]
-=== EHCache support moved to spring-context-support
-Along with Spring's new JCache support, the EHCache support classes in the
-`org.springframework.cache.ehcache` package moved from the `spring-context` module to
-`spring-context-support`.
-
-
-
-
-[[migration-3.2-inline-asm]]
-=== Inlining of spring-asm jar
-In versions 3.0 and 3.1, we published a discrete `spring-asm` containing repackaged
-`org.objectweb.asm` 3.x sources. As of Spring Framework 3.2, we have upgraded to
-`org.objectweb.asm` 4.0 and done away with the separate module jar, favoring inlining
-these classes directly within `spring-core`. This should cause no migration issue for
-most users; but on the off chance that you have `spring-asm` declared directly within
-your project's build script, you'll want to remove it when upgrading to Spring Framework
-3.2.
-
-
-
-
-[[migration-3.2-inline-cglib]]
-=== Explicit CGLIB dependency no longer required
-In prior versions, users of Spring's subclass-based AOP proxies (e.g. via
-`proxy-target-class="true"`) and `@Configuration` class support were required to declare
-an explicit dependency on CGLIB 2.2. As of Spring Framework 3.2, we now repackage and
-inline the newly-released CGLIB 3.0.
-
-This means greater convenience for users, as well as correct functionality for Java 7
-users who are creating subclass proxies of types that contain `invokedynamic` bytecode
-instructions. Repackaging CGLIB internally ensures no classpath conflicts with other
-third party frameworks that may depend on other versions of CGLIB.
-
-
-
-
-[[migration-3.2-osgi-users]]
-=== For OSGi users
-OSGi metadata is no longer published within individual Spring Framework jar MANIFEST.MF
-files. For more information about how users can get OSGi-ready versions of Spring
-Framework 3.2 jars.
-
-
-
-
-[[migration-3.2-compatibility-mvc-config]]
-=== MVC Java Config and MVC Namespace
-As explained in <>, both the MVC Java config and the MVC
-namespace register extensions such as `.json` and `.xml` if the corresponding classpath
-dependencies are present. That means controller methods may now return JSON or XML
-formatted content if those extensions are present in the request URI, even if the
-'Accept' header doesn't request those media types.
-
-The newly added support for matrix variables is explained in
-<>. To preserve backward compatibility, by default, semicolon
-content is removed from incoming request URIs and therefore `@MatrixVariable` cannot be
-used without additional configuration. However, when using the MVC Java config and the
-MVC namespace, semicolon content is left in the URI so that matrix variables are
-automatically supported. The removal of semicolon content is controlled through the
-`UrlPathHelper` property of `RequestMappingHandlerMapping`.
-
-
-
-
-[[migration-3.2-compatibility-uri-variable-values]]
-=== Decoding of URI Variable Values
-URI variable values now get decoded when `UrlPathHelper.setUrlDecode` is set to `false`.
-See https://jira.springsource.org/browse/SPR-9098[SPR-9098].
-
-
-
-
-[[migration-3.2-compatibility-http-patch]]
-=== HTTP PATCH method
-The `DispatcherServlet` now allows the HTTP PATCH method where previously it didn't.
-
-
-
-
-[[migration-3.2-compatibility-tiles3]]
-=== Tiles 3
-Besides the version number change, the set of Tiles dependencies has also changed. You
-will need to have a subset or all of `tiles-request-api`, `tiles-api`, `tiles-core`,
-`tiles-servlet`, `tiles-jsp`, `tiles-el`.
-
-
-
-
-[[migration-3.2-compatibility-spring-mvc-test]]
-=== Spring MVC Test standalone project
-If migrating from the https://github.com/SpringSource/spring-test-mvc[spring-test-mvc]
-standalone project to the `spring-test` module in Spring Framework 3.2, you will need to
-adjust the root package to be `org.springframework.test.web.servlet`.
-
-You will no longer be able to use the `MockMvcBuilders` `annotationConfigSetup` and
-`xmlConfigSetup` options. Instead you'll need to switch to using the
-`@WebAppConfiguration` support of `spring-test` for loading Spring configuration, then
-inject a `WebApplicationContext` into the test and use it to create a `MockMvc`. See
-<> for details.
-
-
-
-
-[[migration-3.2-compatibility-spring-test]]
-=== Spring Test Dependencies
-The `spring-test` module has been upgraded to depend on JUnit 4.11 ( `junit:junit`),
-TestNG 6.5.2 ( `org.testng:testng`), and Hamcrest Core 1.3 (
-`org.hamcrest:hamcrest-core`). Each of these dependencies is declared as an __optional__
-dependency in the Maven POM. Furthermore, it is important to note that the JUnit team
-has stopped inlining Hamcrest Core within the `junit:junit` Maven artifact as of JUnit
-4.11. Hamcrest Core is now a __required__ transitive dependency of `junit`, and users
-may therefore need to remove any exclusions on `hamcrest-core` that they had previously
-configured for their build.
-
-
-
-
-[[migration-3.2-changes]]
-=== Public API changes
-
-
-
-[[migration-3.2-api-changes]]
-==== JDiff reports
-Select JDiff reports are now being published to provide users with a convenient means of
-understanding what's changed between versions. Going forward these will be published
-between each minor version, e.g. from 3.1.3.RELEASE to 3.1.4.RELEASE; from the latest
-maintenance version to the latest GA release, e.g.
-http://docs.spring.io/spring-framework/docs/3.1.3.RELEASE_to_3.2.0.RELEASE[3.1.3.RELEASE
-to 3.2.0.RELEASE]; and in between each milestone and/or RC for users who are tracking
-next-generation development, e.g.
-http://docs.spring.io/spring-framework/docs/3.2.0.RC2_to_3.2.0.RELEASE[3.2.0.RC2 to
-3.2.0.RELEASE].
-
-
-
-[[migration-3.2-removals-and-deprecations]]
-==== Deprecations
-The following packages and types have been wholly or partially deprecated in Spring
-Framework 3.2 and may be removed in a future version. Click through to the linked
-Javadoc for each item for exact details. See also the
-http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/deprecated-list.html[complete
-list of deprecations] in the framework.
-
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/orm/ibatis/package-summary.html[org.springframework.orm.ibatis]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/scheduling/backportconcurrent/package-summary.html[org.springframework.scheduling.backportconcurrent]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/ejb/support/package-summary.html[org.springframework.ejb.support]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/http/converter/xml/XmlAwareFormHttpMessageConverter.html[org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/jsf/DelegatingVariableResolver.html[org.springframework.web.jsf.DelegatingVariableResolver]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/jsf/SpringBeanVariableResolver.html[org.springframework.web.jsf.SpringBeanVariableResolver]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/ui/velocity/CommonsLoggingLogSystem.html[org.springframework.ui.velocity.CommonsLoggingLogSystem]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/ui/velocity/VelocityEngineUtils.html[org.springframework.ui.velocity.VelocityEngineUtils]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanReferenceFactoryBean.html[org.springframework.beans.factory.config.BeanReferenceFactoryBean]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/beans/factory/config/CommonsLogFactoryBean.html[org.springframework.beans.factory.config.CommonsLogFactoryBean]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/instrument/classloading/oc4j/OC4JLoadTimeWeaver.html[org.springframework.beans.instrument.classloading.oc4j.OC4JLoadTimeWeaver]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/transaction/jta/OC4JJtaTransactionManager.html[org.springframework.transaction.jta.OC4JJtaTransactionManager]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/util/ExpressionEvaluationUtils.html[org.springframework.web.util.ExpressionEvaluationUtils]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.html[org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.html[org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.html[org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/ServletAnnotationMappingUtils.html[org.springframework.web.servlet.mvc.annotation.ServletAnnotationMappingUtils]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/jmx/support/MBeanRegistrationSupport.html[org.springframework.jmx.support.MBeanRegistrationSupport]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/context/ContextConfigurationAttributes.html[org.springframework.test.context.ContextConfigurationAttributes]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.html[org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests]:
- use of the `simpleJdbcTemplate` instance variable has been deprecated in favor of the
- new `jdbcTemplate` instance variable.
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.html[org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests]:
- use of the `simpleJdbcTemplate` instance variable has been deprecated in favor of the
- new `jdbcTemplate` instance variable.
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/jdbc/SimpleJdbcTestUtils.html[org.springframework.test.jdbc.SimpleJdbcTestUtils]
- has been deprecated in favor of `JdbcTestUtils` which now contains all of the
- functionality previously available in `SimpleJdbcTestUtils`.
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html[org.springframework.web.servlet.view.ContentNegotiatingViewResolver]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/transaction/interceptor/TransactionAspectUtils.html[org.springframework.transaction.interceptor.TransactionAspectUtils]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/http/HttpStatus.html[org.springframework.http.HttpStatus]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/util/UriUtils.html[org.springframework.web.util.UriUtils]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/orm/jpa/vendor/TopLinkJpaDialect.html[org.springframework.orm.jpa.vendor.TopLinkJpaDialect]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/orm/jpa/vendor/TopLinkJpaVendorAdapter.html[org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter]
-* http://docs.spring.io/spring/docs/3.2.0.RELEASE/javadoc-api/org/springframework/util/CachingMapDecorator.html[org.springframework.orm.util.CachingMapDecorator]
-
-
-
-
-
[[xsd-config]]
== XML Schema-based configuration
-
-
[[xsd-config-introduction]]
=== Introduction
This appendix details the XML Schema-based configuration introduced in Spring 2.0 and
@@ -2499,34 +2266,34 @@ involved in doing so is covered in the appendix entitled <>.
To switch over from the DTD-style to the new XML Schema-style, you need to make the
following change.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
+
-
+
----
The equivalent file in the XML Schema-style would be...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
+
----
[NOTE]
@@ -2560,34 +2327,34 @@ 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 below references the
correct schema so that the tags in the `util` namespace are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
[[xsd-config-body-schemas-util-constant]]
-=====
+=====
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
----
The above configuration uses a Spring `FactoryBean` implementation, the
@@ -2599,14 +2366,14 @@ plumbing to the end user.
The following XML Schema-based version is more concise and clearly expresses the
developer's intent (__'inject this constant value'__), and it just reads better.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
----
[[xsd-config-body-schemas-util-frfb]]
@@ -2620,23 +2387,23 @@ Find below an example which shows how a `static` field is exposed, by using the
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`]
property:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
There is also a convenience usage form where the `static` field is specified as the bean
name:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
This does mean that there is no longer any choice in what the bean id is (so any other
@@ -2644,15 +2411,15 @@ bean that refers to it will also have to use this longer name), but this form is
concise to define, and very convenient to use as an inner bean since the id doesn't have
to be specified for the bean reference:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
----
It is also possible to access a non-static (instance) field of another bean, as
@@ -2666,44 +2433,45 @@ anything about the Spring internals (or even about classes such as the
`FieldRetrievingFactoryBean`). Let's look at an example to see how easy injecting an
enum value is; consider this JDK 5 enum:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package javax.persistence;
+ package javax.persistence;
-public enum PersistenceContextType {
+ public enum PersistenceContextType {
- TRANSACTION,
- EXTENDED
+ TRANSACTION,
+ EXTENDED
-}
+ }
----
Now consider a setter of type `PersistenceContextType`:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package example;
+ package example;
-public class Client {
+ public class Client {
- private PersistenceContextType persistenceContextType;
+ private PersistenceContextType persistenceContextType;
- public void setPersistenceContextType(PersistenceContextType type) {
- this.persistenceContextType = type;
- }
-}
+ public void setPersistenceContextType(PersistenceContextType type) {
+ this.persistenceContextType = type;
+ }
+
+ }
----
.. and the corresponding bean definition:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
This works for classic type-safe emulated enums (on JDK 1.4 and JDK 1.3) as well; Spring
@@ -2712,25 +2480,25 @@ class.
[[xsd-config-body-schemas-util-property-path]]
-=====
+=====
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
----
The above configuration uses a Spring `FactoryBean` implementation, the
@@ -2739,28 +2507,28 @@ has a value equal to the `'age'` property of the `'testBean'` bean.
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
----
The value of the `'path'` attribute of the `` tag follows the form
`'beanName.beanProperty'`.
[[xsd-config-body-schemas-util-property-path-dependency]]
-====== Using to set a bean property or constructor-argument
+====== Using to set a bean property or constructor-argument
`PropertyPathFactoryBean` is a `FactoryBean` that evaluates a property path on a given
target object. The target object can be specified directly or via a bean name. This
@@ -2769,67 +2537,67 @@ argument.
Here's an example where a path is used against another bean, by name:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-// target bean to be referenced by name
-
-
-
-
-
-
-
-
+ // target bean to be referenced by name
+
+
+
+
+
+
+
+
-// will result in 11, which is the value of property 'spouse.age' of bean 'person'
-
-
-
-
+ // will result in 11, which is the value of property 'spouse.age' of bean 'person'
+
+
+
+
----
In this example, a path is evaluated against an inner bean:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
----
There is also a shortcut form, where the bean name is the property path.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
----
This form does mean that there is no choice in the name of the bean. Any reference to it
will also have to use the same id, which is the path. Of course, if used as an inner
bean, there is no need to refer to it at all:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
----
The result type may be specifically set in the actual definition. This is not necessary
@@ -2838,17 +2606,17 @@ this feature.
[[xsd-config-body-schemas-util-properties]]
-=====
+=====
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
The above configuration uses a Spring `FactoryBean` implementation, the
@@ -2857,33 +2625,33 @@ loaded from the supplied <> location).
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
----
[[xsd-config-body-schemas-util-list]]
-=====
+=====
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- pechorin@hero.org
- raskolnikov@slums.org
- stavrogin@gov.org
- porfiry@gov.org
-
-
-
+
+
+
+
+ pechorin@hero.org
+ raskolnikov@slums.org
+ stavrogin@gov.org
+ porfiry@gov.org
+
+
+
----
The above configuration uses a Spring `FactoryBean` implementation, the
@@ -2892,16 +2660,16 @@ from the supplied `'sourceList'`.
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- pechorin@hero.org
- raskolnikov@slums.org
- stavrogin@gov.org
- porfiry@gov.org
-
+
+
+ pechorin@hero.org
+ raskolnikov@slums.org
+ stavrogin@gov.org
+ porfiry@gov.org
+
----
You can also explicitly control the exact type of `List` that will be instantiated and
@@ -2909,15 +2677,15 @@ populated via the use of the `'list-class'` attribute on the `` elem
example, if we really need a `java.util.LinkedList` to be instantiated, we could use the
following configuration:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- jackshaftoe@vagabond.org
- eliza@thinkingmanscrumpet.org
- vanhoek@pirate.org
- d'Arcachon@nemesis.org
-
+
+ jackshaftoe@vagabond.org
+ eliza@thinkingmanscrumpet.org
+ vanhoek@pirate.org
+ d'Arcachon@nemesis.org
+
----
If no `'list-class'` attribute is supplied, a `List` implementation will be chosen by
@@ -2925,24 +2693,24 @@ the container.
[[xsd-config-body-schemas-util-map]]
-=====
+=====
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
+
+
+
+
+
+
----
The above configuration uses a Spring `FactoryBean` implementation, the
@@ -2951,16 +2719,16 @@ taken from the supplied `'sourceMap'`.
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
You can also explicitly control the exact type of `Map` that will be instantiated and
@@ -2968,15 +2736,15 @@ populated via the use of the `'map-class'` attribute on the `` elemen
example, if we really need a `java.util.TreeMap` to be instantiated, we could use the
following configuration:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
+
+
+
+
+
+
----
If no `'map-class'` attribute is supplied, a `Map` implementation will be chosen by the
@@ -2984,24 +2752,24 @@ container.
[[xsd-config-body-schemas-util-set]]
-=====
+=====
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- pechorin@hero.org
- raskolnikov@slums.org
- stavrogin@gov.org
- porfiry@gov.org
-
-
-
+
+
+
+
+ pechorin@hero.org
+ raskolnikov@slums.org
+ stavrogin@gov.org
+ porfiry@gov.org
+
+
+
----
The above configuration uses a Spring `FactoryBean` implementation, the
@@ -3010,16 +2778,16 @@ from the supplied `'sourceSet'`.
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- pechorin@hero.org
- raskolnikov@slums.org
- stavrogin@gov.org
- porfiry@gov.org
-
+
+
+ pechorin@hero.org
+ raskolnikov@slums.org
+ stavrogin@gov.org
+ porfiry@gov.org
+
----
You can also explicitly control the exact type of `Set` that will be instantiated and
@@ -3027,15 +2795,15 @@ populated via the use of the `'set-class'` attribute on the `` elemen
example, if we really need a `java.util.TreeSet` to be instantiated, we could use the
following configuration:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- pechorin@hero.org
- raskolnikov@slums.org
- stavrogin@gov.org
- porfiry@gov.org
-
+
+ pechorin@hero.org
+ raskolnikov@slums.org
+ stavrogin@gov.org
+ porfiry@gov.org
+
----
If no `'set-class'` attribute is supplied, a `Set` implementation will be chosen by the
@@ -3053,240 +2821,240 @@ To use the tags in the `jee` schema, you need to have the following preamble at
of your Spring XML configuration file; the text in the following snippet references the
correct schema so that the tags in the `jee` namespace are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
[[xsd-config-body-schemas-jee-jndi-lookup]]
-===== (simple)
+===== (simple)
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
-
+
+
+
+
----
[[xsd-config-body-schemas-jee-jndi-lookup-environment-single]]
-===== (with single JNDI environment setting)
+===== (with single JNDI environment setting)
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- bar
-
-
-
+
+
+
+
+ bar
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- foo=bar
-
+
+ foo=bar
+
----
[[xsd-config-body-schemas-jee-jndi-lookup-evironment-multiple]]
-===== (with multiple JNDI environment settings)
+===== (with multiple JNDI environment settings)
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- bar
- pong
-
-
-
+
+
+
+
+ bar
+ pong
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
- foo=bar
- ping=pong
-
-
+
+
+
+ foo=bar
+ ping=pong
+
+
----
[[xsd-config-body-schemas-jee-jndi-lookup-complex]]
-===== (complex)
+===== (complex)
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
[[xsd-config-body-schemas-jee-local-slsb]]
-===== (simple)
+===== (simple)
The `` tag configures a reference to an EJB Stateless SessionBean.
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
[[xsd-config-body-schemas-jee-local-slsb-complex]]
-===== (complex)
+===== (complex)
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
[[xsd-config-body-schemas-jee-remote-slsb]]
-=====
+=====
The `` tag configures a reference to a `remote` EJB Stateless
SessionBean.
Before...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
----
After...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
@@ -3306,17 +3074,17 @@ the following preamble at the top of your Spring XML configuration file; the tex
following snippet references the correct schema so that the tags in the `lang` namespace
are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
@@ -3334,17 +3102,17 @@ the following preamble at the top of your Spring XML configuration file; the tex
following snippet references the correct schema so that the tags in the `jms` namespace
are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
@@ -3371,19 +3139,19 @@ the following preamble at the top of your Spring XML configuration file; the tex
following snippet references the correct schema so that the tags in the `tx` namespace
are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
[NOTE]
@@ -3408,17 +3176,17 @@ the following preamble at the top of your Spring XML configuration file; the tex
following snippet references the correct schema so that the tags in the `aop` namespace
are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
@@ -3432,17 +3200,17 @@ a lot of grunt work in Spring, such as `BeanfactoryPostProcessors`. The followin
snippet references the correct schema so that the tags in the `context` namespace are
available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
[NOTE]
@@ -3452,7 +3220,7 @@ The `context` schema was only introduced in Spring 2.5.
[[xsd-config-body-schemas-context-pphc]]
-=====
+=====
This element activates the replacement of `${...}` placeholders, resolved against the
specified properties file (as a <>). This element is
@@ -3462,7 +3230,7 @@ a convenience mechanism that sets up a<
+=====
Activates the Spring infrastructure for various annotations to be detected in bean
classes: Spring's <> and
@@ -3480,25 +3248,25 @@ This element does __not__ activate processing of Spring's
[[xsd-config-body-schemas-context-component-scan]]
-=====
+=====
This element is detailed in <>.
[[xsd-config-body-schemas-context-ltw]]
-=====
+=====
This element is detailed in <>.
[[xsd-config-body-schemas-context-sc]]
-=====
+=====
This element is detailed in <>.
[[xsd-config-body-schemas-context-mbe]]
-=====
+=====
This element is detailed in <>.
@@ -3532,17 +3300,17 @@ To use the tags in the `jdbc` schema, you need to have the following preamble at
of your Spring XML configuration file; the text in the following snippet references the
correct schema so that the tags in the `jdbc` namespace are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
@@ -3558,17 +3326,17 @@ To use the tags in the `cache` schema, you need to have the following preamble a
top of your Spring XML configuration file; the text in the following snippet references
the correct schema so that the tags in the `cache` namespace are available to you.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
----
@@ -3592,17 +3360,21 @@ Find below an example of the `` tag in the context of a surrounding `
-
+
+
-
- ____
+
+ ____
+
+
+
+
----
In the case of the above example, you would assume that there is some logic that will
@@ -3647,12 +3419,12 @@ XML extension (a custom XML element) that allows us to configure objects of the
`SimpleDateFormat` (from the `java.text` package) in an easy manner. When we are done,
we will be able to define bean definitions of type `SimpleDateFormat` like this:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
__(Don't worry about the fact that this example is very simple; much more detailed
@@ -3668,32 +3440,32 @@ Creating an XML configuration extension for use with Spring's IoC container star
authoring an XML Schema to describe the extension. What follows is the schema we'll use
to configure `SimpleDateFormat` objects.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
----
(The emphasized line contains an extension base for all tags that will be identifiable
@@ -3704,12 +3476,12 @@ container). We are able to use this attribute because we imported the Spring-pro
The above schema will be used to configure `SimpleDateFormat` objects, directly in an
XML application context file using the `` element.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
Note that after we've created the infrastructure classes, the above snippet of XML will
@@ -3717,13 +3489,13 @@ essentially be exactly the same as the following XML snippet. In other words, we
creating a bean in the container, identified by the name `'dateFormat'` of type
`SimpleDateFormat`, with a couple of properties set.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
[NOTE]
@@ -3738,7 +3510,7 @@ defined in the enumeration.
[[extensible-xml-namespacehandler]]
-=== Coding a NamespaceHandler
+=== Coding a NamespaceHandler
In addition to the schema, we need a `NamespaceHandler` that will parse all elements of
this specific namespace Spring encounters while parsing configuration files. The
@@ -3767,19 +3539,20 @@ element results in a single `SimpleDateFormat` bean definition). Spring features
number of convenience classes that support this scenario. In this example, we'll make
use the `NamespaceHandlerSupport` class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.samples.xml;
+ package org.springframework.samples.xml;
-import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
-public class MyNamespaceHandler extends NamespaceHandlerSupport {
+ public class MyNamespaceHandler extends NamespaceHandlerSupport {
- public void init() {
- **registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());**
- }
-}
+ public void init() {
+ **registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());**
+ }
+
+ }
----
The observant reader will notice that there isn't actually a whole lot of parsing logic
@@ -3805,30 +3578,36 @@ responsible for parsing __one__ distinct top-level XML element defined in the sc
the parser, we'll have access to the XML element (and thus its subelements too) so that
we can parse our custom XML content, as can be seen in the following example:
-[source,java]
+[source,java,indent=0]
----
-package org.springframework.samples.xml;
+ package org.springframework.samples.xml;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
+ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+ import org.springframework.util.StringUtils;
+ import org.w3c.dom.Element;
-import java.text.SimpleDateFormat;
+ import java.text.SimpleDateFormat;
-public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { // <1>
-protected Class getBeanClass(Element element) { return SimpleDateFormat.class; // <2>
-} protected void doParse(Element element, BeanDefinitionBuilder bean) { // this will never be null since the schema explicitly requires that a value be supplied
- String pattern = element.getAttribute("pattern");
- bean.addConstructorArg(pattern);
+ public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { // <1>
- // this however is an optional property
- String lenient = element.getAttribute("lenient");
- if (StringUtils.hasText(lenient)) {
- bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
- }
- }
-}
+ protected Class getBeanClass(Element element) {
+ return SimpleDateFormat.class; // <2>
+ }
+
+ protected void doParse(Element element, BeanDefinitionBuilder bean) {
+ // this will never be null since the schema explicitly requires that a value be supplied
+ String pattern = element.getAttribute("pattern");
+ bean.addConstructorArg(pattern);
+
+ // this however is an optional property
+ String lenient = element.getAttribute("lenient");
+ if (StringUtils.hasText(lenient)) {
+ bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
+ }
+ }
+
+ }
----
<1> We use the Spring-provided `AbstractSingleBeanDefinitionParser` to handle a lot of
@@ -3857,12 +3636,12 @@ these special properties files, the formats of which are detailed below.
[[extensible-xml-registration-spring-handlers]]
-==== 'META-INF/spring.handlers'
+==== 'META-INF/spring.handlers'
The properties file called `'spring.handlers'` contains a mapping of XML Schema URIs to
namespace handler classes. So for our example, we need to write the following:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler
@@ -3878,7 +3657,7 @@ attribute as specified in your custom XSD schema.
[[extensible-xml-registration-spring-schemas]]
-==== 'META-INF/spring.schemas'
+==== 'META-INF/spring.schemas'
The properties file called `'spring.schemas'` contains a mapping of XML Schema locations
(referred to along with the schema declaration in XML files that use the schema as part
@@ -3888,7 +3667,7 @@ Internet access to retrieve the schema file. If you specify the mapping in this
properties file, Spring will search for the schema on the classpath (in this case
`'myns.xsd'` in the `'org.springframework.samples.xml'` package):
-[source]
+[literal]
[subs="verbatim,quotes"]
----
http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
@@ -3907,28 +3686,28 @@ one of the 'custom' extensions that Spring provides straight out of the box. Fin
an example of using the custom `` element developed in the previous steps
in a Spring XML configuration file.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
----
@@ -3945,26 +3724,26 @@ Find below some much meatier examples of custom XML extensions.
This example illustrates how you might go about writing the various artifacts required
to satisfy a target of the following configuration:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
----
The above configuration actually nests custom extensions within each other. The class
@@ -3973,80 +3752,82 @@ class (shown directly below). Notice how the `Component` class does __not__ expo
setter method for the `'components'` property; this makes it hard (or rather impossible)
to configure a bean definition for the `Component` class using setter injection.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-import java.util.ArrayList;
-import java.util.List;
+ import java.util.ArrayList;
+ import java.util.List;
-public class Component {
+ public class Component {
- private String name;
- private List components = new ArrayList ();
+ private String name;
+ private List components = new ArrayList ();
- // mmm, there is no setter method for the 'components'
- public void addComponent(Component component) {
- this.components.add(component);
- }
+ // mmm, there is no setter method for the 'components'
+ public void addComponent(Component component) {
+ this.components.add(component);
+ }
- public List getComponents() {
- return components;
- }
+ public List getComponents() {
+ return components;
+ }
- public String getName() {
- return name;
- }
+ public String getName() {
+ return name;
+ }
- public void setName(String name) {
- this.name = name;
- }
-}
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ }
----
The typical solution to this issue is to create a custom `FactoryBean` that exposes a
setter property for the `'components'` property.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-import org.springframework.beans.factory.FactoryBean;
+ import org.springframework.beans.factory.FactoryBean;
-import java.util.List;
+ import java.util.List;
-public class ComponentFactoryBean implements FactoryBean {
+ public class ComponentFactoryBean implements FactoryBean {
- private Component parent;
- private List children;
+ private Component parent;
+ private List children;
- public void setParent(Component parent) {
- this.parent = parent;
- }
+ public void setParent(Component parent) {
+ this.parent = parent;
+ }
- public void setChildren(List children) {
- this.children = children;
- }
+ public void setChildren(List children) {
+ this.children = children;
+ }
- public Component getObject() throws Exception {
- if (this.children != null && this.children.size() > 0) {
- for (Component child : children) {
- this.parent.addComponent(child);
- }
- }
- return this.parent;
- }
+ public Component getObject() throws Exception {
+ if (this.children != null && this.children.size() > 0) {
+ for (Component child : children) {
+ this.parent.addComponent(child);
+ }
+ }
+ return this.parent;
+ }
- public Class getObjectType() {
- return Component.class;
- }
+ public Class getObjectType() {
+ return Component.class;
+ }
- public boolean isSingleton() {
- return true;
- }
-}
+ public boolean isSingleton() {
+ return true;
+ }
+
+ }
----
This is all very well, and does work nicely, but exposes a lot of Spring plumbing to the
@@ -4055,112 +3836,112 @@ this Spring plumbing. If we stick to <>, we'll start off by creating the XSD schema to define the structure of our
custom tag.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
----
We'll then create a custom `NamespaceHandler`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
-public class ComponentNamespaceHandler extends NamespaceHandlerSupport {
+ public class ComponentNamespaceHandler extends NamespaceHandlerSupport {
- public void init() {
- registerBeanDefinitionParser("component", new ComponentBeanDefinitionParser());
- }
-}
+ public void init() {
+ registerBeanDefinitionParser("component", new ComponentBeanDefinitionParser());
+ }
+
+ }
----
Next up is the custom `BeanDefinitionParser`. Remember that what we are creating is a
`BeanDefinition` describing a `ComponentFactoryBean`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.ManagedList;
-import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
+ import org.springframework.beans.factory.config.BeanDefinition;
+ import org.springframework.beans.factory.support.AbstractBeanDefinition;
+ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+ import org.springframework.beans.factory.support.ManagedList;
+ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
+ import org.springframework.beans.factory.xml.ParserContext;
+ import org.springframework.util.xml.DomUtils;
+ import org.w3c.dom.Element;
-import java.util.List;
+ import java.util.List;
-public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser {
+ public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser {
- protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
- return parseComponentElement(element);
- }
+ protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
+ return parseComponentElement(element);
+ }
- private static AbstractBeanDefinition parseComponentElement(Element element) {
- BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class);
- factory.addPropertyValue("parent", parseComponent(element));
+ private static AbstractBeanDefinition parseComponentElement(Element element) {
+ BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class);
+ factory.addPropertyValue("parent", parseComponent(element));
- List childElements = DomUtils.getChildElementsByTagName(element, "component");
- if (childElements != null && childElements.size() > 0) {
- parseChildComponents(childElements, factory);
- }
+ List childElements = DomUtils.getChildElementsByTagName(element, "component");
+ if (childElements != null && childElements.size() > 0) {
+ parseChildComponents(childElements, factory);
+ }
- return factory.getBeanDefinition();
- }
+ return factory.getBeanDefinition();
+ }
- private static BeanDefinition parseComponent(Element element) {
- BeanDefinitionBuilder component = BeanDefinitionBuilder.rootBeanDefinition(Component.class);
- component.addPropertyValue("name", element.getAttribute("name"));
- return component.getBeanDefinition();
- }
+ private static BeanDefinition parseComponent(Element element) {
+ BeanDefinitionBuilder component = BeanDefinitionBuilder.rootBeanDefinition(Component.class);
+ component.addPropertyValue("name", element.getAttribute("name"));
+ return component.getBeanDefinition();
+ }
- private static void parseChildComponents(List childElements, BeanDefinitionBuilder factory) {
- ManagedList children = new ManagedList(childElements.size());
+ private static void parseChildComponents(List childElements, BeanDefinitionBuilder factory) {
+ ManagedList children = new ManagedList(childElements.size());
+ for (Element element : childElements) {
+ children.add(parseComponentElement(element));
+ }
+ factory.addPropertyValue("children", children);
+ }
- for (Element element : childElements) {
- children.add(parseComponentElement(element));
- }
-
- factory.addPropertyValue("children", children);
- }
-}
+ }
----
Lastly, the various artifacts need to be registered with the Spring XML infrastructure.
-[source]
+[literal]
[subs="verbatim,quotes"]
----
# in 'META-INF/spring.handlers'
http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler
----
-[source]
+[literal]
[subs="verbatim,quotes"]
----
# in 'META-INF/spring.schemas'
@@ -4182,13 +3963,13 @@ definition for a service object that will (unknown to it) be accessing a cluster
http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the named
JCache instance is eagerly started within the surrounding cluster:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
What we are going to do here is create another `BeanDefinition` when the
@@ -4197,128 +3978,132 @@ the named JCache for us. We will also modify the existing `BeanDefinition` for t
`'checkingAccountService'` so that it will have a dependency on this new
JCache-initializing `BeanDefinition`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-public class JCacheInitializer {
+ public class JCacheInitializer {
- private String name;
+ private String name;
- public JCacheInitializer(String name) {
- this.name = name;
- }
+ public JCacheInitializer(String name) {
+ this.name = name;
+ }
- public void initialize() {
- // lots of JCache API calls to initialize the named cache...
- }
-}
+ public void initialize() {
+ // lots of JCache API calls to initialize the named cache...
+ }
+
+ }
----
Now onto the custom extension. Firstly, the authoring of the XSD schema describing the
custom attribute (quite easy in this case).
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
+
-
+
-
+
----
Next, the associated `NamespaceHandler`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
-public class JCacheNamespaceHandler extends NamespaceHandlerSupport {
+ public class JCacheNamespaceHandler extends NamespaceHandlerSupport {
- public void init() {
- super.registerBeanDefinitionDecoratorForAttribute("cache-name",
- new JCacheInitializingBeanDefinitionDecorator());
- }
-}
+ public void init() {
+ super.registerBeanDefinitionDecoratorForAttribute("cache-name",
+ new JCacheInitializingBeanDefinitionDecorator());
+ }
+
+ }
----
Next, the parser. Note that in this case, because we are going to be parsing an XML
attribute, we write a `BeanDefinitionDecorator` rather than a `BeanDefinitionParser`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo;
+ package com.foo;
-import org.springframework.beans.factory.config.BeanDefinitionHolder;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Node;
+ import org.springframework.beans.factory.config.BeanDefinitionHolder;
+ import org.springframework.beans.factory.support.AbstractBeanDefinition;
+ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+ import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
+ import org.springframework.beans.factory.xml.ParserContext;
+ import org.w3c.dom.Attr;
+ import org.w3c.dom.Node;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.List;
-public class JCacheInitializingBeanDefinitionDecorator implements BeanDefinitionDecorator {
+ public class JCacheInitializingBeanDefinitionDecorator implements BeanDefinitionDecorator {
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
- public BeanDefinitionHolder decorate(
- Node source, BeanDefinitionHolder holder, ParserContext ctx) {
- String initializerBeanName = registerJCacheInitializer(source, ctx);
- createDependencyOnJCacheInitializer(holder, initializerBeanName);
- return holder;
- }
+ public BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder holder,
+ ParserContext ctx) {
+ String initializerBeanName = registerJCacheInitializer(source, ctx);
+ createDependencyOnJCacheInitializer(holder, initializerBeanName);
+ return holder;
+ }
- private void createDependencyOnJCacheInitializer(BeanDefinitionHolder holder, String initializerBeanName) {
- AbstractBeanDefinition definition = ((AbstractBeanDefinition) holder.getBeanDefinition());
- String[] dependsOn = definition.getDependsOn();
- if (dependsOn == null) {
- dependsOn = new String[]{initializerBeanName};
- } else {
- List dependencies = new ArrayList(Arrays.asList(dependsOn));
- dependencies.add(initializerBeanName);
- dependsOn = (String[]) dependencies.toArray(EMPTY_STRING_ARRAY);
- }
- definition.setDependsOn(dependsOn);
- }
+ private void createDependencyOnJCacheInitializer(BeanDefinitionHolder holder,
+ String initializerBeanName) {
+ AbstractBeanDefinition definition = ((AbstractBeanDefinition) holder.getBeanDefinition());
+ String[] dependsOn = definition.getDependsOn();
+ if (dependsOn == null) {
+ dependsOn = new String[]{initializerBeanName};
+ } else {
+ List dependencies = new ArrayList(Arrays.asList(dependsOn));
+ dependencies.add(initializerBeanName);
+ dependsOn = (String[]) dependencies.toArray(EMPTY_STRING_ARRAY);
+ }
+ definition.setDependsOn(dependsOn);
+ }
- private String registerJCacheInitializer(Node source, ParserContext ctx) {
- String cacheName = ((Attr) source).getValue();
- String beanName = cacheName + "-initializer";
- if (!ctx.getRegistry().containsBeanDefinition(beanName)) {
- BeanDefinitionBuilder initializer = BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class);
- initializer.addConstructorArg(cacheName);
- ctx.getRegistry().registerBeanDefinition(beanName, initializer.getBeanDefinition());
- }
- return beanName;
- }
-}
+ private String registerJCacheInitializer(Node source, ParserContext ctx) {
+ String cacheName = ((Attr) source).getValue();
+ String beanName = cacheName + "-initializer";
+ if (!ctx.getRegistry().containsBeanDefinition(beanName)) {
+ BeanDefinitionBuilder initializer = BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class);
+ initializer.addConstructorArg(cacheName);
+ ctx.getRegistry().registerBeanDefinition(beanName, initializer.getBeanDefinition());
+ }
+ return beanName;
+ }
+
+ }
----
Lastly, the various artifacts need to be registered with the Spring XML infrastructure.
-[source]
+[literal]
[subs="verbatim,quotes"]
----
# in 'META-INF/spring.handlers'
http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler
----
-[source]
+[literal]
[subs="verbatim,quotes"]
----
# in 'META-INF/spring.schemas'
@@ -4715,13 +4500,13 @@ escaping. Modeled after the JSTL c:url tag with backwards compatibility in mind.
| true
| true
| The URL to build. This value can include template {placeholders} that are replaced
- with the URL encoded value of the named parameter. Parameters must be defined using
+ with the URL encoded value of the named parameter. Parameters must be defined using
the param tag inside the body of this tag.
| context
| false
| true
-| Specifies a remote application context path. The default is the current application
+| Specifies a remote application context path. The default is the current application
context path.
| var
@@ -4733,8 +4518,8 @@ escaping. Modeled after the JSTL c:url tag with backwards compatibility in mind.
| scope
| false
| true
-| The scope for the var. 'application', 'session', 'request' and 'page' scopes are
- supported. Defaults to page scope. This attribute has no effect unless the var
+| The scope for the var. 'application', 'session', 'request' and 'page' scopes are
+ supported. Defaults to page scope. This attribute has no effect unless the var
attribute is also defined.
| htmlEscape
@@ -4778,8 +4563,8 @@ variable.
| scope
| false
| true
-| The scope for the var. 'application', 'session', 'request' and 'page' scopes are
- supported. Defaults to page scope. This attribute has no effect unless the var
+| The scope for the var. 'application', 'session', 'request' and 'page' scopes are
+ supported. Defaults to page scope. This attribute has no effect unless the var
attribute is also defined.
| htmlEscape
@@ -5038,7 +4823,7 @@ Renders multiple HTML 'input' tags with type 'checkbox'.
| false
| true
| Specifies the HTML element that is used to enclose each 'input' tag with type
- 'checkbox'. Defaults to 'span'.
+ 'checkbox'. Defaults to 'span'.
| htmlEscape
| false
@@ -6390,7 +6175,7 @@ Renders multiple HTML 'input' tags with type 'radio'.
| false
| true
| Specifies the HTML element that is used to enclose each 'input' tag with type 'radio'.
- Defaults to 'span'.
+ Defaults to 'span'.
| htmlEscape
| false
diff --git a/src/asciidoc/images/spring-overview.png b/src/asciidoc/images/spring-overview.png
index c971a29e94..952c9db6c8 100644
Binary files a/src/asciidoc/images/spring-overview.png and b/src/asciidoc/images/spring-overview.png differ
diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc
index 3548644a0a..885664150d 100644
--- a/src/asciidoc/index.adoc
+++ b/src/asciidoc/index.adoc
@@ -1,9 +1,7 @@
= Spring Framework Reference Documentation
Rod Johnson; Juergen Hoeller; Keith Donald; Colin Sampaleanu; Rob Harrop; Thomas Risberg; Alef Arendsen; Darren Davison; Dmitriy Kopylenko; Mark Pollack; Thierry Templier; Erwin Vervaet; Portia Tung; Ben Hale; Adrian Colyer; John Lewis; Costin Leau; Mark Fisher; Sam Brannen; Ramnivas Laddad; Arjen Poutsma; Chris Beams; Tareq Abedrabbo; Andy Clement; Dave Syer; Oliver Gierke; Rossen Stoyanchev; Phillip Webb; Rob Winch
-
-
-
+:javadoc-baseurl: http://docs.spring.io/spring/docs/current/javadoc-api
[[spring-introduction]]
= Overview of Spring Framework
@@ -35,6 +33,26 @@ list or on the support forums at http://forum.spring.io/[].
+[[overview-getting-started-with-spring]]
+== Getting Started With Spring
+This reference guide provides detailed information about the Spring Framework.
+It provides comprehensive documentation for all features, as well as some background
+about the underlying concepts (such as __"Dependency Injection"__) that Spring has
+embraced.
+
+If you are just getting started with Spring, you may want to begin with the lighter
+https://spring.io/guides["Getting Started"] guides that are available from
+http://spring.io. As well as being easier to digest, these guide are very
+__task focused__. They also cover other projects from the Spring portfolio that you might
+ want to consider when solving a particular problem.
+
+https://spring.io/guides/gs/rest-service/[Getting Started Building a RESTful Web Service]
+would be an excellent first choice to get your feet wet.
+
+
+
+
+
[[overview]]
== Introduction to Spring Framework
Spring Framework is a Java platform that provides comprehensive infrastructure support
@@ -73,13 +91,13 @@ http://martinfowler.com/articles/injection.html[http://martinfowler.com/articles
Java applications -- a loose term that runs the gamut from constrained applets to n-tier
server-side enterprise applications -- typically consist of objects that collaborate to
-form the application proper. Thus the objects in an application have__dependencies__ on
+form the application proper. Thus the objects in an application have __dependencies__ on
each other.
Although the Java platform provides a wealth of application development functionality,
it lacks the means to organize the basic building blocks into a coherent whole, leaving
that task to architects and developers. True, you can use design patterns such
-as__Factory__, __Abstract Factory__, __Builder__, __Decorator__, and __Service Locator__
+as __Factory__, __Abstract Factory__, __Builder__, __Decorator__, and __Service Locator__
to compose the various classes and object instances that make up an application.
However, these patterns are simply that: best practices given a name, with a description
of what the pattern does, where to apply it, the problems it addresses, and so forth.
@@ -103,7 +121,7 @@ are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Orien
Programming), Instrumentation, and Test, as shown in the following diagram.
.Overview of the Spring Framework
-image::images/spring-overview.png[]
+image::images/spring-overview.png[width=400]
@@ -147,11 +165,10 @@ The <> module provides a JDBC-abstraction layer that rem
need to do tedious JDBC coding and parsing of database-vendor specific error codes.
The <> module provides integration layers for popular
-object-relational mapping APIs, including <>, <>,
-<>, and <>. Using the ORM package you can
-use all of these O/R-mapping frameworks in combination with all of the other features
-Spring offers, such as the simple declarative transaction management feature mentioned
-previously.
+object-relational mapping APIs, including <>, <>, and
+<>. Using the ORM package you can use all of these O/R-mapping
+frameworks in combination with all of the other features Spring offers, such as the simple
+declarative transaction management feature mentioned previously.
The <> module provides an abstraction layer that supports Object/XML mapping
implementations for JAXB, Castor, XMLBeans, JiBX and XStream.
@@ -179,11 +196,6 @@ The __Web-Servlet__ module contains Spring's model-view-controller
framework provides a clean separation between domain model code and web forms, and
integrates with all the other features of the Spring Framework.
-The __Web-Struts__ module contains the support classes for integrating a classic Struts
-web tier within a Spring application. Note that this support is now deprecated as of
-Spring 3.0. Consider migrating your application to Struts 2.0 and its Spring integration
-or to a Spring MVC solution.
-
The __Web-Portlet__ module provides the MVC implementation to be used in a portlet
environment and mirrors the functionality of Web-Servlet module.
@@ -221,7 +233,7 @@ from applets to full-fledged enterprise applications that use Spring's transacti
management functionality and web framework integration.
.Typical full-fledged Spring web application
-image::images/overview-full.png[]
+image::images/overview-full.png[width=400]
Spring's <> make
the web application fully transactional, just as it would be if you used EJB
@@ -229,32 +241,32 @@ container-managed transactions. All your custom business logic can be implemente
simple POJOs and managed by Spring's IoC container. Additional services include support
for sending email and validation that is independent of the web layer, which lets you
choose where to execute validation rules. Spring's ORM support is integrated with JPA,
-Hibernate, JDO and iBatis; for example, when using Hibernate, you can continue to use
+Hibernate and and JDO; for example, when using Hibernate, you can continue to use
your existing mapping files and standard Hibernate `SessionFactory` configuration. Form
controllers seamlessly integrate the web-layer with the domain model, removing the need
for `ActionForms` or other classes that transform HTTP parameters to values for your
domain model.
.Spring middle-tier using a third-party web framework
-image::images/overview-thirdparty-web.png[]
+image::images/overview-thirdparty-web.png[width=400]
Sometimes circumstances do not allow you to completely switch to a different framework.
The Spring Framework does __not__ force you to use everything within it; it is not an
-__all-or-nothing__ solution. Existing front-ends built with WebWork, Struts, Tapestry,
+__all-or-nothing__ solution. Existing front-ends built with Struts, Tapestry, JSF
or other UI frameworks can be integrated with a Spring-based middle-tier, which allows
you to use Spring transaction features. You simply need to wire up your business logic
using an `ApplicationContext` and use a `WebApplicationContext` to integrate your web
layer.
.Remoting usage scenario
-image::images/overview-remoting.png[]
+image::images/overview-remoting.png[width=400]
When you need to access existing code through web services, you can use Spring's
`Hessian-`, `Burlap-`, `Rmi-` or `JaxRpcProxyFactory` classes. Enabling remote access to
existing applications is not difficult.
.EJBs - Wrapping existing POJOs
-image::images/overview-ejb.png[]
+image::images/overview-ejb.png[width=400]
The Spring Framework also provides an <> for
Enterprise JavaBeans, enabling you to reuse your existing POJOs and wrap them in
@@ -281,106 +293,30 @@ the pieces of Spring that you need. To make this easier Spring is packaged as a
modules that separate the dependencies as much as possible, so for example if you don't
want to write a web application you don't need the spring-web modules. To refer to
Spring library modules in this guide we use a shorthand naming convention `spring-*` or
-`spring-*.jar,` where "*" represents the short name for the module (e.g. `spring-core`,
-`spring-webmvc`, `spring-jms`, etc.). The actual jar file name that you use may be in
-this form (see below) or it may not, and normally it also has a version number in the
-file name (e.g. __spring-core-{spring-version}.jar__).
+`spring-*.jar,` where `*` represents the short name for the module (e.g. `spring-core`,
+`spring-webmvc`, `spring-jms`, etc.). The actual jar file name that you use is normally
+the module name concatenated with the version number
+(e.g. __spring-core-{spring-version}.jar__).
-In general, Spring publishes its artifacts to four different places:
+Each release of the Spring Framework will publish artifacts to the following places:
-* On the community download site
- http://www.springsource.org/download/community[http://www.springsource.org/download/community].
- Here you find all the Spring jars bundled together into a zip file for easy download.
- The names of the jars here since version 3.0 are in the form
- `org.springframework.*-.jar`.
* Maven Central, which is the default repository that Maven queries, and does not
require any special configuration to use. Many of the common libraries that Spring
depends on also are available from Maven Central and a large section of the Spring
community uses Maven for dependency management, so this is convenient for them. The
names of the jars here are in the form `spring-*-.jar` and the Maven groupId
is `org.springframework`.
-* The Enterprise Bundle Repository (EBR), which is run by SpringSource and also hosts
- all the libraries that integrate with Spring. Both Maven and Ivy repositories are
- available here for all Spring jars and their dependencies, plus a large number of
- other common libraries that people use in applications with Spring. Both full releases
- and also milestones and development snapshots are deployed here. The names of the jar
- files are in the same form as the community download (
- `org.springframework.*-.jar`), and the dependencies are also in this "long"
- form, with external libraries (not from SpringSource) having the prefix
- `com.springsource`. See the http://ebr.springsource.com/repository/app/faq[FAQ] for
- more information.
-* In a public Maven repository hosted on Amazon S3 for development snapshots and
- milestone releases (a copy of the final releases is also held here). The jar file
- names are in the same form as Maven Central, so this is a useful place to get
+* In a public Maven repository hosted specifically for Spring. In addition to the final
+ GA releases, this repository also hosts development snapshots and milestones. The jar
+ file names are in the same form as Maven Central, so this is a useful place to get
development versions of Spring to use with other libraries deployed in Maven Central.
+ This repository also contains a bundle distribution zip file that contains all Spring
+ jars bundled together for easy download.
-So the first thing you need to decide is how to manage your dependencies: most people
-use an automated system like Maven or Ivy, but you can also do it manually by
-downloading all the jars yourself. When obtaining Spring with Maven or Ivy you have then
-to decide which place you'll get it from. In general, if you care about OSGi, use the
-EBR, since it houses OSGi compatible artifacts for all of Spring's dependencies, such as
-Hibernate and Freemarker. If OSGi does not matter to you, either place works, though
-there are some pros and cons between them. In general, pick one place or the other for
-your project; do not mix them. This is particularly important since EBR artifacts
-necessarily use a different naming convention than Maven Central artifacts.
-
-[[dependency-comparison-of-maven-central-and-ebr-tbl]]
-.Comparison of Maven Central and SpringSource EBR Repositories
-|===
-| Feature| Maven Central| EBR
-
-| OSGi Compatible
-| Not explicit
-| Yes
-
-| Number of Artifacts
-| Tens of thousands; all kinds
-| Hundreds; those that Spring integrates with
-
-| Consistent Naming Conventions
-| No
-| Yes
-
-| Naming Convention: GroupId
-| Varies. Newer artifacts often use domain name, e.g. org.slf4j. Older ones often just
- use the artifact name, e.g. log4j.
-| Domain name of origin or main package root, e.g. org.springframework
-
-| Naming Convention: ArtifactId
-| Varies. Generally the project or module name, using a hyphen "-" separator, e.g.
- spring-core, logj4.
-| Bundle Symbolic Name, derived from the main package root, e.g.
- org.springframework.beans. If the jar had to be patched to ensure OSGi compliance then
- com.springsource is appended, e.g. com.springsource.org.apache.log4j
-
-| Naming Convention: Version
-| Varies. Many new artifacts use m.m.m or m.m.m.X (with m=digit, X=text). Older ones use
- m.m. Some neither. Ordering is defined but not often relied on, so not strictly
- reliable.
-| OSGi version number m.m.m.X, e.g. 3.0.0.RC3. The text qualifier imposes alphabetic
- ordering on versions with the same numeric values.
-
-| Publishing
-| Usually automatic via rsync or source control updates. Project authors can upload
- individual jars to JIRA.
-| Manual (JIRA processed by SpringSource)
-
-| Quality Assurance
-| By policy. Accuracy is responsibility of authors.
-| Extensive for OSGi manifest, Maven POM and Ivy metadata. QA performed by Spring team.
-
-| Hosting
-| Contegix. Funded by Sonatype with several mirrors.
-| S3 funded by SpringSource.
-
-| Search Utilities
-| Various
-| http://ebr.springsource.com/repository/app/[http://ebr.springsource.com/repository/app/]
-
-| Integration with SpringSource Tools
-| Integration through STS with Maven dependency management
-| Extensive integration through STS with Maven, Roo, CloudFoundry
-|===
+So the first thing you need to decide is how to manage your dependencies: we generally
+recommend the use of an automated system like Maven, Gradle or Ivy, but you can also do
+it manually by downloading all the jars yourself. We provide detailed instructions later
+in this chapter.
[[overview-spring-dependencies]]
@@ -393,177 +329,214 @@ injection there is only one mandatory external dependency, and that is for loggi
below for a more detailed description of logging options).
Next we outline the basic steps needed to configure an application that depends on
-Spring, first with Maven and then with Ivy. In all cases, if anything is unclear, refer
-to the documentation of your dependency management system, or look at some sample code -
-Spring itself uses Ivy to manage dependencies when it is building, and our samples
-mostly use Maven.
+Spring, first with Maven and then with Gradle and finally using Ivy. In all cases, if
+anything is unclear, refer to the documentation of your dependency management system, or
+look at some sample code - Spring itself uses Gradle to manage dependencies when it is
+building, and our samples mostly use Gradle or Maven.
[[overview-maven-dependency-management]]
===== Maven Dependency Management
-If you are using Maven for dependency management you don't even need to supply the
-logging dependency explicitly. For example, to create an application context and use
-dependency injection to configure an application, your Maven dependencies will look like
-this:
+If you are using http://maven.apache.org/[Maven] for dependency management you don't even
+need to supply the logging dependency explicitly. For example, to create an application
+context and use dependency injection to configure an application, your Maven dependencies
+will look like this:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
-
-
- org.springframework
- spring-context
- {spring-version}
- runtime
-
-
+
+
+ org.springframework
+ spring-context
+ {spring-version}
+ runtime
+
+
----
That's it. Note the scope can be declared as runtime if you don't need to compile
against Spring APIs, which is typically the case for basic dependency injection use
cases.
-We used the Maven Central naming conventions in the example above, so that works with
-Maven Central or the SpringSource Maven repository. To use the Spring Maven repository
-(e.g. for milestones or developer snapshots), you need to specify the repository
-location in your Maven configuration. For full releases:
+The example above works with the Maven Central repository. To use the Spring Maven
+repository (e.g. for milestones or developer snapshots), you need to specify the
+repository location in your Maven configuration. For full releases:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- io.spring.repo.maven.release
- https://repo.spring.io/release/
- false
-
-
+
+
+ io.spring.repo.maven.release
+ http://repo.spring.io/release/
+ false
+
+
----
For milestones:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- io.spring.repo.maven.milestone
- https://repo.spring.io/milestone/
- false
-
-
+
+
+ io.spring.repo.maven.milestone
+ http://repo.spring.io/milestone/
+ false
+
+
----
And for snapshots:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- io.spring.repo.maven.snapshot
- https://repo.spring.io/snapshot/
- true
-
-
+
+
+ io.spring.repo.maven.snapshot
+ http://repo.spring.io/snapshot/
+ true
+
+
----
-To use the SpringSource EBR you would need to use a different naming convention for the
-dependencies. The names are usually easy to guess, e.g. in this case it is:
-[source,xml]
+[[overview-maven-bom]]
+===== Maven "Bill Of Materials" Dependency =====
+It is possible to accidentally mix different versions of Spring JARs when using Maven.
+For example, you may find that a third-party library, or another Spring project,
+pulls in a transitive dependency to an older release. If you forget to explicitly declare
+a direct dependency yourself, all sorts of unexpected issues can arise.
+
+To overcome such problems Maven supports the concept of a "bill of materials" (BOM)
+dependency. You can import the `spring-framework-bom` in your `dependencyManagement`
+section to ensure that all spring dependencies (both direct and transitive) are at
+the same version.
+
+[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
-
-
- org.springframework
- org.springframework.context
- {spring-version}
- runtime
-
-
+
+
+
+ org.springframework
+ spring-framework-bom
+ {spring-version}
+ pom
+ import
+
+
+
----
-You also need to declare the location of the repository explicitly (only the URL is
-important):
+An added benefit of using the BOM is that you no longer need to specify the ``
+attribute when depending on Spring Framework artifacts:
-[source,xml]
+[source,xml,indent=0]
+[subs="verbatim,quotes,attributes"]
+----
+
+
+ org.springframework
+ spring-context
+
+
+ org.springframework
+ spring-web
+
+
+----
+
+
+[[overview-gradle-dependency-management]]
+===== Gradle Dependency Management
+To use the Spring repository with the http://www.gradle.org/[Gradle] build system,
+include the appropriate URL in the `repositories` section:
+
+[source,groovy,indent=0]
[subs="verbatim,quotes"]
----
-
-
- com.springsource.repository.bundles.release
- http://repository.springsource.com/maven/bundles/release/
-
-
+ repositories {
+ mavenCentral()
+ // and optionally...
+ maven { url "http://repo.spring.io/release" }
+ }
----
-If you are managing your dependencies by hand, the URL in the repository declaration
-above is not browsable, but there is a user interface at
-http://ebr.springsource.com/repository/app/[http://ebr.springsource.com/repository/app/]
-that can be used to search for and download dependencies. It also has handy snippets of
-Maven and Ivy configuration that you can copy and paste if you are using those tools.
+You can change the `repositories` URL from `/release` to `/milestone` or `/snapshot` as
+appropriate. Once a repository has been configured, you can declare dependencies in the
+usual Gradle way:
+
+[source,groovy,indent=0]
+[subs="verbatim,quotes,attributes"]
+----
+ dependencies {
+ compile("org.springframework:spring-context:{spring-version}")
+ testCompile("org.springframework:spring-test:{spring-version}")
+ }
+----
[[overview-ivy-dependency-management]]
===== Ivy Dependency Management
If you prefer to use http://ant.apache.org/ivy[Ivy] to manage dependencies then there
-are similar names and configuration options.
+are similar configuration options.
-To configure Ivy to point to the SpringSource EBR add the following resolvers to your
+To configure Ivy to point to the Spring repository add the following resolver to your
`ivysettings.xml`:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
----
-The XML above is not valid because the lines are too long - if you copy-paste then
-remove the extra line endings in the middle of the url patterns.
+You can change the `root` URL from `/release/` to `/milestone/` or `/snapshot/` as
+appropriate.
-Once Ivy is configured to look in the EBR adding a dependency is easy. Simply pull up
-the details page for the bundle in question in the repository browser and you'll find an
-Ivy snippet ready for you to include in your dependencies section. For example (in
-`ivy.xml`):
+Once configured, you can add dependencies in the usual way. For example (in `ivy.xml`):
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
-
+
----
+[[overview-distribution-zip]]
+===== Distribution Zip Files
+Although using a build system that supports dependency management is the recommended
+way to obtain the Spring Framework, it is still possible to download a distribution
+zip file.
+
+Distribution zips are published to the Spring Maven Repository (this is just for our
+convenience, you don't need Maven or any other build system in order to download them).
+
+To download a distribution zip open a web browser to
+http://repo.spring.io/release/org/springframework/spring and select the appropriate
+subfolder for the version that you want. Distribution files end `-dist.zip`, for example
++spring-framework-{spring-version}-RELEASE-dist.zip+. Distributions are also published
+for http://repo.spring.io/milestone/org/springframework/spring[milestones] and
+http://repo.spring.io/snapshot/org/springframework/spring[snapshots].
+
+
[[overview-logging]]
==== Logging
-Logging is a very important dependency for Spring because a) it is the only mandatory
-external dependency, b) everyone likes to see some output from the tools they are using,
-and c) Spring integrates with lots of other tools all of which have also made a choice
-of logging dependency. One of the goals of an application developer is often to have
-unified logging configured in a central place for the whole application, including all
-external components. This is more difficult than it might have been since there are so
+Logging is a very important dependency for Spring because __a)__ it is the only mandatory
+external dependency, __b)__ everyone likes to see some output from the tools they are
+using, and __c)__ Spring integrates with lots of other tools all of which have also made
+a choice of logging dependency. One of the goals of an application developer is often to
+have unified logging configured in a central place for the whole application, including
+all external components. This is more difficult than it might have been since there are so
many choices of logging framework.
The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We
@@ -598,23 +571,23 @@ Switching off `commons-logging` is easy: just make sure it isn't on the classpat
runtime. In Maven terms you exclude the dependency, and because of the way that the
Spring dependencies are declared, you only have to do that once.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
-
-
- org.springframework
- spring-context
- {spring-version}
- runtime
-
-
- commons-logging
- commons-logging
-
-
-
-
+
+
+ org.springframework
+ spring-context
+ {spring-version}
+ runtime
+
+
+ commons-logging
+ commons-logging
+
+
+
+
----
Now this application is probably broken because there is no implementation of the JCL
@@ -643,47 +616,47 @@ from SLF4J to Log4J. You need to supply 4 dependencies (and exclude the existing
`commons-logging`): the bridge, the SLF4J API, the binding to Log4J, and the Log4J
implementation itself. In Maven you would do that like this
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
-
-
- org.springframework
- spring-context
- {spring-version}
- runtime
-
-
- commons-logging
- commons-logging
-
-
-
-
- org.slf4j
- jcl-over-slf4j
- 1.5.8
- runtime
-
-
- org.slf4j
- slf4j-api
- 1.5.8
- runtime
-
-
- org.slf4j
- slf4j-log4j12
- 1.5.8
- runtime
-
-
- log4j
- log4j
- 1.2.14
- runtime
-
-
+
+
+ org.springframework
+ spring-context
+ {spring-version}
+ runtime
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.slf4j
+ jcl-over-slf4j
+ 1.5.8
+ runtime
+
+
+ org.slf4j
+ slf4j-api
+ 1.5.8
+ runtime
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.5.8
+ runtime
+
+
+ log4j
+ log4j
+ 1.2.14
+ runtime
+
+
----
That might seem like a lot of dependencies just to get some logging. Well it is, but it
@@ -713,28 +686,28 @@ do is put Log4j on the classpath, and provide it with a configuration file (
`log4j.properties` or `log4j.xml` in the root of the classpath). So for Maven users this
is your dependency declaration:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
-
-
- org.springframework
- spring-context
- {spring-version}
- runtime
-
-
- log4j
- log4j
- 1.2.14
- runtime
-
-
+
+
+ org.springframework
+ spring-context
+ {spring-version}
+ runtime
+
+
+ log4j
+ log4j
+ 1.2.14
+ runtime
+
+
----
And here's a sample log4j.properties for logging to the console:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
log4j.rootCategory=INFO, stdout
@@ -771,7 +744,6 @@ the exact version and feature set of the container.
-
[[spring-core]]
= Core Technologies
[partintro]
@@ -820,7 +792,7 @@ testing will hopefully convince you of this as well.
[[beans-introduction]]
=== Introduction to the Spring IoC container and beans
This chapter covers the Spring Framework implementation of the Inversion of Control
-(IoC) footnote:[See pass:specialcharacters,macros[<>] ] principle. IoC
+(IoC) footnote:[See pass:specialcharacters,macros[<>] ] principle. IoC
is also known as __dependency injection__ (DI). It is a process whereby objects define
their dependencies, that is, the other objects they work with, only through constructor
arguments, arguments to a factory method, or properties that are set on the object
@@ -832,10 +804,10 @@ construction of classes, or a mechanism such as the __Service Locator__ pattern.
The `org.springframework.beans` and `org.springframework.context` packages are the basis
for Spring Framework's IoC container. The
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html[BeanFactory]
+{javadoc-baseurl}/org/springframework/beans/factory/BeanFactory.html[BeanFactory]
interface provides an advanced configuration mechanism capable of managing any type of
object.
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html[ApplicationContext]
+{javadoc-baseurl}/org/springframework/context/ApplicationContext.html[ApplicationContext]
is a sub-interface of `BeanFactory`. It adds easier integration with Spring's AOP
features; message resource handling (for use in internationalization), event
publication; and application-layer specific contexts such as the `WebApplicationContext`
@@ -844,7 +816,7 @@ for use in web applications.
In short, the `BeanFactory` provides the configuration framework and basic
functionality, and the `ApplicationContext` adds more enterprise-specific functionality.
The `ApplicationContext` is a complete superset of the `BeanFactory`, and is used
-exclusively in this chapter in descriptions of Spring's IoC container.For more
+exclusively in this chapter in descriptions of Spring's IoC container. For more
information on using the `BeanFactory` instead of the `ApplicationContext,` refer to
<>.
@@ -870,8 +842,8 @@ between such objects.
Several implementations of the `ApplicationContext` interface are supplied
out-of-the-box with Spring. In standalone applications it is common to create an
instance of
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
-or http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`].
+{javadoc-baseurl}/org/springframework/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
+or {javadoc-baseurl}/org/springframework/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`].
While XML has been the traditional format for defining configuration metadata you can
instruct the container to use Java annotations or code as the metadata format by
providing a small amount of XML configuration to declaratively enable support for these
@@ -879,11 +851,11 @@ additional metadata formats.
In most application scenarios, explicit user code is not required to instantiate one or
more instances of a Spring IoC container. For example, in a web application scenario, a
-simple eight (or so) lines of boilerplate J2EE web descriptor XML in the `web.xml` file
+simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file
of the application will typically suffice (see <>). If you are using the
http://spring.io/tools/sts[SpringSource Tool Suite] Eclipse-powered development
-environment or https://github.com/spring-projects/spring-roo[Spring Roo] this
-boilerplate configuration can be easily created with few mouse clicks or keystrokes.
+environment this boilerplate configuration can be easily created with few mouse clicks or
+keystrokes.
The following diagram is a high-level view of how Spring works. Your application classes
are combined with configuration metadata so that after the `ApplicationContext` is
@@ -891,7 +863,7 @@ created and initialized, you have a fully configured and executable system or
application.
.The Spring IoC container
-image::images/container-magic.png[]
+image::images/container-magic.png[width=250]
@@ -909,8 +881,9 @@ Spring IoC container.
[NOTE]
====
XML-based metadata is __not__ the only allowed form of configuration metadata. The
-Spring IoC container itself is__totally__ decoupled from the format in which this
-configuration metadata is actually written.
+Spring IoC container itself is __totally__ decoupled from the format in which this
+configuration metadata is actually written. These days many developers choose
+<> for their Spring applications.
====
For information about using other forms of metadata with the Spring container, see:
@@ -920,12 +893,13 @@ For information about using other forms of metadata with the Spring container, s
* <>: Starting with Spring 3.0, many features
provided by the Spring JavaConfig project became part of the core Spring Framework.
Thus you can define beans external to your application classes by using Java rather
- than XML files. To use these new features, see the `@Configuration`, `@Bean, @Import`
+ than XML files. To use these new features, see the `@Configuration`, `@Bean`, `@Import`
and `@DependsOn` annotations.
Spring configuration consists of at least one and typically more than one bean
definition that the container must manage. XML-based configuration metadata shows these
-beans configured as `` elements inside a top-level `` element.
+beans configured as `` elements inside a top-level `` element. Java
+configuration typically uses `@Bean` annotated methods within a `@Configuration` class.
These bean definitions correspond to the actual objects that make up your application.
Typically you define service layer objects, data access objects (DAOs), presentation
@@ -939,26 +913,26 @@ dependency-inject domain objects with Spring>>.
The following example shows the basic structure of XML-based configuration metadata:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
----
The `id` attribute is a string that you use to identify the individual bean definition.
@@ -976,11 +950,11 @@ supplied to an `ApplicationContext` constructor are actually resource strings th
the container to load configuration metadata from a variety of external resources such
as the local file system, from the Java `CLASSPATH`, and so on.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext context =
- new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
----
[NOTE]
@@ -994,61 +968,60 @@ particular, `Resource` paths are used to construct applications contexts as desc
The following example shows the service layer objects `(services.xml)` configuration file:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
+
----
The following example shows the data access objects `daos.xml` file:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
----
In the preceding example, the service layer consists of the class `PetStoreServiceImpl`,
-and two data access objects of the type `SqlMapAccountDao` and SqlMapItemDao are based
-on the http://ibatis.apache.org/[iBatis] Object/Relational mapping framework. The
-`property name` element refers to the name of the JavaBean property, and the `ref`
-element refers to the name of another bean definition. This linkage between id and ref
-elements expresses the dependency between collaborating objects. For details of
-configuring an object's dependencies, see <>.
+and two data access objects of the type `JpaAccountDao` and `JpaItemDao` (based
+on the JPA Object/Relational mapping standard). The `property name` element refers to the
+name of the JavaBean property, and the `ref` element refers to the name of another bean
+definition. This linkage between `id` and `ref` elements expresses the dependency between
+collaborating objects. For details of configuring an object's dependencies, see
+<>.
[[beans-factory-xml-import]]
@@ -1061,19 +1034,17 @@ XML fragments. This constructor takes multiple `Resource` locations, as was show
previous section. Alternatively, use one or more occurrences of the `` element
to load bean definitions from another file or files. For example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
----
In the preceding example, external bean definitions are loaded from three files,
@@ -1084,7 +1055,7 @@ same directory or classpath location as the file doing the importing, while
location of the importing file. As you can see, a leading slash is ignored, but given
that these paths are relative, it is better form not to use the slash at all. The
contents of the files being imported, including the top level `` element, must
-be valid XML bean definitions according to the Spring Schema or DTD.
+be valid XML bean definitions according to the Spring Schema.
[NOTE]
====
@@ -1113,18 +1084,18 @@ name, Class requiredType)` you can retrieve instances of your beans.
The `ApplicationContext` enables you to read bean definitions and access them as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-// create and configure beans
-ApplicationContext context =
- new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
+ // create and configure beans
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
-// retrieve configured instance
-PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
+ // retrieve configured instance
+ PetStoreService service = context.getBean("petStore", PetStoreService.class);
-// use configured instance
-List userList = service.getUsernameList();
+ // use configured instance
+ List userList = service.getUsernameList();
----
You use `getBean()` to retrieve instances of your beans. The `ApplicationContext`
@@ -1151,7 +1122,7 @@ objects, which contain (among other information) the following metadata:
* Bean behavioral configuration elements, which state how the bean should behave in the
container (scope, lifecycle callbacks, and so forth).
* References to other beans that are needed for the bean to do its work; these
- references are also called__collaborators__ or __dependencies__.
+ references are also called __collaborators__ or __dependencies__.
* Other configuration settings to set in the newly created object, for example, the
number of connections to use in a bean that manages a connection pool, or the size
limit of the pool.
@@ -1164,31 +1135,31 @@ This metadata translates to a set of properties that make up each bean definitio
| Property| Explained in...
| class
-| <>
+| <>
| name
-| <>
+| <>
| scope
-| <>
+| <>
| constructor arguments
-| <>
+| <>
| properties
-| <>
+| <>
| autowiring mode
-| <>
+| <>
| lazy-initialization mode
-| <>
+| <>
| initialization method
-| <>
+| <>
| destruction method
-| <>
+| <>
|===
In addition to bean definitions that contain information on how to create a specific
@@ -1203,7 +1174,7 @@ defined through metadata bean definitions.
[[beans-beanname]]
-==== Naming beansBean naming conventions
+==== Naming beans
Every bean has one or more identifiers. These identifiers must be unique within the
container that hosts the bean. A bean usually has only one identifier, but if it
requires more than one, the extra ones can be considered aliases.
@@ -1211,11 +1182,11 @@ requires more than one, the extra ones can be considered aliases.
In XML-based configuration metadata, you use the `id` and/or `name` attributes to
specify the bean identifier(s). The `id` attribute allows you to specify exactly one id.
Conventionally these names are alphanumeric ('myBean', 'fooService', etc), but may
-special characters as well. If you want to introduce other aliases to the bean, you can
-also specify them in the `name` attribute, separated by a comma ( `,`), semicolon (
-`;`), or white space. As a historical note, in versions prior to Spring 3.1, the `id`
-attribute was typed as an `xsd:ID`, which constrained possible characters. As of 3.1,
-it is now `xsd:string`. Note that bean id uniqueness is still enforced by the
+special characters as well. If you want to introduce other aliases to the bean, you can
+also specify them in the `name` attribute, separated by a comma (`,`), semicolon (`;`),
+or white space. As a historical note, in versions prior to Spring 3.1, the `id`
+attribute was typed as an `xsd:ID`, which constrained possible characters. As of 3.1,
+it is now `xsd:string`. Note that bean id uniqueness is still enforced by the
container, though no longer by XML parsers.
You are not required to supply a name or id for a bean. If no name or id is supplied
@@ -1225,6 +1196,7 @@ refer to that bean by name, through the use of the `ref` element or
Motivations for not supplying a name are related to using <> and <>.
+.Bean Naming Conventions
****
The convention is to use the standard Java convention for instance field names when
naming beans. That is, bean names start with a lowercase letter, and are camel-cased
@@ -1252,37 +1224,41 @@ elsewhere. This is commonly the case in large systems where configuration is spl
amongst each subsystem, each subsystem having its own set of object definitions. In
XML-based configuration metadata, you can use the `` element to accomplish this.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
In this case, a bean in the same container which is named `fromName`, may also after the
use of this alias definition, be referred to as `toName`.
For example, the configuration metadata for subsystem A may refer to a DataSource via
-the name 'subsystemA-dataSource. The configuration metadata for subsystem B may refer to
-a DataSource via the name 'subsystemB-dataSource'. When composing the main application
+the name `subsystemA-dataSource`. The configuration metadata for subsystem B may refer to
+a DataSource via the name `subsystemB-dataSource`. When composing the main application
that uses both these subsystems the main application refers to the DataSource via the
-name 'myApp-dataSource'. To have all three names refer to the same object you add to the
+name `myApp-dataSource`. To have all three names refer to the same object you add to the
MyApp configuration metadata the following aliases definitions:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
----
Now each component and the main application can refer to the dataSource through a name
that is unique and guaranteed not to clash with any other definition (effectively
creating a namespace), yet they refer to the same bean.
-
+.Java-configuration
+****
+If you are using Java-configuration, the `@Bean` annotation can be used to provide aliases
+see <> for details.
+****
[[beans-factory-class]]
-==== Instantiating beansInner class names
+==== Instantiating beans
A bean definition essentially is a recipe for creating one or more objects. The
container looks at the recipe for a named bean when asked, and uses the configuration
metadata encapsulated by that bean definition to create (or acquire) an actual object.
@@ -1304,6 +1280,7 @@ You use the `Class` property in one of two ways:
class entirely.
****
+.Inner class names
If you want to configure a bean definition for a `static` nested class, you have to use
the __binary__ name of the inner class.
@@ -1336,12 +1313,12 @@ well.
With XML-based configuration metadata you can specify your bean class as follows:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
+
----
For details about the mechanism for supplying arguments to the constructor (if required)
@@ -1363,25 +1340,25 @@ factory-method. The definition does not specify the type (class) of the returned
only the class containing the factory method. In this example, the `createInstance()`
method must be a __static__ method.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ClientService {
- private static ClientService clientService = new ClientService();
- private ClientService() {}
+ public class ClientService {
+ private static ClientService clientService = new ClientService();
+ private ClientService() {}
- public static ClientService createInstance() {
- return clientService;
- }
-}
+ public static ClientService createInstance() {
+ return clientService;
+ }
+ }
----
For details about the mechanism for supplying (optional) arguments to the factory method
@@ -1399,67 +1376,71 @@ specify the name of a bean in the current (or parent/ancestor) container that co
the instance method that is to be invoked to create the object. Set the name of the
factory method itself with the `factory-method` attribute.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
-
-
+
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class DefaultServiceLocator {
- private static ClientService clientService = new ClientServiceImpl();
- private DefaultServiceLocator() {}
+ public class DefaultServiceLocator {
- public ClientService createClientServiceInstance() {
- return clientService;
- }
-}
+ private static ClientService clientService = new ClientServiceImpl();
+ private DefaultServiceLocator() {}
+
+ public ClientService createClientServiceInstance() {
+ return clientService;
+ }
+ }
----
One factory class can also hold more than one factory method as shown here:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
-
+
+
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class DefaultServiceLocator {
- private static ClientService clientService = new ClientServiceImpl();
- private static AccountService accountService = new AccountServiceImpl();
+ public class DefaultServiceLocator {
- private DefaultServiceLocator() {}
+ private static ClientService clientService = new ClientServiceImpl();
+ private static AccountService accountService = new AccountServiceImpl();
- public ClientService createClientServiceInstance() {
- return clientService;
- }
+ private DefaultServiceLocator() {}
- public AccountService createAccountServiceInstance() {
- return accountService;
- }
-}
+ public ClientService createClientServiceInstance() {
+ return clientService;
+ }
+
+ public AccountService createAccountServiceInstance() {
+ return accountService;
+ }
+
+ }
----
This approach shows that the factory bean itself can be managed and configured through
@@ -1496,7 +1477,7 @@ that is, the other objects they work with, only through constructor arguments, a
to a factory method, or properties that are set on the object instance after it is
constructed or returned from a factory method. The container then __injects__ those
dependencies when it creates the bean. This process is fundamentally the inverse, hence
-the name__Inversion of Control__ (IoC), of the bean itself controlling the instantiation
+the name __Inversion of Control__ (IoC), of the bean itself controlling the instantiation
or location of its dependencies on its own by using direct construction of classes, or
the __Service Locator__ pattern.
@@ -1520,21 +1501,22 @@ following example shows a class that can only be dependency-injected with constr
injection. Notice that there is nothing __special__ about this class, it is a POJO that
has no dependencies on container specific interfaces, base classes or annotations.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- // the SimpleMovieLister has a dependency on a MovieFinder
- private MovieFinder movieFinder;
+ // the SimpleMovieLister has a dependency on a MovieFinder
+ private MovieFinder movieFinder;
- // a constructor so that the Spring container can 'inject' a MovieFinder
- public SimpleMovieLister(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
+ // a constructor so that the Spring container can 'inject' a MovieFinder
+ public SimpleMovieLister(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
- // business logic that actually 'uses' the injected MovieFinder is omitted...
-}
+ // business logic that actually 'uses' the injected MovieFinder is omitted...
+
+ }
----
[[beans-factory-ctor-arguments-resolution]]
@@ -1545,17 +1527,18 @@ order in which the constructor arguments are defined in a bean definition is the
in which those arguments are supplied to the appropriate constructor when the bean is
being instantiated. Consider the following class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package x.y;
+ package x.y;
-public class Foo {
+ public class Foo {
- public Foo(Bar bar, Baz baz) {
- // ...
- }
-}
+ public Foo(Bar bar, Baz baz) {
+ // ...
+ }
+
+ }
----
No potential ambiguity exists, assuming that `Bar` and `Baz` classes are not related by
@@ -1563,44 +1546,45 @@ inheritance. Thus the following configuration works fine, and you do not need to
the constructor argument indexes and/or types explicitly in the ``
element.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
-
-
+
-
+
+
----
When another bean is referenced, the type is known, and matching can occur (as was the
case with the preceding example). When a simple type is used, such as
-`true`, Spring cannot determine the type of the value, and so cannot match
+`true`, Spring cannot determine the type of the value, and so cannot match
by type without help. Consider the following class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package examples;
+ package examples;
-public class ExampleBean {
+ public class ExampleBean {
- // No. of years to the calculate the Ultimate Answer
- private int years;
+ // No. of years to the calculate the Ultimate Answer
+ private int years;
- // The Answer to Life, the Universe, and Everything
- private String ultimateAnswer;
+ // The Answer to Life, the Universe, and Everything
+ private String ultimateAnswer;
- public ExampleBean(int years, String ultimateAnswer) {
- this.years = years;
- this.ultimateAnswer = ultimateAnswer;
- }
-}
+ public ExampleBean(int years, String ultimateAnswer) {
+ this.years = years;
+ this.ultimateAnswer = ultimateAnswer;
+ }
+
+ }
----
.[[beans-factory-ctor-arguments-type]]Constructor argument type matching
@@ -1609,13 +1593,13 @@ In the preceding scenario, the container __can__ use type matching with simple t
you explicitly specify the type of the constructor argument using the `type` attribute.
For example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
--
@@ -1624,13 +1608,13 @@ For example:
Use the `index` attribute to specify explicitly the index of constructor arguments. For
example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
In addition to resolving the ambiguity of multiple simple values, specifying an index
@@ -1640,15 +1624,15 @@ __index is 0 based__.
.[[beans-factory-ctor-arguments-name]]Constructor argument name
--
-As of Spring 3.0 you can also use the constructor parameter name for value disambiguation:
+You can also use the constructor parameter name for value disambiguation:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
Keep in mind that to make this work out of the box your code must be compiled with the
@@ -1658,27 +1642,28 @@ http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.ht
JDK annotation to explicitly name your constructor arguments. The sample class would
then have to look as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package examples;
+ package examples;
-public class ExampleBean {
+ public class ExampleBean {
- // Fields omitted
+ // Fields omitted
- @ConstructorProperties({"years", "ultimateAnswer"})
- public ExampleBean(int years, String ultimateAnswer) {
- this.years = years;
- this.ultimateAnswer = ultimateAnswer;
- }
-}
+ @ConstructorProperties({"years", "ultimateAnswer"})
+ public ExampleBean(int years, String ultimateAnswer) {
+ this.years = years;
+ this.ultimateAnswer = ultimateAnswer;
+ }
+
+ }
----
--
[[beans-setter-injection]]
-===== Setter-based dependency injectionConstructor-based or setter-based DI?
+===== Setter-based dependency injection
__Setter-based__ DI is accomplished by the container calling setter methods on your
beans after invoking a no-argument constructor or no-argument `static` factory method to
instantiate your bean.
@@ -1687,21 +1672,22 @@ The following example shows a class that can only be dependency-injected using p
setter injection. This class is conventional Java. It is a POJO that has no dependencies
on container specific interfaces, base classes or annotations.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- // the SimpleMovieLister has a dependency on the MovieFinder
- private MovieFinder movieFinder;
+ // the SimpleMovieLister has a dependency on the MovieFinder
+ private MovieFinder movieFinder;
- // a setter method so that the Spring container can 'inject' a MovieFinder
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
+ // a setter method so that the Spring container can 'inject' a MovieFinder
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
- // business logic that actually 'uses' the injected MovieFinder is omitted...
-}
+ // business logic that actually 'uses' the injected MovieFinder is omitted...
+
+ }
----
The `ApplicationContext` supports constructor- and setter-based DI for the beans it
@@ -1713,6 +1699,7 @@ directly (programmatically), but rather with an XML definition file that is then
converted internally into instances of these classes, and used to load an entire Spring
IoC container instance.
+.Constructor-based or setter-based DI?
****
Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to
use constructor arguments for mandatory dependencies and setters for optional
@@ -1737,7 +1724,7 @@ the only available DI.
[[beans-dependency-resolution]]
-===== Dependency resolution processCircular dependencies
+===== Dependency resolution process
The container performs bean dependency resolution as follows:
* The `ApplicationContext` is created and initialized with configuration metadata that
@@ -1763,6 +1750,7 @@ are created when the container is created. Scopes are defined in
Creation of a bean potentially causes a graph of beans to be created, as the bean's
dependencies and its dependencies' dependencies (and so on) are created and assigned.
+.Circular dependencies
****
If you use predominantly constructor injection, it is possible to create an unresolvable
circular dependency scenario.
@@ -1812,85 +1800,85 @@ are invoked.
The following example uses XML-based configuration metadata for setter-based DI. A small
part of a Spring XML configuration file specifies some bean definitions:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
+
+
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ExampleBean {
+ public class ExampleBean {
- private AnotherBean beanOne;
- private YetAnotherBean beanTwo;
- private int i;
+ private AnotherBean beanOne;
+ private YetAnotherBean beanTwo;
+ private int i;
- public void setBeanOne(AnotherBean beanOne) {
- this.beanOne = beanOne;
- }
+ public void setBeanOne(AnotherBean beanOne) {
+ this.beanOne = beanOne;
+ }
- public void setBeanTwo(YetAnotherBean beanTwo) {
- this.beanTwo = beanTwo;
- }
+ public void setBeanTwo(YetAnotherBean beanTwo) {
+ this.beanTwo = beanTwo;
+ }
- public void setIntegerProperty(int i) {
- this.i = i;
- }
-}
+ public void setIntegerProperty(int i) {
+ this.i = i;
+ }
+
+ }
----
In the preceding example, setters are declared to match against the properties specified
in the XML file. The following example uses constructor-based DI:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
+
+
+
+
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
+
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ExampleBean {
+ public class ExampleBean {
- private AnotherBean beanOne;
- private YetAnotherBean beanTwo;
- private int i;
+ private AnotherBean beanOne;
+ private YetAnotherBean beanTwo;
+ private int i;
- public ExampleBean(
- AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
- this.beanOne = anotherBean;
- this.beanTwo = yetAnotherBean;
- this.i = i;
- }
-}
+ public ExampleBean(
+ AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
+ this.beanOne = anotherBean;
+ this.beanTwo = yetAnotherBean;
+ this.i = i;
+ }
+
+ }
----
The constructor arguments specified in the bean definition will be used as arguments to
@@ -1899,41 +1887,41 @@ the constructor of the `ExampleBean`.
Now consider a variant of this example, where instead of using a constructor, Spring is
told to call a `static` factory method to return an instance of the object:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
-
-
+
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ExampleBean {
+ public class ExampleBean {
- // a private constructor
- private ExampleBean(...) {
- ...
- }
+ // a private constructor
+ private ExampleBean(...) {
+ ...
+ }
- // a static factory method; the arguments to this method can be
- // considered the dependencies of the bean that is returned,
- // regardless of how those arguments are actually used.
- public static ExampleBean createInstance (
- AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
+ // a static factory method; the arguments to this method can be
+ // considered the dependencies of the bean that is returned,
+ // regardless of how those arguments are actually used.
+ public static ExampleBean createInstance (
+ AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
- ExampleBean eb = new ExampleBean (...);
- // some other operations...
- return eb;
- }
-}
+ ExampleBean eb = new ExampleBean (...);
+ // some other operations...
+ return eb;
+ }
+
+ }
----
Arguments to the `static` factory method are supplied via `` elements,
@@ -1958,43 +1946,42 @@ inline. Spring's XML-based configuration metadata supports sub-element types wit
===== Straight values (primitives, Strings, and so on)
The `value` attribute of the `` element specifies a property or constructor
-argument as a human-readable string representation. <>, JavaBeans `PropertyEditors` are used to convert these string
+argument as a human-readable string representation. Spring's
+<> is used to convert these
values from a `String` to the actual type of the property or argument.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
The following example uses the <> for even more succinct
XML configuration.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
+
-
+
----
The preceding XML is more succinct; however, typos are discovered at runtime rather than
@@ -2005,20 +1992,20 @@ assistance is highly recommended.
You can also configure a `java.util.Properties` instance as:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
- jdbc.driver.className=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mydb
-
-
-
+
+
+
+ jdbc.driver.className=com.mysql.jdbc.Driver
+ jdbc.url=jdbc:mysql://localhost:3306/mydb
+
+
+
----
The Spring container converts the text inside the `` element into a
@@ -2033,29 +2020,29 @@ The `idref` element is simply an error-proof way to pass the __id__ (string valu
a reference) of another bean in the container to a `` or ``
element.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
-
-
+
+
+
+
+
----
The above bean definition snippet is __exactly__ equivalent (at runtime) to the
following snippet:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
----
The first form is preferable to the second, because using the `idref` tag allows the
@@ -2070,18 +2057,18 @@ Additionally, if the referenced bean is in the same XML unit, and the bean name
bean __id__, you can use the `local` attribute, which allows the XML parser itself to
validate the bean id earlier, at XML document parse time.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
-A common place (at least in versions earlier than Spring 2.0) where the element
+A common place (at least in versions earlier than Spring 2.0) where the `` element
brings value is in the configuration of <> in a
-`ProxyFactoryBean` bean definition. Using elements when you specify the
+`ProxyFactoryBean` bean definition. Using `` elements when you specify the
interceptor names prevents you from misspelling an interceptor id.
@@ -2102,10 +2089,10 @@ parent container, regardless of whether it is in the same XML file. The value of
`bean` attribute may be the same as the `id` attribute of the target bean, or as one of
the values in the `name` attribute of the target bean.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
Specifying the target bean through the `local` attribute leverages the ability of the
@@ -2115,10 +2102,10 @@ issues an error if no matching element is found in the same file. As such, using
local variant is the best choice (in order to know about errors as early as possible) if
the target bean is in the same XML file.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
Specifying the target bean through the `parent` attribute creates a reference to a bean
@@ -2129,26 +2116,26 @@ parent container of the current one. You use this bean reference variant mainly
have a hierarchy of containers and you want to wrap an existing bean in a parent
container with a proxy that will have the same name as the parent bean.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- class="org.springframework.aop.framework.ProxyFactoryBean">
-
-
-
-
-
+
+
+ class="org.springframework.aop.framework.ProxyFactoryBean">
+
+
+
+
+
----
@@ -2157,18 +2144,18 @@ container with a proxy that will have the same name as the parent bean.
A `` element inside the `` or `` elements defines a
so-called __inner bean__.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
----
An inner bean definition does not require a defined id or name; the container ignores
@@ -2183,54 +2170,54 @@ In the `
`, ``, ``, and `` elements, you set the prope
and arguments of the Java `Collection` types `List`, `Set`, `Map`, and `Properties`,
respectively.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- administrator@example.org
- support@example.org
- development@example.org
-
-
-
-
-
- a list element followed by a reference
-
-
-
-
-
-
-
-
-
-
- just some string
-
-
-
-
+
+
+
+
+ administrator@example.org
+ support@example.org
+ development@example.org
+
+
+
+
+
+ a list element followed by a reference
+
+
+
+
+
+
+
+
+
+
+ just some string
+
+
+
+
----
__The value of a map key or value, or a set value, can also again be any of the
following elements:__
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-bean | ref | idref | list | set | map | props | value | null
+ bean | ref | idref | list | set | map | props | value | null
----
[[beans-collection-elements-merging]]
====== Collection merging
-As of Spring 2.0, the container supports the __merging__ of collections. An application
+The Spring container also supports the __merging__ of collections. An application
developer can define a parent-style `
`, ``, `` or `` element,
and have child-style `
`, ``, `` or `` elements inherit and
override values from the parent collection. That is, the child collection's values are
@@ -2243,28 +2230,28 @@ with parent and child bean definitions may wish to read the
The following example demonstrates collection merging:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- administrator@example.com
- support@example.com
-
-
-
-
-
-
-
- sales@example.com
- support@example.co.uk
-
-
-
-
+
+
+
+
+ administrator@example.com
+ support@example.com
+
+
+
+
+
+
+
+ sales@example.com
+ support@example.co.uk
+
+
+
+
----
Notice the use of the `merge=true` attribute on the `` element of the
@@ -2273,7 +2260,7 @@ and instantiated by the container, the resulting instance has an `adminEmails`
`Properties` collection that contains the result of the merging of the child's
`adminEmails` collection with the parent's `adminEmails` collection.
-[source]
+[literal]
[subs="verbatim,quotes"]
----
administrator=administrator@example.com
@@ -2300,44 +2287,43 @@ You cannot merge different collection types (such as a `Map` and a `List`), and
do attempt to do so an appropriate `Exception` is thrown. The `merge` attribute must be
specified on the lower, inherited, child definition; specifying the `merge` attribute on
a parent collection definition is redundant and will not result in the desired merging.
-The merging feature is available only in Spring 2.0 and later.
[[beans-collection-elements-strongly-typed]]
-====== Strongly-typed collection (Java 5+ only)
-In Java 5 and later, you can use strongly typed collections (using generic types). That
-is, it is possible to declare a `Collection` type such that it can only contain `String`
-elements (for example). If you are using Spring to dependency-inject a strongly-typed
-`Collection` into a bean, you can take advantage of Spring's type-conversion support
-such that the elements of your strongly-typed `Collection` instances are converted to
-the appropriate type prior to being added to the `Collection`.
+====== Strongly-typed collection
+With the introduction of generic types in Java 5, you can use strongly typed collections.
+That is, it is possible to declare a `Collection` type such that it can only contain
+`String` elements (for example). If you are using Spring to dependency-inject a
+strongly-typed `Collection` into a bean, you can take advantage of Spring's
+type-conversion support such that the elements of your strongly-typed `Collection`
+instances are converted to the appropriate type prior to being added to the `Collection`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class Foo {
+ public class Foo {
- private Map accounts;
+ private Map accounts;
- public void setAccounts(Map accounts) {
- this.accounts = accounts;
- }
-}
+ public void setAccounts(Map accounts) {
+ this.accounts = accounts;
+ }
+ }
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
When the `accounts` property of the `foo` bean is prepared for injection, the generics
@@ -2353,23 +2339,25 @@ Spring treats empty arguments for properties and the like as empty `Strings`. Th
following XML-based configuration metadata snippet sets the email property to the empty
`String` value ("")
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
The preceding example is equivalent to the following Java code:
`exampleBean.setEmail("")`. The `` element handles `null` values. For example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
+
+
----
The above configuration is equivalent to the following Java code:
@@ -2381,30 +2369,30 @@ The above configuration is equivalent to the following Java code:
The p-namespace enables you to use the `bean` element's attributes, instead of nested
`` elements, to describe your property values and/or collaborating beans.
-Spring 2.0 and later supports extensible configuration formats <>, which are based on an XML Schema definition. The `beans` configuration
-format discussed in this chapter is defined in an XML Schema document. However, the
-p-namespace is not defined in an XSD file and exists only in the core of Spring.
+Spring supports extensible configuration formats <>, which are
+based on an XML Schema definition. The `beans` configuration format discussed in this
+chapter is defined in an XML Schema document. However, the p-namespace is not defined in
+an XSD file and exists only in the core of Spring.
The following example shows two XML snippets that resolve to the same result: The first
uses standard XML format and the second uses the p-namespace.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
-
+
+
----
The example shows an attribute in the p-namespace called email in the bean definition.
@@ -2415,29 +2403,29 @@ to the property name.
This next example includes two more bean definitions that both have a reference to
another bean:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
+
+
----
As you can see, this example includes not only a property value using the p-namespace,
@@ -2466,29 +2454,29 @@ then nested `constructor-arg` elements.
Let's review the examples from <> with the `c` namespace:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
+
+
- <-- 'traditional' declaration -->
-
-
-
-
-
+ <-- 'traditional' declaration -->
+
+
+
+
+
- <-- 'c-namespace' declaration -->
-
+ <-- 'c-namespace' declaration -->
+
-
+
----
The `c:` namespace uses the same conventions as the `p:` one (trailing `-ref` for bean
@@ -2500,16 +2488,16 @@ For the rare cases where the constructor argument names are not available (usual
the bytecode was compiled without debugging information), one can use fallback to the
argument indexes:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-<-- 'c-namespace' index declaration -->
-
+ <-- 'c-namespace' index declaration -->
+
----
[NOTE]
====
-Due to the XML grammar, the index notation requires the presence of the leading _____ as
+Due to the XML grammar, the index notation requires the presence of the leading `_` as
XML attribute names cannot start with a number (even though some IDE allow it).
====
@@ -2525,12 +2513,12 @@ You can use compound or nested property names when you set bean properties, as l
all components of the path except the final property name are not `null`. Consider the
following bean definition.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
The `foo` bean has a `fred` property, which has a `bob` property, which has a `sammy`
@@ -2544,7 +2532,7 @@ this to work, the `fred` property of `foo`, and the `bob` property of `fred` mus
==== Using depends-on
If a bean is a dependency of another that usually means that one bean is set as a
-property of another. Typically you accomplish this with the<`
+property of another. Typically you accomplish this with the <`
element>> in XML-based configuration metadata. However, sometimes dependencies between
beans are less direct; for example, a static initializer in a class needs to be
triggered, such as database driver registration. The `depends-on` attribute can
@@ -2552,32 +2540,32 @@ explicitly force one or more beans to be initialized before the bean using this
is initialized. The following example uses the `depends-on` attribute to express a
dependency on a single bean:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
----
To express a dependency on multiple beans, supply a list of bean names as the value of
the `depends-on` attribute, with commas, whitespace and semicolons, used as valid
delimiters:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
-
-
+
+
----
[NOTE]
====
The `depends-on` attribute in the bean definition can specify both an initialization
-time dependency and, in the case of<> beans
+time dependency and, in the case of <> beans
only, a corresponding destroy time dependency. Dependent beans that define a
`depends-on` relationship with a given bean are destroyed first, prior to the given bean
itself being destroyed. Thus `depends-on` can also control shutdown order.
@@ -2599,11 +2587,11 @@ instance when it is first requested, rather than at startup.
In XML, this behavior is controlled by the `lazy-init` attribute on the ``
element; for example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
----
When the preceding configuration is consumed by an `ApplicationContext`, the bean named
@@ -2618,12 +2606,12 @@ is injected into a singleton bean elsewhere that is not lazy-initialized.
You can also control lazy-initialization at the container level by using the
`default-lazy-init` attribute on the `` element; for example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
@@ -2700,7 +2688,7 @@ two bean definitions.
Consider the limitations and disadvantages of autowiring:
* Explicit dependencies in `property` and `constructor-arg` settings always override
- autowiring. You cannot autowire so-called__simple__ properties such as primitives,
+ autowiring. You cannot autowire so-called __simple__ properties such as primitives,
`Strings`, and `Classes` (and arrays of such simple properties). This limitation is
by-design.
* Autowiring is less exact than explicit wiring. Although, as noted in the above table,
@@ -2722,7 +2710,7 @@ In the latter scenario, you have several options:
to `false` as described in the next section.
* Designate a single bean definition as the __primary__ candidate by setting the
`primary` attribute of its `` element to `true`.
-* If you are using Java 5 or later, implement the more fine-grained control available
+* Implement the more fine-grained control available
with annotation-based configuration, as described in <>.
@@ -2737,7 +2725,7 @@ makes that specific bean definition unavailable to the autowiring infrastructure
You can also limit autowire candidates based on pattern-matching against bean names. The
top-level `` element accepts one or more patterns within its
`default-autowire-candidates` attribute. For example, to limit autowire candidate status
-to any bean whose name ends with__Repository,__ provide a value of *Repository. To
+to any bean whose name ends with __Repository,__ provide a value of *Repository. To
provide multiple patterns, define them in a comma-separated list. An explicit value of
`true` or `false` for a bean definitions `autowire-candidate` attribute always takes
precedence, and for such beans, the pattern matching rules do not apply.
@@ -2766,39 +2754,39 @@ and by <> ask
typically new) bean B instance every time bean A needs it. The following is an example
of this approach:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-// a class that uses a stateful Command-style class to perform some processing
-package fiona.apple;
+ // a class that uses a stateful Command-style class to perform some processing
+ package fiona.apple;
-// Spring-API imports
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
+ // Spring-API imports
+ import org.springframework.beans.BeansException;
+ import org.springframework.context.ApplicationContext;
+ import org.springframework.context.ApplicationContextAware;
-public class CommandManager implements ApplicationContextAware {
+ public class CommandManager implements ApplicationContextAware {
- private ApplicationContext applicationContext;
+ private ApplicationContext applicationContext;
- public Object process(Map commandState) {
- // grab a new instance of the appropriate Command
- Command command = createCommand();
- // set the state on the (hopefully brand new) Command instance
- command.setState(commandState);
- return command.execute();
- }
+ public Object process(Map commandState) {
+ // grab a new instance of the appropriate Command
+ Command command = createCommand();
+ // set the state on the (hopefully brand new) Command instance
+ command.setState(commandState);
+ return command.execute();
+ }
- protected Command createCommand() {
- // notice the Spring API dependency!
- return this.applicationContext.getBean("command", Command.class);
- }
+ protected Command createCommand() {
+ // notice the Spring API dependency!
+ return this.applicationContext.getBean("command", Command.class);
+ }
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this.applicationContext = applicationContext;
- }
-}
+ public void setApplicationContext(
+ ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+ }
----
The preceding is not desirable, because the business code is aware of and coupled to the
@@ -2838,53 +2826,53 @@ Spring container will dynamically override the implementation of the `createComm
method. Your `CommandManager` class will not have any Spring dependencies, as can be
seen in the reworked example:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package fiona.apple;
+ package fiona.apple;
-// no more Spring imports!
+ // no more Spring imports!
-public abstract class CommandManager {
+ public abstract class CommandManager {
- public Object process(Object commandState) {
- // grab a new instance of the appropriate Command interface
- Command command = createCommand();
- // set the state on the (hopefully brand new) Command instance
- command.setState(commandState);
- return command.execute();
- }
+ public Object process(Object commandState) {
+ // grab a new instance of the appropriate Command interface
+ Command command = createCommand();
+ // set the state on the (hopefully brand new) Command instance
+ command.setState(commandState);
+ return command.execute();
+ }
- // okay... but where is the implementation of this method?
- protected abstract Command createCommand();
-}
+ // okay... but where is the implementation of this method?
+ protected abstract Command createCommand();
+ }
----
In the client class containing the method to be injected (the `CommandManager` in this
case), the method to be injected requires a signature of the following form:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
- [abstract] theMethodName(no-arguments);
+ [abstract] theMethodName(no-arguments);
----
If the method is `abstract`, the dynamically-generated subclass implements the method.
Otherwise, the dynamically-generated subclass overrides the concrete method defined in
the original class. For example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
----
The bean identified as __commandManager__ calls its own method `createCommand()`
@@ -2895,7 +2883,6 @@ bean is returned each time.
[TIP]
====
-
The interested reader may also find the `ServiceLocatorFactoryBean` (in the
`org.springframework.beans.factory.config` package) to be of use. The approach used in
ServiceLocatorFactoryBean is similar to that of another utility class,
@@ -2915,55 +2902,55 @@ With XML-based configuration metadata, you can use the `replaced-method` element
replace an existing method implementation with another, for a deployed bean. Consider
the following class, with a method computeValue, which we want to override:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MyValueCalculator {
+ public class MyValueCalculator {
-public String computeValue(String input) {
- // some real code...
-}
+ public String computeValue(String input) {
+ // some real code...
+ }
-// some other methods...
+ // some other methods...
-}
+ }
----
A class implementing the `org.springframework.beans.factory.support.MethodReplacer`
interface provides the new method definition.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-/** meant to be used to override the existing computeValue(String)
- implementation in MyValueCalculator
-*/
-public class ReplacementComputeValue implements MethodReplacer {
+ /**
+ * meant to be used to override the existing computeValue(String)
+ * implementation in MyValueCalculator
+ */
+ public class ReplacementComputeValue implements MethodReplacer {
- public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
- // get the input value, work with it, and return a computed result
- String input = (String) args[0];
- ...
- return ...;
- }
-}
+ public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
+ // get the input value, work with it, and return a computed result
+ String input = (String) args[0];
+ ...
+ return ...;
+ }
+ }
----
The bean definition to deploy the original class and specify the method override would
look like this:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
+
+
+ String
+
+
-
-
- String
-
-
-
-
+
----
You can use one or more contained `` elements within the ``
@@ -2973,12 +2960,12 @@ exist within the class. For convenience, the type string for an argument may be
substring of the fully qualified type name. For example, the following all match
`java.lang.String`:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-java.lang.String
- String
- Str
+ java.lang.String
+ String
+ Str
----
Because the number of arguments is often enough to distinguish between each possible
@@ -3012,23 +2999,23 @@ The following scopes are supported out of the box. You can also create
|===
| Scope| Description
-| <>
+| <>
| (Default) Scopes a single bean definition to a single object instance per Spring IoC
container.
-| <>
+| <>
| Scopes a single bean definition to any number of object instances.
-| <>
+| <>
| Scopes a single bean definition to the lifecycle of a single HTTP request; that is,
each HTTP request has its own instance of a bean created off the back of a single bean
definition. Only valid in the context of a web-aware Spring `ApplicationContext`.
-| <>
+| <>
| Scopes a single bean definition to the lifecycle of an HTTP `Session`. Only valid in
the context of a web-aware Spring `ApplicationContext`.
-| <>
+| <>
| Scopes a single bean definition to the lifecycle of a global HTTP `Session`. Typically
only valid when used in a portlet context. Only valid in the context of a web-aware
Spring `ApplicationContext`.
@@ -3038,7 +3025,7 @@ The following scopes are supported out of the box. You can also create
====
As of Spring 3.0, a __thread scope__ is available, but is not registered by default. For
more information, see the documentation for
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/SimpleThreadScope.html[SimpleThreadScope].
+{javadoc-baseurl}/org/springframework/context/support/SimpleThreadScope.html[SimpleThreadScope].
For instructions on how to register this or any other custom scope, see
<>.
====
@@ -3054,27 +3041,27 @@ instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a
singleton, the Spring IoC container creates __exactly one__ instance of the object
defined by that bean definition. This single instance is stored in a cache of such
-singleton beans, and__all subsequent requests and references__ for that named bean
+singleton beans, and __all subsequent requests and references__ for that named bean
return the cached object.
-image::images/singleton.png[]
+image::images/singleton.png[width=400]
Spring's concept of a singleton bean differs from the Singleton pattern as defined in
the Gang of Four (GoF) patterns book. The GoF Singleton hard-codes the scope of an
object such that one __and only one__ instance of a particular class is created __per
ClassLoader__. The scope of the Spring singleton is best described as __per container
and per bean__. This means that if you define one bean for a particular class in a
-single Spring container, then the Spring container creates one__and only one__ instance
+single Spring container, then the Spring container creates one __and only one__ instance
of the class defined by that bean definition. __The singleton scope is the default scope
in Spring__. To define a bean as a singleton in XML, you would write, for example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
+
+
----
@@ -3092,22 +3079,21 @@ The following diagram illustrates the Spring prototype scope. __A data access ob
any conversational state; it was just easier for this author to reuse the core of the
singleton diagram.__
-image::images/prototype.png[]
+image::images/prototype.png[width=400]
The following example defines a bean as a prototype in XML:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
----
In contrast to the other scopes, Spring does not manage the complete lifecycle of a
prototype bean: the container instantiates, configures, and otherwise assembles a
prototype object, and hands it to the client, with no further record of that prototype
-instance. Thus, although__initialization__ lifecycle callback methods are called on all
-objects regardless of scope, in the case of prototypes, configured__destruction__
+instance. Thus, although__ initialization__ lifecycle callback methods are called on all
+objects regardless of scope, in the case of prototypes, configured __destruction__
lifecycle callbacks are __not__ called. The client code must clean up prototype-scoped
objects and release expensive resources that the prototype bean(s) are holding. To get
the Spring container to release resources held by prototype-scoped beans, try using a
@@ -3162,22 +3148,24 @@ setup is necessary: `DispatcherServlet` and `DispatcherPortlet` already expose a
relevant state.
If you use a Servlet 2.4+ web container, with requests processed outside of Spring's
-DispatcherServlet (for example, when using JSF or Struts), you need to add the following
-`javax.servlet.ServletRequestListener` to the declarations in your web applications
-`web.xml` file:
+DispatcherServlet (for example, when using JSF or Struts), you need to register the
+`org.springframework.web.context.request.RequestContextListener` `ServletRequestListener`.
+For Servlet 3.0+, this can done programmatically via the `WebApplicationInitializer`
+interface. Alternatively, or for older containers, add the following declaration to your
+web applications `web.xml` file:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-...
-
-
- org.springframework.web.context.request.RequestContextListener
-
-
-...
-
+
+ ...
+
+
+ org.springframework.web.context.request.RequestContextListener
+
+
+ ...
+
----
If you use an older web container (Servlet 2.3), use the provided `javax.servlet.Filter`
@@ -3187,21 +3175,21 @@ requests outside of Spring's DispatcherServlet on a Servlet 2.3 container. (The
mapping depends on the surrounding web application configuration, so you must change it
as appropriate.)
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-..
-
- requestContextFilter
- org.springframework.web.filter.RequestContextFilter
-
-
- requestContextFilter
- /*
-
-...
-
+
+ ...
+
+ requestContextFilter
+ org.springframework.web.filter.RequestContextFilter
+
+
+ requestContextFilter
+ /*
+
+ ...
+
----
`DispatcherServlet`, `RequestContextListener` and `RequestContextFilter` all do exactly
@@ -3214,10 +3202,10 @@ down the call chain.
===== Request scope
Consider the following bean definition:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
The Spring container creates a new instance of the `LoginAction` bean by using the
@@ -3233,10 +3221,10 @@ bean that is scoped to the request is discarded.
===== Session scope
Consider the following bean definition:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
The Spring container creates a new instance of the `UserPreferences` bean by using the
@@ -3254,10 +3242,10 @@ HTTP `Session` is eventually discarded, the bean that is scoped to that particul
===== Global session scope
Consider the following bean definition:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
The `global session` scope is similar to the standard HTTP `Session` scope
@@ -3291,51 +3279,48 @@ scoped as `singletons` or `prototypes`.
The configuration in the following example is only one line, but it is important to
understand the "why" as well as the "how" behind it.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
----
To create such a proxy, you insert a child `` element into a scoped
-bean definition. See <> and
+bean definition. See <> and
<>.) Why do definitions of beans scoped at the `request`, `session`,
`globalSession` and custom-scope levels require the `` element ?
Let's examine the following singleton bean definition and contrast it with what you need
to define for the aforementioned scopes. (The following `userPreferences` bean
definition as it stands is __incomplete.)__
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
----
In the preceding example, the singleton bean `userManager` is injected with a reference
@@ -3364,15 +3349,15 @@ method invocation onto the retrieved real `UserPreferences` object.
Thus you need the following, correct and complete, configuration when injecting
`request-`, `session-`, and `globalSession-scoped` beans into collaborating objects:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
+
+
+
+
+
+
----
[[beans-factory-scopes-other-injection-proxies]]
@@ -3380,8 +3365,11 @@ Thus you need the following, correct and complete, configuration when injecting
By default, when the Spring container creates a proxy for a bean that is marked up with
the `` element, __a CGLIB-based class proxy is created__.
-__Note: CGLIB proxies only intercept public method calls!__ Do not call non-public
+[NOTE]
+====
+CGLIB proxies only intercept public method calls! Do not call non-public
methods on such a proxy; they will not be delegated to the scoped target object.
+====
Alternatively, you can configure the Spring container to create standard JDK
interface-based proxies for such scoped beans, by specifying `false` for the value of
@@ -3392,16 +3380,16 @@ the scoped bean must implement at least one interface, and __that all__ collabor
into which the scoped bean is injected must reference the bean through one of its
interfaces.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
For more detailed information about choosing class-based or interface-based proxying,
@@ -3411,7 +3399,7 @@ see <>.
[[beans-factory-scopes-custom]]
==== Custom scopes
-As of Spring 2.0, the bean scoping mechanism is extensible. You can define your own
+The bean scoping mechanism is extensible; You can define your own
scopes, or even redefine existing scopes, although the latter is considered bad practice
and you __cannot__ override the built-in `singleton` and `prototype` scopes.
@@ -3422,7 +3410,7 @@ To integrate your custom scope(s) into the Spring container, you need to impleme
`org.springframework.beans.factory.config.Scope` interface, which is described in this
section. For an idea of how to implement your own scopes, see the `Scope`
implementations that are supplied with the Spring Framework itself and the
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/Scope.html[Scope
+{javadoc-baseurl}/org/springframework/beans/factory/config/Scope.html[Scope
Javadoc], which explains the methods you need to implement in more detail.
The `Scope` interface has four methods to get objects from the scope, remove them from
@@ -3433,10 +3421,10 @@ implementation, for example, returns the session-scoped bean (and if it does not
the method returns a new instance of the bean, after having bound it to the session for
future reference).
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Object get(String name, ObjectFactory objectFactory)
+ Object get(String name, ObjectFactory objectFactory)
----
The following method removes the object from the underlying scope. The session scope
@@ -3444,30 +3432,30 @@ implementation for example, removes the session-scoped bean from the underlying
The object should be returned, but you can return null if the object with the specified
name is not found.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Object remove(String name)
+ Object remove(String name)
----
The following method registers the callbacks the scope should execute when it is
destroyed or when the specified object in the scope is destroyed. Refer to the Javadoc
or a Spring scope implementation for more information on destruction callbacks.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-void registerDestructionCallback(String name, Runnable destructionCallback)
+ void registerDestructionCallback(String name, Runnable destructionCallback)
----
The following method obtains the conversation identifier for the underlying scope. This
identifier is different for each scope. For a session scoped implementation, this
identifier can be the session identifier.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-String getConversationId()
+ String getConversationId()
----
@@ -3477,10 +3465,10 @@ After you write and test one or more custom `Scope` implementations, you need to
the Spring container aware of your new scope(s). The following method is the central
method to register a new `Scope` with the Spring container:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-void registerScope(String scopeName, Scope scope);
+ void registerScope(String scopeName, Scope scope);
----
This method is declared on the `ConfigurableBeanFactory` interface, which is available
@@ -3501,57 +3489,57 @@ registered by default. The instructions would be the same for your own custom `S
implementations.
====
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Scope threadScope = new SimpleThreadScope();
-beanFactory.registerScope("thread", threadScope);
+ Scope threadScope = new SimpleThreadScope();
+ beanFactory.registerScope("thread", threadScope);
----
You then create bean definitions that adhere to the scoping rules of your custom `Scope`:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
With a custom `Scope` implementation, you are not limited to programmatic registration
of the scope. You can also do the `Scope` registration declaratively, using the
`CustomScopeConfigurer` class:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
+
----
[NOTE]
@@ -3581,7 +3569,7 @@ to perform certain actions upon initialization and destruction of your beans.
The JSR-250 `@PostConstruct` and `@PreDestroy` annotations are generally considered best
practice for receiving lifecycle callbacks in a modern Spring application. Using these
annotations means that your beans are not coupled to Spring specific interfaces. For
-details see<>.
+details see <>.
If you don't want to use the JSR-250 annotations but you are still looking to remove
coupling consider the use of init-method and destroy-method object definition metadata.
@@ -3606,53 +3594,55 @@ The `org.springframework.beans.factory.InitializingBean` interface allows a bean
perform initialization work after all necessary properties on the bean have been set by
the container. The `InitializingBean` interface specifies a single method:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-void afterPropertiesSet() throws Exception;
+ void afterPropertiesSet() throws Exception;
----
It is recommended that you do not use the `InitializingBean` interface because it
unnecessarily couples the code to Spring. Alternatively, use
-the<> or
+the <> annotation or
specify a POJO initialization method. In the case of XML-based configuration metadata,
you use the `init-method` attribute to specify the name of the method that has a void
no-argument signature. For example, the following definition:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ExampleBean {
+ public class ExampleBean {
- public void init() {
- // do some initialization work
- }
-}
+ public void init() {
+ // do some initialization work
+ }
+
+ }
----
...is exactly the same as...
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class AnotherExampleBean implements InitializingBean {
+ public class AnotherExampleBean implements InitializingBean {
- public void afterPropertiesSet() {
- // do some initialization work
- }
-}
+ public void afterPropertiesSet() {
+ // do some initialization work
+ }
+
+ }
----
but does not couple the code to Spring.
@@ -3664,56 +3654,58 @@ Implementing the `org.springframework.beans.factory.DisposableBean` interface al
bean to get a callback when the container containing it is destroyed. The
`DisposableBean` interface specifies a single method:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-void destroy() throws Exception;
+ void destroy() throws Exception;
----
It is recommended that you do not use the `DisposableBean` callback interface because it
unnecessarily couples the code to Spring. Alternatively, use
-the<> or
+the <> annotation or
specify a generic method that is supported by bean definitions. With XML-based
configuration metadata, you use the `destroy-method` attribute on the ``. For
example, the following definition:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class ExampleBean {
+ public class ExampleBean {
- public void cleanup() {
- // do some destruction work (like releasing pooled connections)
- }
-}
+ public void cleanup() {
+ // do some destruction work (like releasing pooled connections)
+ }
+
+ }
----
-...is exactly the same as...
+is exactly the same as:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class AnotherExampleBean implements DisposableBean {
+ public class AnotherExampleBean implements DisposableBean {
- public void destroy() {
- // do some destruction work (like releasing pooled connections)
- }
-}
+ public void destroy() {
+ // do some destruction work (like releasing pooled connections)
+ }
+
+ }
----
-... but does not couple the code to Spring.
+but does not couple the code to Spring.
[[beans-factory-lifecycle-default-init-destroy-methods]]
@@ -3737,36 +3729,37 @@ Suppose that your initialization callback methods are named `init()` and destroy
callback methods are named `destroy()`. Your class will resemble the class in the
following example.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class DefaultBlogService implements BlogService {
+ public class DefaultBlogService implements BlogService {
- private BlogDao blogDao;
+ private BlogDao blogDao;
- public void setBlogDao(BlogDao blogDao) {
- this.blogDao = blogDao;
- }
+ public void setBlogDao(BlogDao blogDao) {
+ this.blogDao = blogDao;
+ }
- // this is (unsurprisingly) the initialization callback method
- public void init() {
- if (this.blogDao == null) {
- throw new IllegalStateException("The [blogDao] property must be set.");
- }
- }
-}
+ // this is (unsurprisingly) the initialization callback method
+ public void init() {
+ if (this.blogDao == null) {
+ throw new IllegalStateException("The [blogDao] property must be set.");
+ }
+ }
+
+ }
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
+
+
+
-
+
----
The presence of the `default-init-method` attribute on the top-level `` element
@@ -3831,18 +3824,18 @@ Destroy methods are called in the same order:
The `Lifecycle` interface defines the essential methods for any object that has its own
lifecycle requirements (e.g. starts and stops some background process):
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface Lifecycle {
+ public interface Lifecycle {
- void start();
+ void start();
- void stop();
+ void stop();
- boolean isRunning();
+ boolean isRunning();
-}
+ }
----
Any Spring-managed object may implement that interface. Then, when the
@@ -3850,16 +3843,16 @@ ApplicationContext itself starts and stops, it will cascade those calls to all L
implementations defined within that context. It does this by delegating to a
`LifecycleProcessor`:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface LifecycleProcessor extends Lifecycle {
+ public interface LifecycleProcessor extends Lifecycle {
- void onRefresh();
+ void onRefresh();
- void onClose();
+ void onClose();
-}
+ }
----
Notice that the `LifecycleProcessor` is itself an extension of the `Lifecycle`
@@ -3874,22 +3867,26 @@ prior to objects of another type. In those cases, the `SmartLifecycle` interface
another option, namely the `getPhase()` method as defined on its super-interface,
`Phased`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface Phased {
+ public interface Phased {
- int getPhase();
+ int getPhase();
-}
+ }
+----
-public interface SmartLifecycle extends Lifecycle, Phased {
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ public interface SmartLifecycle extends Lifecycle, Phased {
- boolean isAutoStartup();
+ boolean isAutoStartup();
- void stop(Runnable callback);
+ void stop(Runnable callback);
-}
+ }
----
When starting, the objects with the lowest phase start first, and when stopping, the
@@ -3913,13 +3910,13 @@ You can override the default lifecycle processor instance by defining a bean nam
"lifecycleProcessor" within the context. If you only want to modify the timeout, then
defining the following would be sufficient:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
----
As mentioned, the `LifecycleProcessor` interface defines callback methods for the
@@ -3955,44 +3952,47 @@ and implement these destroy callbacks correctly.
To register a shutdown hook, you call the `registerShutdownHook()` method that is
declared on the `AbstractApplicationContext` class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
+ import org.springframework.context.support.AbstractApplicationContext;
+ import org.springframework.context.support.ClassPathXmlApplicationContext;
-public final class Boot {
+ public final class Boot {
- public static void main(final String[] args) throws Exception {
- AbstractApplicationContext ctx
- = new ClassPathXmlApplicationContext(new String []{"beans.xml"});
+ public static void main(final String[] args) throws Exception {
- // add a shutdown hook for the above context...
- ctx.registerShutdownHook();
+ AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String []{"beans.xml"});
- // app runs here...
+ // add a shutdown hook for the above context...
+ ctx.registerShutdownHook();
- // main method exits, hook is called prior to the app shutting down...
- }
-}
+ // app runs here...
+
+ // main method exits, hook is called prior to the app shutting down...
+
+ }
+ }
----
[[beans-factory-aware]]
-==== ApplicationContextAware and `BeanNameAware`
+==== ApplicationContextAware and BeanNameAware
When an `ApplicationContext` creates a class that implements the
`org.springframework.context.ApplicationContextAware` interface, the class is provided
with a reference to that `ApplicationContext`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface ApplicationContextAware {
+ public interface ApplicationContextAware {
- void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
-}
+ void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
+
+ }
----
Thus beans can manipulate programmatically the `ApplicationContext` that created them,
@@ -4021,17 +4021,18 @@ When an ApplicationContext creates a class that implements the
`org.springframework.beans.factory.BeanNameAware` interface, the class is provided with
a reference to the name defined in its associated object definition.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface BeanNameAware {
+ public interface BeanNameAware {
- void setBeanName(string name) throws BeansException;
-}
+ void setBeanName(string name) throws BeansException;
+
+ }
----
The callback is invoked after population of normal bean properties but before an
-initialization callback such as `InitializingBean` s __afterPropertiesSet__ or a custom
+initialization callback such as `InitializingBean` __afterPropertiesSet__ or a custom
init-method.
@@ -4052,19 +4053,19 @@ dependency type:
| `ApplicationContextAware`
| Declaring `ApplicationContext`
-a| <>
+| <>
| `ApplicationEventPublisherAware`
| Event publisher of the enclosing `ApplicationContext`
-a| <>
+| <>
| `BeanClassLoaderAware`
| Class loader used to load the bean classes.
-a| <>
+| <>
| `BeanFactoryAware`
| Declaring `BeanFactory`
-a| <>
+| <>
| `BeanNameAware`
| Name of the declaring bean
@@ -4136,23 +4137,21 @@ like the `ClassPathXmlApplicationContext`. When you use XML-based configuration
metadata, you indicate a child bean definition by using the `parent` attribute,
specifying the parent bean as the value of this attribute.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
----
A child bean definition uses the bean class from the parent definition if none is
@@ -4171,19 +4170,19 @@ The preceding example explicitly marks the parent bean definition as abstract by
the `abstract` attribute. If the parent definition does not specify a class, explicitly
marking the parent bean definition as `abstract` is required, as follows:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
----
The parent bean cannot be instantiated on its own because it is incomplete, and it is
@@ -4278,9 +4277,9 @@ While the recommended approach for `BeanPostProcessor` registration is through
register them __programmatically__ against a `ConfigurableBeanFactory` using the
`addBeanPostProcessor` method. This can be useful when needing to evaluate conditional
logic before registration, or even for copying bean post processors across contexts in a
-hierarchy. Note however that `BeanPostProcessors` added programmatically __do not
+hierarchy. Note however that `BeanPostProcessors` added programmatically __do not
respect the `Ordered` interface__. Here it is the __order of registration__ that
-dictates the order of execution. Note also that `BeanPostProcessors` registered
+dictates the order of execution. Note also that `BeanPostProcessors` registered
programmatically are always processed before those registered through auto-detection,
regardless of any explicit ordering.
====
@@ -4304,7 +4303,7 @@ eligible for getting processed by all BeanPostProcessor interfaces (for example:
eligible for auto-proxying)__".
Note that if you have beans wired into your `BeanPostProcessor` using autowiring or
-`@Resource` (which may fall back to autowiring), Spring might access unexpected beans
+`@Resource` (which may fall back to autowiring), Spring might access unexpected beans
when searching for type-matching dependency candidates, and therefore make them
ineligible for auto-proxying or other kinds of bean post-processing. For example, if you
have a dependency annotated with `@Resource` where the field/setter name does not
@@ -4325,84 +4324,86 @@ it is created by the container and prints the resulting string to the system con
Find below the custom `BeanPostProcessor` implementation class definition:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package scripting;
+ package scripting;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.beans.BeansException;
+ import org.springframework.beans.factory.config.BeanPostProcessor;
+ import org.springframework.beans.BeansException;
-public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
+ public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
- // simply return the instantiated bean as-is
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException {
- return bean; // we could potentially return any object reference here...
- }
+ // simply return the instantiated bean as-is
+ public Object postProcessBeforeInitialization(Object bean,
+ String beanName) throws BeansException {
+ return bean; // we could potentially return any object reference here...
+ }
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- System.out.println("Bean '" + beanName + "' created : " + bean.toString());
- return bean;
- }
-}
+ public Object postProcessAfterInitialization(Object bean,
+ String beanName) throws BeansException {
+ System.out.println("Bean '" + beanName + "' created : " + bean.toString());
+ return bean;
+ }
+
+ }
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
+
----
Notice how the `InstantiationTracingBeanPostProcessor` is simply defined. It does not
even have a name, and because it is a bean it can be dependency-injected just like any
other bean. (The preceding configuration also defines a bean that is backed by a Groovy
-script. The Spring 2.0 dynamic language support is detailed in the chapter entitled
+script. The Spring dynamic language support is detailed in the chapter entitled
<>.)
The following simple Java application executes the preceding code and configuration:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.scripting.Messenger;
+ import org.springframework.context.ApplicationContext;
+ import org.springframework.context.support.ClassPathXmlApplicationContext;
+ import org.springframework.scripting.Messenger;
-public final class Boot {
+ public final class Boot {
- public static void main(final String[] args) throws Exception {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
- Messenger messenger = (Messenger) ctx.getBean("messenger");
- System.out.println(messenger);
- }
-}
+ public static void main(final String[] args) throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+ System.out.println(messenger);
+ }
+
+ }
----
The output of the preceding application resembles the following:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
@@ -4428,9 +4429,9 @@ actually (configured to be) dependency-injected with a value.
The next extension point that we will look at is the
`org.springframework.beans.factory.config.BeanFactoryPostProcessor`. The semantics of
this interface are similar to those of the `BeanPostProcessor`, with one major
-difference: `BeanFactoryPostProcessor` s operate on the __bean configuration metadata__;
-that is, the Spring IoC container allows `BeanFactoryPostProcessors` to read the
-configuration metadata and potentially change it__before__ the container instantiates
+difference: `BeanFactoryPostProcessor` operates on the __bean configuration metadata__;
+that is, the Spring IoC container allows a `BeanFactoryPostProcessor` to read the
+configuration metadata and potentially change it __before__ the container instantiates
any beans other than `BeanFactoryPostProcessors`.
You can configure multiple `BeanFactoryPostProcessors`, and you can control the order in
@@ -4495,28 +4496,28 @@ Consider the following XML-based configuration metadata fragment, where a `DataS
with placeholder values is defined. The example shows properties configured from an
external `Properties` file. At runtime, a `PropertyPlaceholderConfigurer` is applied to
the metadata that will replace some properties of the DataSource. The values to replace
-are specified as __placeholders__ of the form ${property-name} which follows the Ant /
+are specified as __placeholders__ of the form `${property-name}` which follows the Ant /
log4j / JSP EL style.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
----
The actual values come from another file in the standard Java `Properties` format:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
jdbc.driverClassName=org.hsqldb.jdbcDriver
@@ -4535,10 +4536,10 @@ With the `context` namespace introduced in Spring 2.5, it is possible to configu
property placeholders with a dedicated configuration element. One or more locations can
be provided as a comma-separated list in the `location` attribute.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
The `PropertyPlaceholderConfigurer` not only looks for properties in the `Properties`
@@ -4562,19 +4563,19 @@ You can use the `PropertyPlaceholderConfigurer` to substitute class names, which
sometimes useful when you have to pick a particular implementation class at runtime. For
example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
- classpath:com/foo/strategy.properties
-
-
- custom.strategy.class=com.foo.DefaultStrategy
-
-
+
+
+ classpath:com/foo/strategy.properties
+
+
+ custom.strategy.class=com.foo.DefaultStrategy
+
+
-
+
----
If the class cannot be resolved at runtime to a valid class, resolution of the bean
@@ -4599,7 +4600,7 @@ values for the same bean property, the last one wins, due to the overriding mech
Properties file configuration lines take this format:
-[source,java]
+[literal]
[subs="verbatim,quotes"]
----
beanName.property=value
@@ -4607,7 +4608,7 @@ beanName.property=value
For example:
-[source,java]
+[literal]
[subs="verbatim,quotes"]
----
dataSource.driverClassName=com.mysql.jdbc.Driver
@@ -4621,7 +4622,7 @@ Compound property names are also supported, as long as every component of the pa
except the final property being overridden is already non-null (presumably initialized
by the constructors). In this example...
-[source]
+[literal]
[subs="verbatim,quotes"]
----
foo.fred.bob.sammy=123
@@ -4640,10 +4641,10 @@ definition specifies a bean reference.
With the `context` namespace introduced in Spring 2.5, it is possible to configure
property overriding with a dedicated configuration element:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
@@ -4685,13 +4686,14 @@ product of the `FactoryBean`; whereas, invoking `getBean("&myBean")` returns the
[[beans-annotation-config]]
-=== Annotation-based container configurationAre annotations better than XML for configuring Spring?
-****
+=== Annotation-based container configuration
+.Are annotations better than XML for configuring Spring?
+****
The introduction of annotation-based configurations raised the question of whether this
approach is 'better' than XML. The short answer is __it depends__. The long answer is
that each approach has its pros and cons, and usually it is up to the developer to
-decide which strategy suits her better. Due to the way they are defined, annotations
+decide which strategy suits them better. Due to the way they are defined, annotations
provide a lot of context in their declaration, leading to shorter and more concise
configuration. However, XML excels at wiring up components without touching their source
code or recompiling them. Some developers prefer having the wiring close to the source
@@ -4703,7 +4705,6 @@ It's worth pointing out that through its <> option, Sprin
annotations to be used in a non-invasive way, without touching the target components
source code and that in terms of tooling, all configuration styles are supported by the
http://www.springsource.com/products/sts[SpringSource Tool Suite].
-
****
An alternative to XML setups is provided by annotation-based configuration which rely on
@@ -4731,29 +4732,29 @@ As always, you can register them as individual bean definitions, but they can al
implicitly registered by including the following tag in an XML-based Spring
configuration (notice the inclusion of the `context` namespace):
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
+
----
(The implicitly registered post-processors include
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`],
- http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`],
- http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`],
+{javadoc-baseurl}/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`],
+ {javadoc-baseurl}/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`],
+ {javadoc-baseurl}/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`],
as well as the aforementioned
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html[`RequiredAnnotationBeanPostProcessor`].)
+{javadoc-baseurl}/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html[`RequiredAnnotationBeanPostProcessor`].)
[NOTE]
====
@@ -4767,25 +4768,26 @@ it only checks for `@Autowired` beans in your controllers, and not your services
[[beans-required-annotation]]
-==== @Required
+==== @Required
The `@Required` annotation applies to bean property setter methods, as in the following
example:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Required
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
+ @Required
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
- // ...
-}
+ // ...
+
+ }
----
This annotation simply indicates that the affected bean property must be populated at
@@ -4799,24 +4801,25 @@ references and values even when you use the class outside of a container.
[[beans-autowired-annotation]]
-==== @Autowired
+==== @Autowired
As expected, you can apply the `@Autowired` annotation to "traditional" setter methods:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Autowired
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
+ @Autowired
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
- // ...
-}
+ // ...
+
+ }
----
[NOTE]
@@ -4828,119 +4831,133 @@ the examples below. See <> for more details
You can also apply the annotation to methods with arbitrary names and/or multiple
arguments:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- private MovieCatalog movieCatalog;
+ private MovieCatalog movieCatalog;
- private CustomerPreferenceDao customerPreferenceDao;
+ private CustomerPreferenceDao customerPreferenceDao;
- @Autowired
- public void prepare(MovieCatalog movieCatalog,
- CustomerPreferenceDao customerPreferenceDao) {
- this.movieCatalog = movieCatalog;
- this.customerPreferenceDao = customerPreferenceDao;
- }
+ @Autowired
+ public void prepare(MovieCatalog movieCatalog,
+ CustomerPreferenceDao customerPreferenceDao) {
+ this.movieCatalog = movieCatalog;
+ this.customerPreferenceDao = customerPreferenceDao;
+ }
- // ...
-}
+ // ...
+
+ }
----
You can apply `@Autowired` to constructors and fields:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- private MovieCatalog movieCatalog;
+ @Autowired
+ private MovieCatalog movieCatalog;
- private CustomerPreferenceDao customerPreferenceDao;
+ private CustomerPreferenceDao customerPreferenceDao;
- @Autowired
- public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
- this.customerPreferenceDao = customerPreferenceDao;
- }
+ @Autowired
+ public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
+ this.customerPreferenceDao = customerPreferenceDao;
+ }
- // ...
-}
+ // ...
+
+ }
----
It is also possible to provide __all__ beans of a particular type from the
`ApplicationContext` by adding the annotation to a field or method that expects an array
of that type:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- private MovieCatalog[] movieCatalogs;
+ @Autowired
+ private MovieCatalog[] movieCatalogs;
- // ...
-}
+ // ...
+
+ }
----
The same applies for typed collections:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- private Set movieCatalogs;
+ private Set movieCatalogs;
- @Autowired
- public void setMovieCatalogs(Set movieCatalogs) {
- this.movieCatalogs = movieCatalogs;
- }
+ @Autowired
+ public void setMovieCatalogs(Set movieCatalogs) {
+ this.movieCatalogs = movieCatalogs;
+ }
- // ...
-}
+ // ...
+
+ }
----
+[TIP]
+====
+Your beans can implement the `org.springframework.core.Ordered` interface or use the
+the `@Ordered` annotation if you want items in the array or list to be sorted into a
+specific order.
+====
+
+
Even typed Maps can be autowired as long as the expected key type is `String`. The Map
values will contain all beans of the expected type, and the keys will contain the
corresponding bean names:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- private Map movieCatalogs;
+ private Map movieCatalogs;
- @Autowired
- public void setMovieCatalogs(Map movieCatalogs) {
- this.movieCatalogs = movieCatalogs;
- }
+ @Autowired
+ public void setMovieCatalogs(Map movieCatalogs) {
+ this.movieCatalogs = movieCatalogs;
+ }
- // ...
-}
+ // ...
+
+ }
----
By default, the autowiring fails whenever __zero__ candidate beans are available; the
default behavior is to treat annotated methods, constructors, and fields as
-indicating__required__ dependencies. This behavior can be changed as demonstrated below.
+indicating __required__ dependencies. This behavior can be changed as demonstrated below.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Autowired(required=false)
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
+ @Autowired(required=false)
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
- // ...
-}
+ // ...
+
+ }
----
[NOTE]
@@ -4963,19 +4980,20 @@ dependencies: `BeanFactory`, `ApplicationContext`, `Environment`, `ResourceLoade
interfaces, such as `ConfigurableApplicationContext` or `ResourcePatternResolver`, are
automatically resolved, with no special setup necessary.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- private ApplicationContext context;
+ @Autowired
+ private ApplicationContext context;
- public MovieRecommender() {
- }
+ public MovieRecommender() {
+ }
- // ...
-}
+ // ...
+
+ }
----
[NOTE]
@@ -4996,74 +5014,76 @@ Spring's `@Qualifier` annotation. You can associate qualifier values with specif
arguments, narrowing the set of type matches so that a specific bean is chosen for each
argument. In the simplest case, this can be a plain descriptive value:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- **@Qualifier("main")**
- private MovieCatalog movieCatalog;
+ @Autowired
+ **@Qualifier("main")**
+ private MovieCatalog movieCatalog;
- // ...
-}
+ // ...
+
+ }
----
The `@Qualifier` annotation can also be specified on individual constructor arguments or
method parameters:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- private MovieCatalog movieCatalog;
+ private MovieCatalog movieCatalog;
- private CustomerPreferenceDao customerPreferenceDao;
+ private CustomerPreferenceDao customerPreferenceDao;
- @Autowired
- public void prepare(**@Qualifier("main")**MovieCatalog movieCatalog,
- CustomerPreferenceDao customerPreferenceDao) {
- this.movieCatalog = movieCatalog;
- this.customerPreferenceDao = customerPreferenceDao;
- }
+ @Autowired
+ public void prepare(**@Qualifier("main")**MovieCatalog movieCatalog,
+ CustomerPreferenceDao customerPreferenceDao) {
+ this.movieCatalog = movieCatalog;
+ this.customerPreferenceDao = customerPreferenceDao;
+ }
- // ...
-}
+ // ...
+
+ }
----
The corresponding bean definitions appear as follows. The bean with qualifier value
"main" is wired with the constructor argument that is qualified with the same value.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
- ****
+
+ ****
-
-
+
+
-
- ****
+
+ ****
-
-
+
+
-
+
-
+
----
For a fallback match, the bean name is considered a default qualifier value. Thus you
@@ -5108,37 +5128,38 @@ multi-argument method.
You can create your own custom qualifier annotations. Simply define an annotation and
provide the `@Qualifier` annotation within your definition:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Target({ElementType.FIELD, ElementType.PARAMETER})
-@Retention(RetentionPolicy.RUNTIME)
-**@Qualifier**
-public @interface Genre {
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+ @Retention(RetentionPolicy.RUNTIME)
+ **@Qualifier**
+ public @interface Genre {
- String value();
-}
+ String value();
+ }
----
Then you can provide the custom qualifier on autowired fields and parameters:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- **@Genre("Action")**
- private MovieCatalog actionCatalog;
- private MovieCatalog comedyCatalog;
+ @Autowired
+ **@Genre("Action")**
+ private MovieCatalog actionCatalog;
+ private MovieCatalog comedyCatalog;
- @Autowired
- public void setComedyCatalog(**@Genre("Comedy")** MovieCatalog comedyCatalog) {
- this.comedyCatalog = comedyCatalog;
- }
+ @Autowired
+ public void setComedyCatalog(**@Genre("Comedy")** MovieCatalog comedyCatalog) {
+ this.comedyCatalog = comedyCatalog;
+ }
- // ...
-}
+ // ...
+
+ }
----
Next, provide the information for the candidate bean definitions. You can add
@@ -5148,33 +5169,33 @@ fully-qualified class name of the annotation. Or, as a convenience if no risk of
conflicting names exists, you can use the short class name. Both approaches are
demonstrated in the following example.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
- ****
-
-
+
+ ****
+
+
-
- **_**
-
-
+
+ **_**
+
+
-
+
-
+
----
In <>, you will see an annotation-based alternative to
@@ -5186,41 +5207,42 @@ several different types of dependencies. For example, you may provide an __offli
catalog that would be searched when no Internet connection is available. First define
the simple annotation:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Target({ElementType.FIELD, ElementType.PARAMETER})
-@Retention(RetentionPolicy.RUNTIME)
-@Qualifier
-public @interface Offline {
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Qualifier
+ public @interface Offline {
-}
+ }
----
Then add the annotation to the field or property to be autowired:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- **@Offline**
- private MovieCatalog offlineCatalog;
+ @Autowired
+ **@Offline**
+ private MovieCatalog offlineCatalog;
- // ...
-}
+ // ...
+
+ }
----
Now the bean definition only needs a qualifier `type`:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- ****
-
-
+
+ ****
+
+
----
You can also define custom qualifier annotations that accept named attributes in
@@ -5229,57 +5251,58 @@ then specified on a field or parameter to be autowired, a bean definition must m
__all__ such attribute values to be considered an autowire candidate. As an example,
consider the following annotation definition:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Target({ElementType.FIELD, ElementType.PARAMETER})
-@Retention(RetentionPolicy.RUNTIME)
-@Qualifier
-public @interface MovieQualifier {
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Qualifier
+ public @interface MovieQualifier {
- String genre();
+ String genre();
- Format format();
-}
+ Format format();
+
+ }
----
In this case `Format` is an enum:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public enum Format {
-
- VHS, DVD, BLURAY
-}
+ public enum Format {
+ VHS, DVD, BLURAY
+ }
----
The fields to be autowired are annotated with the custom qualifier and include values
for both attributes: `genre` and `format`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Autowired
- @MovieQualifier(format=Format.VHS, genre="Action")
- private MovieCatalog actionVhsCatalog;
+ @Autowired
+ @MovieQualifier(format=Format.VHS, genre="Action")
+ private MovieCatalog actionVhsCatalog;
- @Autowired
- @MovieQualifier(format=Format.VHS, genre="Comedy")
- private MovieCatalog comedyVhsCatalog;
+ @Autowired
+ @MovieQualifier(format=Format.VHS, genre="Comedy")
+ private MovieCatalog comedyVhsCatalog;
- @Autowired
- @MovieQualifier(format=Format.DVD, genre="Action")
- private MovieCatalog actionDvdCatalog;
+ @Autowired
+ @MovieQualifier(format=Format.DVD, genre="Action")
+ private MovieCatalog actionDvdCatalog;
- @Autowired
- @MovieQualifier(format=Format.BLURAY, genre="Comedy")
- private MovieCatalog comedyBluRayCatalog;
+ @Autowired
+ @MovieQualifier(format=Format.BLURAY, genre="Comedy")
+ private MovieCatalog comedyBluRayCatalog;
- // ...
-}
+ // ...
+
+ }
----
Finally, the bean definitions should contain matching qualifier values. This example
@@ -5289,90 +5312,142 @@ precedence, but the autowiring mechanism falls back on the values provided withi
`` tags if no such qualifier is present, as in the last two bean definitions in
the following example.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
----
+[[beans-generics-as-qualifiers]]
+==== Using generics as autowiring qualifiers
+In addition to the `@Qualifier` annotation, it is also possible to use Java generic types
+as an implicit form of qualification. For example, suppose you have the following
+configuration:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Configuration
+ public class MyConfiguration {
+
+ @Bean
+ public StringStore stringStore() {
+ return new StringStore();
+ }
+
+ @Bean
+ public IntegerStore integerStore() {
+ return new IntegerStore();
+ }
+
+ }
+----
+
+Assuming that beans above implement a generic interface, i.e. `Store` and
+`Store`, you can `@Autowire` the `Store` interface and the __generic__ will
+be used as a qualifier:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Autowired
+ private Store s1; // qualifier, injects the stringStore bean
+
+ @Autowired
+ private Store s2; // qualifier, injects the integerStore bean
+----
+
+Generic qualifiers also apply when autowiring Lists, Maps and Arrays:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ // Inject all Store beans as long as they have an generic
+ // Store beans will not appear in this list
+ @Autowired
+ private List> s;
+----
+
+
+
+
[[beans-custom-autowire-configurer]]
-==== CustomAutowireConfigurer
+==== CustomAutowireConfigurer
The
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html[`CustomAutowireConfigurer`]
+{javadoc-baseurl}/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html[`CustomAutowireConfigurer`]
is a `BeanFactoryPostProcessor` that enables you to register your own custom qualifier
annotation types even if they are not annotated with Spring's `@Qualifier` annotation.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
- example.CustomQualifier
-
-
-
+
+
+
+ example.CustomQualifier
+
+
+
----
-The particular implementation of `AutowireCandidateResolver` that is activated for the
-application context depends on the Java version. In versions earlier than Java 5, the
-qualifier annotations are not supported, and therefore autowire candidates are solely
-determined by the `autowire-candidate` value of each bean definition as well as by any
-`default-autowire-candidates` pattern(s) available on the `` element. In Java 5
-or later, the presence of `@Qualifier` annotations and any custom annotations registered
-with the `CustomAutowireConfigurer` will also play a role.
+The `AutowireCandidateResolver` determines autowire candidates by:
-Regardless of the Java version, when multiple beans qualify as autowire candidates, the
-determination of a "primary" candidate is the same: if exactly one bean definition among
-the candidates has a `primary` attribute set to `true`, it will be selected.
+* the `autowire-candidate` value of each bean definition
+* any `default-autowire-candidates` pattern(s) available on the `` element
+* the presence of `@Qualifier` annotations and any custom annotations registered
+with the `CustomAutowireConfigurer`
+
+When multiple beans qualify as autowire candidates, the determination of a "primary" is
+the following: if exactly one bean definition among the candidates has a `primary`
+attribute set to `true`, it will be selected.
[[beans-resource-annotation]]
-==== @Resource
+==== @Resource
Spring also supports injection using the JSR-250 `@Resource` annotation on fields or
bean property setter methods. This is a common pattern in Java EE 5 and 6, for example
@@ -5383,18 +5458,19 @@ Spring-managed objects as well.
bean name to be injected. In other words, it follows __by-name__ semantics, as
demonstrated in this example:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- **@Resource(name="myMovieFinder")**
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
-}
+ **@Resource(name="myMovieFinder")**
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ }
----
If no name is specified explicitly, the default name is derived from the field name or
@@ -5402,18 +5478,19 @@ setter method. In case of a field, it takes the field name; in case of a setter
it takes the bean property name. So the following example is going to have the bean with
name "movieFinder" injected into its setter method:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- **@Resource**
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
-}
+ **@Resource**
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ }
----
[NOTE]
@@ -5421,7 +5498,7 @@ public class SimpleMovieLister {
The name provided with the annotation is resolved as a bean name by the
`ApplicationContext` of which the `CommonAnnotationBeanPostProcessor` is aware. The
names can be resolved through JNDI if you configure Spring's
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jndi/support/SimpleJndiBeanFactory.html[`SimpleJndiBeanFactory`]
+{javadoc-baseurl}/org/springframework/jndi/support/SimpleJndiBeanFactory.html[`SimpleJndiBeanFactory`]
explicitly. However, it is recommended that you rely on the default behavior and simply
use Spring's JNDI lookup capabilities to preserve the level of indirection.
====
@@ -5437,28 +5514,29 @@ named customerPreferenceDao, then falls back to a primary type match for the typ
`CustomerPreferenceDao`. The "context" field is injected based on the known resolvable
dependency type `ApplicationContext`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class MovieRecommender {
+ public class MovieRecommender {
- @Resource
- private CustomerPreferenceDao customerPreferenceDao;
+ @Resource
+ private CustomerPreferenceDao customerPreferenceDao;
- @Resource
- private ApplicationContext context;
+ @Resource
+ private ApplicationContext context;
- public MovieRecommender() {
- }
+ public MovieRecommender() {
+ }
- // ...
-}
+ // ...
+
+ }
----
[[beans-postconstruct-and-predestroy-annotations]]
-==== @PostConstruct and `@PreDestroy`
+==== @PostConstruct and @PreDestroy
The `CommonAnnotationBeanPostProcessor` not only recognizes the `@Resource` annotation
but also the JSR-250 __lifecycle__ annotations. Introduced in Spring 2.5, the support
@@ -5471,21 +5549,22 @@ point in the lifecycle as the corresponding Spring lifecycle interface method or
explicitly declared callback method. In the example below, the cache will be
pre-populated upon initialization and cleared upon destruction.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class CachingMovieLister {
+ public class CachingMovieLister {
- @PostConstruct
- public void populateMovieCache() {
- // populates the movie cache upon initialization...
- }
+ @PostConstruct
+ public void populateMovieCache() {
+ // populates the movie cache upon initialization...
+ }
- @PreDestroy
- public void clearMovieCache() {
- // clears the movie cache upon destruction...
- }
-}
+ @PreDestroy
+ public void clearMovieCache() {
+ // clears the movie cache upon destruction...
+ }
+
+ }
----
[NOTE]
@@ -5523,14 +5602,14 @@ than using the traditional XML files. Take a look at the `@Configuration`, `@Bea
[[beans-stereotype-annotations]]
-==== @Component and further stereotype annotations
+==== @Component and further stereotype annotations
-In Spring 2.0 and later, the `@Repository` annotation is a marker for any class that
-fulfills the role or __stereotype__ (also known as Data Access Object or DAO) of a
-repository. Among the uses of this marker is the automatic translation of exceptions as
-described in <>.
+The `@Repository` annotation is a marker for any class that fulfills the role or
+__stereotype__ (also known as Data Access Object or DAO) of a repository. Among the uses
+of this marker is the automatic translation of exceptions as described in
+<>.
-Spring 2.5 introduces further stereotype annotations: `@Component`, `@Service`, and
+Spring provides further stereotype annotations: `@Component`, `@Service`, and
`@Controller`. `@Component` is a generic stereotype for any Spring-managed component.
`@Repository`, `@Service`, and `@Controller` are specializations of `@Component` for
more specific use cases, for example, in the persistence, service, and presentation
@@ -5546,34 +5625,84 @@ supported as a marker for automatic exception translation in your persistence la
+[[beans-meta-annotations]]
+==== Meta-annotations
+Many of the annotations provided by Spring can be used as "meta-annotations" in
+your own code. A meta-annotation is simply an annotation, that can be applied to another
+annotation. For example, The `@Service` annotation mentioned above is meta-annotated with
+with `@Component`:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Target({ElementType.TYPE})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ **@Component** // Spring will see this and treat @Service in the same way as @Component
+ public @interface Service {
+
+ // ....
+
+ }
+----
+
+Meta-annotations can also be combined together to create __composed annotations__. For
+example, the `@RestController` annotation from Spring MVC is __composed__ of
+`@Controller` and `@ResponseBody`.
+
+With the exception of `value()`, meta-annotated types may redeclare attributes from the
+source annotation to allow user customization. This can be particularly useful when you
+want to only expose a subset of the source annotation attributes. For example, here is a
+custom `@Scope` annotation that defines `session` scope, but still allows customization
+of the `proxyMode`.
+
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Target({ElementType.TYPE})
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ **@Scope("session")**
+ public @interface SessionScope {
+
+ ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT
+
+ }
+----
+
+
+
+
[[beans-scanning-autodetection]]
==== Automatically detecting classes and registering bean definitions
Spring can automatically detect stereotyped classes and register corresponding
`BeanDefinition` s with the `ApplicationContext`. For example, the following two classes
are eligible for such autodetection:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Service
-public class SimpleMovieLister {
+ @Service
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Autowired
- public SimpleMovieLister(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
-}
+ @Autowired
+ public SimpleMovieLister(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Repository
-public class JpaMovieFinder implements MovieFinder {
- // implementation elided for clarity
-}
+ @Repository
+ public class JpaMovieFinder implements MovieFinder {
+ // implementation elided for clarity
+ }
----
To autodetect these classes and register the corresponding beans, you need to include
@@ -5581,21 +5710,21 @@ the following element in XML, where the base-package element is a common parent
for the two classes. (Alternatively, you can specify a comma-separated list that
includes the parent package of each class.)
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
+
+
-
+
-
+
----
[TIP]
@@ -5665,18 +5794,17 @@ and `expression` attributes. The following table describes the filtering options
The following example shows the XML configuration ignoring all `@Repository` annotations
and using "stub" repositories instead.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
-
+
+
+
+
+
+
----
[NOTE]
@@ -5695,21 +5823,23 @@ Spring components can also contribute bean definition metadata to the container.
this with the same `@Bean` annotation used to define bean metadata within
`@Configuration` annotated classes. Here is a simple example:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Component
-public class FactoryMethodComponent {
+ @Component
+ public class FactoryMethodComponent {
- @Bean @Qualifier("public")
- public TestBean publicInstance() {
- return new TestBean("publicInstance");
- }
+ @Bean
+ @Qualifier("public")
+ public TestBean publicInstance() {
+ return new TestBean("publicInstance");
+ }
- public void doWork() {
- // Component method implementation omitted
- }
-}
+ public void doWork() {
+ // Component method implementation omitted
+ }
+
+ }
----
This class is a Spring component that has application-specific code contained in its
@@ -5717,45 +5847,57 @@ This class is a Spring component that has application-specific code contained in
method referring to the method `publicInstance()`. The `@Bean` annotation identifies the
factory method and other bean definition properties, such as a qualifier value through
the `@Qualifier` annotation. Other method level annotations that can be specified are
-`@Scope`, `@Lazy`, and custom qualifier annotations. Autowired fields and methods are
-supported as previously discussed, with additional support for autowiring of `@Bean`
-methods:
+`@Scope`, `@Lazy`, and custom qualifier annotations.
-[source,java]
+[TIP]
+====
+In addition to its role for component initialization, the `@Lazy` annotation may also be
+placed on injection points marked with `@Autowired` or `@Inject`. In this context, it
+leads to the injection of a lazy-resolution proxy.
+====
+
+Autowired fields and methods are supported as previously discussed, with additional
+support for autowiring of `@Bean` methods:
+
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Component
-public class FactoryMethodComponent {
+ @Component
+ public class FactoryMethodComponent {
- private static int i;
+ private static int i;
- @Bean @Qualifier("public")
- public TestBean publicInstance() {
- return new TestBean("publicInstance");
- }
+ @Bean
+ @Qualifier("public")
+ public TestBean publicInstance() {
+ return new TestBean("publicInstance");
+ }
- // use of a custom qualifier and autowiring of method parameters
+ // use of a custom qualifier and autowiring of method parameters
- @Bean
- protected TestBean protectedInstance(@Qualifier("public") TestBean spouse,
- @Value("#{privateInstance.age}") String country) {
- TestBean tb = new TestBean("protectedInstance", 1);
- tb.setSpouse(tb);
- tb.setCountry(country);
- return tb;
- }
+ @Bean
+ protected TestBean protectedInstance(
+ @Qualifier("public") TestBean spouse,
+ @Value("#{privateInstance.age}") String country) {
+ TestBean tb = new TestBean("protectedInstance", 1);
+ tb.setSpouse(tb);
+ tb.setCountry(country);
+ return tb;
+ }
- @Bean @Scope(BeanDefinition.SCOPE_SINGLETON)
- private TestBean privateInstance() {
- return new TestBean("privateInstance", i++);
- }
+ @Bean
+ @Scope(BeanDefinition.SCOPE_SINGLETON)
+ private TestBean privateInstance() {
+ return new TestBean("privateInstance", i++);
+ }
- @Bean @Scope(value = WebApplicationContext.SCOPE_SESSION,
- proxyMode = ScopedProxyMode.TARGET_CLASS)
- public TestBean requestScopedInstance() {
- return new TestBean("requestScopedInstance", 3);
- }
-}
+ @Bean
+ @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
+ public TestBean requestScopedInstance() {
+ return new TestBean("requestScopedInstance", 3);
+ }
+
+ }
----
The example autowires the `String` method parameter `country` to the value of the `Age`
@@ -5769,7 +5911,7 @@ counterparts inside a Spring `@Configuration` class. The difference is that `@Co
classes are not enhanced with CGLIB to intercept the invocation of methods and fields.
CGLIB proxying is the means by which invoking methods or fields within `@Configuration`
classes `@Bean` methods create bean metadata references to collaborating objects.
-Methods are__not__ invoked with normal Java semantics. In contrast, calling a method or
+Methods are __not__ invoked with normal Java semantics. In contrast, calling a method or
field within a `@Component` classes `@Bean` method __has__ standard Java semantics.
@@ -5787,42 +5929,40 @@ as those discovered by custom filters), the default bean name generator returns
uncapitalized non-qualified class name. For example, if the following two components
were detected, the names would be myMovieLister and movieFinderImpl:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Service("myMovieLister")
-public class SimpleMovieLister {
- // ...
-}
+ @Service("myMovieLister")
+ public class SimpleMovieLister {
+ // ...
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Repository
-public class MovieFinderImpl implements MovieFinder {
- // ...
-}
+ @Repository
+ public class MovieFinderImpl implements MovieFinder {
+ // ...
+ }
----
[NOTE]
====
If you do not want to rely on the default bean-naming strategy, you can provide a custom
bean-naming strategy. First, implement the
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`]
+{javadoc-baseurl}/org/springframework/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`]
interface, and be sure to include a default no-arg constructor. Then, provide the
fully-qualified class name when configuring the scanner:
====
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
----
As a general rule, consider specifying the name with the annotation whenever other
@@ -5838,51 +5978,47 @@ autodetected components is singleton. However, sometimes you need other scopes,
Spring 2.5 provides with a new `@Scope` annotation. Simply provide the name of the scope
within the annotation:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Scope("prototype")
-@Repository
-public class MovieFinderImpl implements MovieFinder {
- // ...
-}
+ @Scope("prototype")
+ @Repository
+ public class MovieFinderImpl implements MovieFinder {
+ // ...
+ }
----
[NOTE]
====
To provide a custom strategy for scope resolution rather than relying on the
annotation-based approach, implement the
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ScopeMetadataResolver.html[`ScopeMetadataResolver`]
+{javadoc-baseurl}/org/springframework/context/annotation/ScopeMetadataResolver.html[`ScopeMetadataResolver`]
interface, and be sure to include a default no-arg constructor. Then, provide the
fully-qualified class name when configuring the scanner:
====
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
----
When using certain non-singleton scopes, it may be necessary to generate proxies for the
-scoped objects. The reasoning is described in<>.
+scoped objects. The reasoning is described in <>.
For this purpose, a __scoped-proxy__ attribute is available on the component-scan
element. The three possible values are: no, interfaces, and targetClass. For example,
the following configuration will result in standard JDK dynamic proxies:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
----
@@ -5899,34 +6035,34 @@ autodetection of components, you provide the qualifier metadata with type-level
annotations on the candidate class. The following three examples demonstrate this
technique:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Component
-**@Qualifier("Action")**
-public class ActionMovieCatalog implements MovieCatalog {
- // ...
-}
+ @Component
+ **@Qualifier("Action")**
+ public class ActionMovieCatalog implements MovieCatalog {
+ // ...
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Component
-**@Genre("Action")**
-public class ActionMovieCatalog implements MovieCatalog {
- // ...
-}
+ @Component
+ **@Genre("Action")**
+ public class ActionMovieCatalog implements MovieCatalog {
+ // ...
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Component
-**@Offline**
-public class CachingMovieCatalog implements MovieCatalog {
- // ...
-}
+ @Component
+ **@Offline**
+ public class CachingMovieCatalog implements MovieCatalog {
+ // ...
+ }
----
[NOTE]
@@ -5953,39 +6089,41 @@ repository (
http://repo1.maven.org/maven2/javax/inject/javax.inject/1/[http://repo1.maven.org/maven2/javax/inject/javax.inject/1/]).
You can add the following dependency to your file pom.xml:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
- javax.inject
- javax.inject
- 1
-
+
+ javax.inject
+ javax.inject
+ 1
+
----
====
[[beans-inject-named]]
-==== Dependency Injection with @Inject and `@Named`
+==== Dependency Injection with @Inject and @Named
Instead of `@Autowired`, `@javax.inject.Inject` may be used as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import javax.inject.Inject;
+ import javax.inject.Inject;
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Inject
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
- // ...
-}
+ @Inject
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+
+ }
----
As with `@Autowired`, it is possible to use `@Inject` at the class-level, field-level,
@@ -5993,82 +6131,88 @@ method-level and constructor-argument level. If you would like to use a qualifie
for the dependency that should be injected, you should use the `@Named` annotation as
follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import javax.inject.Inject;
-import javax.inject.Named;
+ import javax.inject.Inject;
+ import javax.inject.Named;
-public class SimpleMovieLister {
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Inject
- public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
- // ...
-}
+ @Inject
+ public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+
+ }
----
[[beans-named]]
-==== @Named: a standard equivalent to the `@Component` annotation
+==== @Named: a standard equivalent to the @Component annotation
Instead of `@Component`, `@javax.inject.Named` may be used as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import javax.inject.Inject;
-import javax.inject.Named;
+ import javax.inject.Inject;
+ import javax.inject.Named;
-@Named("movieListener")
-public class SimpleMovieLister {
+ @Named("movieListener")
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Inject
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
- // ...
-}
+ @Inject
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+
+ }
----
It is very common to use `@Component` without
specifying a name for the component. `@Named`
can be used in a similar fashion:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import javax.inject.Inject;
-import javax.inject.Named;
+ import javax.inject.Inject;
+ import javax.inject.Named;
-@Named
-public class SimpleMovieLister {
+ @Named
+ public class SimpleMovieLister {
- private MovieFinder movieFinder;
+ private MovieFinder movieFinder;
- @Inject
- public void setMovieFinder(MovieFinder movieFinder) {
- this.movieFinder = movieFinder;
- }
- // ...
-}
+ @Inject
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+
+ }
----
When using `@Named`, it is possible to use
component-scanning in the exact same way as when using Spring annotations:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
@@ -6093,7 +6237,7 @@ features are not available as shown in the table below:
| @Scope("singleton")
| @Singleton
-| The JSR-330 default scope is like Spring's `prototype`. However, in order to keep it
+| The JSR-330 default scope is like Spring's `prototype`. However, in order to keep it
consistent with Spring's general defaults, a JSR-330 bean declared in the Spring
container is a `singleton` by default. In order to use a scope other than `singleton`,
you should use Spring's `@Scope` annotation.
@@ -6128,23 +6272,7 @@ Nevertheless, this one is only intended to be used for creating your own annotat
[[beans-java-basic-concepts]]
-==== Basic concepts: Full @Configuration vs 'lite' @Beans mode? @Bean and `@Configuration`
-
-****
-When `@Bean` methods are declared within classes that are __not__ annotated with
-`@Configuration` they are referred to as being processed in a 'lite' mode. For example,
-bean methods declared in a `@Component` or even in a __plain old class__ will be
-considered 'lite'.
-
-Unlike full `@Configuration`, lite `@Bean` methods cannot easily declare inter-bean
-dependencies. Usually one `@Bean` method should not invoke another `@Bean` method when
-operating in 'lite' mode.
-
-Only using `@Bean` methods within `@Configuration` classes is a recommended approach of
-ensuring that 'full' mode is always used. This will prevent the same `@Bean` method from
-accidentally being invoked multiple times and helps to reduce subtle bugs that can be
-hard to track down when operating in 'lite' mode.
-****
+==== Basic concepts: @Bean and @Configuration
The central artifacts in Spring's new Java-configuration support are
`@Configuration`-annotated classes and `@Bean`-annotated methods.
@@ -6160,32 +6288,50 @@ source of bean definitions. Furthermore, `@Configuration` classes allow inter-be
dependencies to be defined by simply calling other `@Bean` methods in the same class.
The simplest possible `@Configuration` class would read as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
- @Bean
- public MyService myService() {
- return new MyServiceImpl();
- }
-}
+ @Configuration
+ public class AppConfig {
+
+ @Bean
+ public MyService myService() {
+ return new MyServiceImpl();
+ }
+
+ }
----
The `AppConfig` class above would be equivalent to the following Spring `` XML:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
The `@Bean` and `@Configuration` annotations will be discussed in depth in the sections
below. First, however, we'll cover the various ways of creating a spring container using
Java-based configuration.
+.Full @Configuration vs 'lite' @Beans mode?
+****
+When `@Bean` methods are declared within classes that are __not__ annotated with
+`@Configuration` they are referred to as being processed in a 'lite' mode. For example,
+bean methods declared in a `@Component` or even in a __plain old class__ will be
+considered 'lite'.
+
+Unlike full `@Configuration`, lite `@Bean` methods cannot easily declare inter-bean
+dependencies. Usually one `@Bean` method should not invoke another `@Bean` method when
+operating in 'lite' mode.
+
+Only using `@Bean` methods within `@Configuration` classes is a recommended approach of
+ensuring that 'full' mode is always used. This will prevent the same `@Bean` method from
+accidentally being invoked multiple times and helps to reduce subtle bugs that can be
+hard to track down when operating in 'lite' mode.
+****
[[beans-java-instantiating-container]]
@@ -6211,29 +6357,28 @@ In much the same way that Spring XML files are used as input when instantiating
instantiating an `AnnotationConfigApplicationContext`. This allows for completely
XML-free usage of the Spring container:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
- MyService myService = ctx.getBean(MyService.class);
- myService.doStuff();
-}
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ MyService myService = ctx.getBean(MyService.class);
+ myService.doStuff();
+ }
----
-As mentioned above,
- `AnnotationConfigApplicationContext` is not limited to working only with
-`@Configuration` classes. Any `@Component` or JSR-330 annotated class may be supplied as
-input to the constructor. For example:
+As mentioned above, `AnnotationConfigApplicationContext` is not limited to working only
+with `@Configuration` classes. Any `@Component` or JSR-330 annotated class may be supplied
+as input to the constructor. For example:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
- MyService myService = ctx.getBean(MyService.class);
- myService.doStuff();
-}
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
+ MyService myService = ctx.getBean(MyService.class);
+ myService.doStuff();
+ }
----
The above assumes that `MyServiceImpl`, `Dependency1` and `Dependency2` use Spring
@@ -6247,17 +6392,17 @@ An `AnnotationConfigApplicationContext` may be instantiated using a no-arg const
and then configured using the `register()` method. This approach is particularly useful
when programmatically building an `AnnotationConfigApplicationContext`.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
- ctx.register(AppConfig.class, OtherConfig.class);
- ctx.register(AdditionalConfig.class);
- ctx.refresh();
- MyService myService = ctx.getBean(MyService.class);
- myService.doStuff();
-}
+ public static void main(String[] args) {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(AppConfig.class, OtherConfig.class);
+ ctx.register(AdditionalConfig.class);
+ ctx.refresh();
+ MyService myService = ctx.getBean(MyService.class);
+ myService.doStuff();
+ }
----
@@ -6267,12 +6412,12 @@ public static void main(String[] args) {
Experienced Spring users will be familiar with the following commonly-used XML
declaration from Spring's `context:` namespace
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
In the example above, the `com.acme` package will be scanned, looking for any
@@ -6280,24 +6425,25 @@ In the example above, the `com.acme` package will be scanned, looking for any
definitions within the container. `AnnotationConfigApplicationContext` exposes the
`scan(String...)` method to allow for the same component-scanning functionality:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
- ctx.scan("com.acme");
- ctx.refresh();
- MyService myService = ctx.getBean(MyService.class);
-}
+ public static void main(String[] args) {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.scan("com.acme");
+ ctx.refresh();
+ MyService myService = ctx.getBean(MyService.class);
+ }
----
[NOTE]
====
-Remember that `@Configuration` classes are meta-annotated with `@Component`, so they are
-candidates for component-scanning! In the example above, assuming that `AppConfig` is
-declared within the `com.acme` package (or any package underneath), it will be picked up
-during the call to `scan()`, and upon `refresh()` all its `@Bean` methods will be
-processed and registered as bean definitions within the container.
+Remember that `@Configuration` classes are <>
+with `@Component`, so they are candidates for component-scanning! In the example above,
+assuming that `AppConfig` is declared within the `com.acme` package (or any package
+underneath), it will be picked up during the call to `scan()`, and upon `refresh()` all
+its `@Bean` methods will be processed and registered as bean definitions within the
+container.
====
@@ -6311,58 +6457,58 @@ configuring the Spring `ContextLoaderListener` servlet listener, Spring MVC
Spring MVC web application. Note the use of the `contextClass` context-param and
init-param:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
- contextClass
-
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
+
+
+
+ contextClass
+
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
-
-
- contextConfigLocation
- com.acme.AppConfig
-
+
+
+ contextConfigLocation
+ com.acme.AppConfig
+
-
-
- org.springframework.web.context.ContextLoaderListener
-
+
+
+ org.springframework.web.context.ContextLoaderListener
+
-
-
- dispatcher
- org.springframework.web.servlet.DispatcherServlet
-
-
- contextClass
-
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
-
-
- contextConfigLocation
- com.acme.web.MvcConfig
-
-
+
+
+ dispatcher
+ org.springframework.web.servlet.DispatcherServlet
+
+
+ contextClass
+
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+
+
+ contextConfigLocation
+ com.acme.web.MvcConfig
+
+
-
-
- dispatcher
- /app/*
-
-
+
+
+ dispatcher
+ /app/*
+
+
----
@@ -6387,34 +6533,34 @@ method to register a bean definition within an `ApplicationContext` of the type
specified as the method's return value. By default, the bean name will be the same as
the method name. The following is a simple example of a `@Bean` method declaration:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
+ @Configuration
+ public class AppConfig {
- @Bean
- public TransferService transferService() {
- return new TransferServiceImpl();
- }
+ @Bean
+ public TransferService transferService() {
+ return new TransferServiceImpl();
+ }
-}
+ }
----
The preceding configuration is exactly equivalent to the following Spring XML:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
Both declarations make a bean named `transferService` available in the
`ApplicationContext`, bound to an object instance of type `TransferServiceImpl`:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
transferService -> com.acme.TransferServiceImpl
@@ -6441,51 +6587,55 @@ The `@Bean` annotation supports specifying arbitrary initialization and destruct
callback methods, much like Spring XML's `init-method` and `destroy-method` attributes
on the `bean` element:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class Foo {
- public void init() {
- // initialization logic
- }
-}
+ public class Foo {
+ public void init() {
+ // initialization logic
+ }
+ }
-public class Bar {
- public void cleanup() {
- // destruction logic
- }
-}
+ public class Bar {
+ public void cleanup() {
+ // destruction logic
+ }
+ }
-@Configuration
-public class AppConfig {
- @Bean(initMethod = "init")
- public Foo foo() {
- return new Foo();
- }
- @Bean(destroyMethod = "cleanup")
- public Bar bar() {
- return new Bar();
- }
-}
+ @Configuration
+ public class AppConfig {
+
+ @Bean(initMethod = "init")
+ public Foo foo() {
+ return new Foo();
+ }
+
+ @Bean(destroyMethod = "cleanup")
+ public Bar bar() {
+ return new Bar();
+ }
+
+ }
----
Of course, in the case of `Foo` above, it would be equally as valid to call the `init()`
method directly during construction:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
- @Bean
- public Foo foo() {
- Foo foo = new Foo();
- foo.init();
- return foo;
- }
+ @Configuration
+ public class AppConfig {
+ @Bean
+ public Foo foo() {
+ Foo foo = new Foo();
+ foo.init();
+ return foo;
+ }
- // ...
-}
+ // ...
+
+ }
----
[TIP]
@@ -6508,21 +6658,23 @@ specific scope. You can use any of the standard scopes specified in the
The default scope is `singleton`, but you can override this with the `@Scope` annotation:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class MyConfiguration {
- @Bean
- **@Scope("prototype")**
- public Encryptor encryptor() {
- // ...
- }
-}
+ @Configuration
+ public class MyConfiguration {
+
+ @Bean
+ **@Scope("prototype")**
+ public Encryptor encryptor() {
+ // ...
+ }
+
+ }
----
[[beans-java-scoped-proxy]]
-====== @Scope and scoped-proxy
+====== @Scope and scoped-proxy
Spring offers a convenient way of working with scoped dependencies through
<>. The easiest way to create such
@@ -6534,23 +6686,23 @@ specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`.
If you port the scoped proxy example from the XML reference documentation (see preceding
link) to our `@Bean` using Java, it would look like the following:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-// an HTTP Session-scoped bean exposed as a proxy
-@Bean
-**@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)**
-public UserPreferences userPreferences() {
- return new UserPreferences();
-}
+ // an HTTP Session-scoped bean exposed as a proxy
+ @Bean
+ **@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)**
+ public UserPreferences userPreferences() {
+ return new UserPreferences();
+ }
-@Bean
-public Service userService() {
- UserService service = new SimpleUserService();
- // a reference to the proxied userPreferences bean
- service.setUserPreferences(userPreferences());
- return service;
-}
+ @Bean
+ public Service userService() {
+ UserService service = new SimpleUserService();
+ // a reference to the proxied userPreferences bean
+ service.setUserPreferences(userPreferences());
+ return service;
+ }
----
@@ -6559,18 +6711,18 @@ public Service userService() {
By default, configuration classes use a `@Bean` method's name as the name of the
resulting bean. This functionality can be overridden, however, with the `name` attribute.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
+ @Configuration
+ public class AppConfig {
- @Bean(name = "myFoo")
- public Foo foo() {
- return new Foo();
- }
+ @Bean(name = "myFoo")
+ public Foo foo() {
+ return new Foo();
+ }
-}
+ }
----
@@ -6580,21 +6732,45 @@ As discussed in <>, it is sometimes desirable to give a single b
multiple names, otherwise known as__bean aliasing__. The `name` attribute of the `@Bean`
annotation accepts a String array for this purpose.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
+ @Configuration
+ public class AppConfig {
- @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
- public DataSource dataSource() {
- // instantiate, configure and return DataSource bean...
- }
+ @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
+ public DataSource dataSource() {
+ // instantiate, configure and return DataSource bean...
+ }
-}
+ }
----
+[[beans-java-bean-description]]
+===== Bean description
+Sometimes it is helpful to provide a more detailed textual description of a bean. This can
+be particularly useful when beans are exposed (perhaps via JMX) for monitoring purposes.
+
+To add a description to a `@Bean` the
+{javadoc-baseurl}/org/springframework/context/annotation/Description.html[`@Description`]
+annotation can be used:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Configuration
+ public class AppConfig {
+
+ @Bean
+ **@Desciption("Provides a basic example of a bean")**
+ public Foo foo() {
+ return new Foo();
+ }
+
+ }
+----
+
[[beans-java-configuration-annotation]]
==== Using the @Configuration annotation
@@ -6610,23 +6786,23 @@ inter-bean dependencies. See <> for a general introdu
When `@Bean` s have dependencies on one another, expressing that dependency is as simple
as having one bean method call another:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
+ @Configuration
+ public class AppConfig {
- @Bean
- public Foo foo() {
- return new Foo(bar());
- }
+ @Bean
+ public Foo foo() {
+ return new Foo(bar());
+ }
- @Bean
- public Bar bar() {
- return new Bar();
- }
+ @Bean
+ public Bar bar() {
+ return new Bar();
+ }
-}
+ }
----
In the example above, the `foo` bean receives a reference to `bar` via constructor
@@ -6647,49 +6823,49 @@ advanced feature that you should use rarely. It is useful in cases where a
singleton-scoped bean has a dependency on a prototype-scoped bean. Using Java for this
type of configuration provides a natural means for implementing this pattern.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public abstract class CommandManager {
- public Object process(Object commandState) {
- // grab a new instance of the appropriate Command interface
- Command command = createCommand();
+ public abstract class CommandManager {
+ public Object process(Object commandState) {
+ // grab a new instance of the appropriate Command interface
+ Command command = createCommand();
- // set the state on the (hopefully brand new) Command instance
- command.setState(commandState);
- return command.execute();
- }
+ // set the state on the (hopefully brand new) Command instance
+ command.setState(commandState);
+ return command.execute();
+ }
- // okay... but where is the implementation of this method?
- protected abstract Command createCommand();
-}
+ // okay... but where is the implementation of this method?
+ protected abstract Command createCommand();
+ }
----
Using Java-configuration support , you can create a subclass of `CommandManager` where
the abstract `createCommand()` method is overridden in such a way that it looks up a new
(prototype) command object:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Bean
-@Scope("prototype")
-public AsyncCommand asyncCommand() {
- AsyncCommand command = new AsyncCommand();
- // inject dependencies here as required
- return command;
-}
+ @Bean
+ @Scope("prototype")
+ public AsyncCommand asyncCommand() {
+ AsyncCommand command = new AsyncCommand();
+ // inject dependencies here as required
+ return command;
+ }
-@Bean
-public CommandManager commandManager() {
- // return new anonymous implementation of CommandManager with command() overridden
- // to return a new prototype Command object
- return new CommandManager() {
- protected Command createCommand() {
- return asyncCommand();
- }
- }
-}
+ @Bean
+ public CommandManager commandManager() {
+ // return new anonymous implementation of CommandManager with command() overridden
+ // to return a new prototype Command object
+ return new CommandManager() {
+ protected Command createCommand() {
+ return asyncCommand();
+ }
+ }
+ }
----
@@ -6697,30 +6873,32 @@ public CommandManager commandManager() {
===== Further information about how Java-based configuration works internally
The following example shows a `@Bean` annotated method being called twice:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
+ @Configuration
+ public class AppConfig {
- @Bean
- public ClientService clientService1() {
- ClientServiceImpl clientService = new ClientServiceImpl();
- clientService.setClientDao(clientDao());
- return clientService;
- }
- @Bean
- public ClientService clientService2() {
- ClientServiceImpl clientService = new ClientServiceImpl();
- clientService.setClientDao(clientDao());
- return clientService;
- }
+ @Bean
+ public ClientService clientService1() {
+ ClientServiceImpl clientService = new ClientServiceImpl();
+ clientService.setClientDao(clientDao());
+ return clientService;
+ }
- @Bean
- public ClientDao clientDao() {
- return new ClientDaoImpl();
- }
-}
+ @Bean
+ public ClientService clientService2() {
+ ClientServiceImpl clientService = new ClientServiceImpl();
+ clientService.setClientDao(clientDao());
+ return clientService;
+ }
+
+ @Bean
+ public ClientDao clientDao() {
+ return new ClientDaoImpl();
+ }
+
+ }
----
`clientDao()` has been called once in `clientService1()` and once in `clientService2()`.
@@ -6762,40 +6940,49 @@ Much as the `` element is used within Spring XML files to aid in modula
configurations, the `@Import` annotation allows for loading `@Bean` definitions from
another configuration class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class ConfigA {
- public @Bean A a() { return new A(); }
-}
+ @Configuration
+ public class ConfigA {
-@Configuration
-@Import(ConfigA.class)
-public class ConfigB {
- public @Bean B b() { return new B(); }
-}
+ @Bean
+ public A a() {
+ return new A();
+ }
+
+ }
+
+ @Configuration
+ @Import(ConfigA.class)
+ public class ConfigB {
+
+ @Bean
+ public B b() {
+ return new B();
+ }
+
+ }
----
-Now, rather than needing to specify both
- `ConfigA.class` and `ConfigB.class` when instantiating the context, only
-`ConfigB` needs to be supplied explicitly:
+Now, rather than needing to specify both `ConfigA.class` and `ConfigB.class` when
+instantiating the context, only `ConfigB` needs to be supplied explicitly:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
- // now both beans A and B will be available...
- A a = ctx.getBean(A.class);
- B b = ctx.getBean(B.class);
-}
+ // now both beans A and B will be available...
+ A a = ctx.getBean(A.class);
+ B b = ctx.getBean(B.class);
+ }
----
-This approach simplifies container instantiation, as only one class
- needs to be dealt with, rather than requiring the developer to remember
- a potentially large number of `@Configuration` classes during construction.
+This approach simplifies container instantiation, as only one class needs to be dealt
+with, rather than requiring the developer to remember a potentially large number of
+`@Configuration` classes during construction.
[[beans-java-injecting-imported-beans]]
====== Injecting dependencies on imported @Bean definitions
@@ -6814,39 +7001,52 @@ of `@Autowired` injection metadata just like any other bean!
Let's consider a more real-world scenario with several `@Configuration` classes, each
depending on beans declared in the others:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class ServiceConfig {
- private @Autowired AccountRepository accountRepository;
+ @Configuration
+ public class ServiceConfig {
- public @Bean TransferService transferService() {
- return new TransferServiceImpl(accountRepository);
- }
-}
+ @Autowired
+ private AccountRepository accountRepository;
-@Configuration
-public class RepositoryConfig {
- private @Autowired DataSource dataSource;
+ @Bean
+ public TransferService transferService() {
+ return new TransferServiceImpl(accountRepository);
+ }
- public @Bean AccountRepository accountRepository() {
- return new JdbcAccountRepository(dataSource);
- }
-}
+ }
-@Configuration
-@Import({ServiceConfig.class, RepositoryConfig.class})
-public class SystemTestConfig {
- public @Bean DataSource dataSource() { /* return new DataSource */ }
-}
+ @Configuration
+ public class RepositoryConfig {
-public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
- // everything wires up across configuration classes...
- TransferService transferService = ctx.getBean(TransferService.class);
- transferService.transfer(100.00, "A123", "C456");
-}
+ @Autowired
+ private DataSource dataSource;
+
+ @Bean
+ public AccountRepository accountRepository() {
+ return new JdbcAccountRepository(dataSource);
+ }
+
+ }
+
+ @Configuration
+ @Import({ServiceConfig.class, RepositoryConfig.class})
+ public class SystemTestConfig {
+
+ @Bean
+ public DataSource dataSource() {
+ // return new DataSource
+ }
+
+ }
+
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
+ // everything wires up across configuration classes...
+ TransferService transferService = ctx.getBean(TransferService.class);
+ transferService.transfer(100.00, "A123", "C456");
+ }
----
.[[beans-java-injecting-imported-beans-fq]]Fully-qualifying imported beans for ease of navigation
@@ -6865,61 +7065,78 @@ In cases where this ambiguity is not acceptable and you wish to have direct navi
from within your IDE from one `@Configuration` class to another, consider autowiring the
configuration classes themselves:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class ServiceConfig {
- private @Autowired RepositoryConfig repositoryConfig;
+ @Configuration
+ public class ServiceConfig {
- public @Bean TransferService transferService() {
- // navigate 'through' the config class to the @Bean method!
- return new TransferServiceImpl(repositoryConfig.accountRepository());
- }
-}
+ @Autowired
+ private RepositoryConfig repositoryConfig;
+
+ @Bean
+ public TransferService transferService() {
+ // navigate 'through' the config class to the @Bean method!
+ return new TransferServiceImpl(repositoryConfig.accountRepository());
+ }
+
+ }
----
-In the situation above, it is completely explicit where
- `AccountRepository` is defined. However, `ServiceConfig` is now tightly
-coupled to `RepositoryConfig`; that's the tradeoff. This tight coupling can be somewhat
-mitigated by using interface-based or abstract class-based `@Configuration` classes.
-Consider the following:
+In the situation above, it is completely explicit where `AccountRepository` is defined.
+However, `ServiceConfig` is now tightly coupled to `RepositoryConfig`; that's the
+tradeoff. This tight coupling can be somewhat mitigated by using interface-based or
+abstract class-based `@Configuration` classes. Consider the following:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class ServiceConfig {
- private @Autowired RepositoryConfig repositoryConfig;
+ @Configuration
+ public class ServiceConfig {
- public @Bean TransferService transferService() {
- return new TransferServiceImpl(repositoryConfig.accountRepository());
- }
-}
+ @Autowired
+ private RepositoryConfig repositoryConfig;
-@Configuration
-public interface RepositoryConfig {
- @Bean AccountRepository accountRepository();
-}
+ @Bean
+ public TransferService transferService() {
+ return new TransferServiceImpl(repositoryConfig.accountRepository());
+ }
+ }
-@Configuration
-public class DefaultRepositoryConfig implements RepositoryConfig {
- public @Bean AccountRepository accountRepository() {
- return new JdbcAccountRepository(...);
- }
-}
+ @Configuration
+ public interface RepositoryConfig {
-@Configuration
-@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
-public class SystemTestConfig {
- public @Bean DataSource dataSource() { /* return DataSource */ }
-}
+ @Bean
+ AccountRepository accountRepository();
-public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
- TransferService transferService = ctx.getBean(TransferService.class);
- transferService.transfer(100.00, "A123", "C456");
-}
+ }
+
+ @Configuration
+ public class DefaultRepositoryConfig implements RepositoryConfig {
+
+ @Bean
+ public AccountRepository accountRepository() {
+ return new JdbcAccountRepository(...);
+ }
+
+ }
+
+ @Configuration
+ @Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
+ public class SystemTestConfig {
+
+ @Bean
+ public DataSource dataSource() {
+ // return DataSource
+ }
+
+ }
+
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
+ TransferService transferService = ctx.getBean(TransferService.class);
+ transferService.transfer(100.00, "A123", "C456");
+ }
----
Now `ServiceConfig` is loosely coupled with respect to the concrete
@@ -6930,6 +7147,48 @@ than the usual process of navigating interface-based code.
--
+[[beans-java-conditional]]
+===== Conditionally including @Configuration classes or @Beans
+It is often useful to conditionally enable to disable a complete `@Configuration` class,
+or even individual `@Bean` methods, based on some arbitrary system state. One common
+example of this it to use the `@Profile` annotation to active beans only when a specific
+profile has been enabled in the Spring `Environment` (see <>
+for details).
+
+The `@Profile` annotation is actually implemented using a much more flexible annotation
+called {javadoc-baseurl}/org/springframework/context/annotation/Conditional.html[`@Conditional`].
+The `@Conditional` annotation indicates specific
+`org.springframework.context.annotation.Condition` implementations that should be
+consulted before a `@Bean` is registered.
+
+Implementations of the `Condition` interface simply provide a `matches(...)`
+method that returns `true` or `false`. For example, here is the actual
+`Condition` implementation used for `@Profile`:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ if (context.getEnvironment() != null) {
+ // Read the @Profile annotation attributes
+ MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
+ if (attrs != null) {
+ for (Object value : attrs.get("value")) {
+ if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ return true;
+ }
+----
+
+See the {javadoc-baseurl}/org/springframework/context/annotation/Conditional.html[
+@Conditional Javadoc] for more detail.
+
[[beans-java-combining]]
===== Combining Java and XML configuration
Spring's `@Configuration` class support does not aim to be a 100% complete replacement
@@ -6958,43 +7217,48 @@ include it within `system-test-config.xml` as a `` definition. Because
`@Configuration` annotation, and process the `@Bean` methods declared in `AppConfig`
properly.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-public class AppConfig {
- private @Autowired DataSource dataSource;
+ @Configuration
+ public class AppConfig {
- public @Bean AccountRepository accountRepository() {
- return new JdbcAccountRepository(dataSource);
- }
+ @Autowired
+ private DataSource dataSource;
- public @Bean TransferService transferService() {
- return new TransferService(accountRepository());
- }
-}
+ @Bean
+ public AccountRepository accountRepository() {
+ return new JdbcAccountRepository(dataSource);
+ }
+
+ @Bean
+ public TransferService transferService() {
+ return new TransferService(accountRepository());
+ }
+
+ }
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-system-test-config.xml
-
-
-
-
+ system-test-config.xml
+
+
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
----
-[source]
+[literal]
[subs="verbatim,quotes"]
----
jdbc.properties
@@ -7003,14 +7267,14 @@ jdbc.username=sa
jdbc.password=
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
- TransferService transferService = ctx.getBean(TransferService.class);
- // ...
-}
+ public static void main(String[] args) {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
+ TransferService transferService = ctx.getBean(TransferService.class);
+ // ...
+ }
----
[NOTE]
@@ -7032,26 +7296,26 @@ Note that in this case, we don't need to explicitly declare
``, because `` enables all the same
functionality.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-system-test-config.xml
-
-
-
-
+ system-test-config.xml
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
----
--
[[beans-java-combining-java-centric]]
-====== @Configuration class-centric use of XML with `@ImportResource`
+====== @Configuration class-centric use of XML with @ImportResource
In applications where `@Configuration` classes are the primary mechanism for configuring
the container, it will still likely be necessary to use at least some XML. In these
@@ -7059,32 +7323,40 @@ scenarios, simply use `@ImportResource` and define only as much XML as is needed
so achieves a "Java-centric" approach to configuring the container and keeps XML to a
bare minimum.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-@ImportResource("classpath:/com/acme/properties-config.xml")
-public class AppConfig {
- private @Value("${jdbc.url}") String url;
- private @Value("${jdbc.username}") String username;
- private @Value("${jdbc.password}") String password;
+ @Configuration
+ @ImportResource("classpath:/com/acme/properties-config.xml")
+ public class AppConfig {
- public @Bean DataSource dataSource() {
- return new DriverManagerDataSource(url, username, password);
- }
-}
+ @Value("${jdbc.url}")
+ private String url;
+
+ @Value("${jdbc.username}")
+ private String username;
+
+ @Value("${jdbc.password}")
+ private String password;
+
+ @Bean
+ public DataSource dataSource() {
+ return new DriverManagerDataSource(url, username, password);
+ }
+
+ }
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-properties-config.xml
-
-
-
+ properties-config.xml
+
+
+
----
-[source]
+[literal]
[subs="verbatim,quotes"]
----
jdbc.properties
@@ -7093,17 +7365,46 @@ jdbc.username=sa
jdbc.password=
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
- TransferService transferService = ctx.getBean(TransferService.class);
- // ...
-}
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ TransferService transferService = ctx.getBean(TransferService.class);
+ // ...
+ }
----
+[[beans-definition-profiles]]
+=== Bean definition profiles and environment abstraction
+Bean definition profiles is a mechanism in the core container that allows for registration
+of different beans in different environments. This feature can help with many use cases,
+including:
+
+* working against an in-memory datasource in development vs looking up that same
+datasource from JNDI when in QA or production
+* registering monitoring infrastructure only when deploying an application into a
+performance environment
+* registering customized implementations of beans for customer A vs. customer B deployments
+
+Find out more about http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/[Environment,
+XML Profiles] and the
+http://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/[@Profile annotation].
+
+
+[[beans-property-source-abstraction]]
+=== PropertySource Abstraction
+
+Spring's <> provides search operations
+over a configurable hierarchy of property sources.
+
+You can find out more about
+http://spring.io/blog/2011/02/15/spring-3-1-m1-unified-property-management/[Unified
+Property Management], the
+{javadoc-baseurl}/org/springframework/core/env/PropertySource.html[PropertySource class]
+and the {javadoc-baseurl}org/springframework/context/annotation/PropertySource.html[@PropertySource
+annotation].
[[context-load-time-weaver]]
@@ -7115,24 +7416,24 @@ loaded into the Java virtual machine (JVM).
To enable load-time weaving add the `@EnableLoadTimeWeaving` to one of your
`@Configuration` classes:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Configuration
-@EnableLoadTimeWeaving
-public class AppConfig {
+ @Configuration
+ @EnableLoadTimeWeaving
+ public class AppConfig {
-}
+ }
----
Alternatively for XML configuration use the `context:load-time-weaver` element:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
Once configured for the `ApplicationContext`. Any bean within that `ApplicationContext`
@@ -7151,7 +7452,7 @@ AspectJ load-time weaving, see <>.
As was discussed in the chapter introduction, the `org.springframework.beans.factory`
package provides basic functionality for managing and manipulating beans, including in a
programmatic way. The `org.springframework.context` package adds the
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html[`ApplicationContext`]
+{javadoc-baseurl}/org/springframework/context/ApplicationContext.html[`ApplicationContext`]
interface, which extends the `BeanFactory` interface, in addition to extending other
interfaces to provide additional functionality in a more __application
framework-oriented style__. Many people use the `ApplicationContext` in a completely
@@ -7208,21 +7509,21 @@ messaging. The `StaticMessageSource` is rarely used but provides programmatic wa
add messages to the source. The `ResourceBundleMessageSource` is shown in the following
example:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
- format
- exceptions
- windows
-
-
-
-
+
+
+
+
+ format
+ exceptions
+ windows
+
+
+
+
----
In the example it is assumed you have three resource bundles defined in your classpath
@@ -7231,37 +7532,37 @@ handled in the JDK standard way of resolving messages through ResourceBundles. F
purposes of the example, assume the contents of two of the above resource bundle files
are...
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-# in format.properties
-message=Alligators rock!
+ # in format.properties
+ message=Alligators rock!
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-# in exceptions.properties
-argument.required=The '{0}' argument is required.
+ # in exceptions.properties
+ argument.required=The '{0}' argument is required.
----
A program to execute the `MessageSource` functionality is shown in the next example.
Remember that all `ApplicationContext` implementations are also `MessageSource`
implementations and so can be cast to the `MessageSource` interface.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(String[] args) {
- MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
- String message = resources.getMessage("message", null, "Default", null);
- System.out.println(message);
-}
+ public static void main(String[] args) {
+ MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
+ String message = resources.getMessage("message", null, "Default", null);
+ System.out.println(message);
+ }
----
The resulting output from the above program will be...
-[source]
+[literal]
[subs="verbatim,quotes"]
----
Alligators rock!
@@ -7277,47 +7578,47 @@ classpath and are called `format.properties`, `exceptions.properties`, and
The next example shows arguments passed to the message lookup; these arguments will be
converted into Strings and inserted into placeholders in the lookup message.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
+
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class Example {
+ public class Example {
- private MessageSource messages;
+ private MessageSource messages;
- public void setMessages(MessageSource messages) {
- this.messages = messages;
- }
+ public void setMessages(MessageSource messages) {
+ this.messages = messages;
+ }
- public void execute() {
- String message = this.messages.getMessage("argument.required",
- new Object [] {"userDao"}, "Required", null);
- System.out.println(message);
- }
+ public void execute() {
+ String message = this.messages.getMessage("argument.required",
+ new Object [] {"userDao"}, "Required", null);
+ System.out.println(message);
+ }
-}
+ }
----
The resulting output from the invocation of the `execute()` method will be...
-[source]
+[literal]
[subs="verbatim,quotes"]
----
The userDao argument is required.
@@ -7326,7 +7627,7 @@ The userDao argument is required.
With regard to internationalization (i18n), Spring's various `MessageResource`
implementations follow the same locale resolution and fallback rules as the standard JDK
`ResourceBundle`. In short, and continuing with the example `messageSource` defined
-previously, if you want to resolve messages against the British (en-GB) locale, you
+previously, if you want to resolve messages against the British (`en-GB`) locale, you
would create files called `format_en_GB.properties`, `exceptions_en_GB.properties`, and
`windows_en_GB.properties` respectively.
@@ -7334,27 +7635,27 @@ Typically, locale resolution is managed by the surrounding environment of the
application. In this example, the locale against which (British) messages will be
resolved is specified manually.
-[source]
+[literal]
[subs="verbatim,quotes"]
----
# in exceptions_en_GB.properties
argument.required=Ebagum lad, the '{0}' argument is required, I say, required.
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public static void main(final String[] args) {
- MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
- String message = resources.getMessage("argument.required",
- new Object [] {"userDao"}, "Required", Locale.UK);
- System.out.println(message);
-}
+ public static void main(final String[] args) {
+ MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
+ String message = resources.getMessage("argument.required",
+ new Object [] {"userDao"}, "Required", Locale.UK);
+ System.out.println(message);
+ }
----
The resulting output from the running of the above program will be...
-[source]
+[literal]
[subs="verbatim,quotes"]
----
Ebagum lad, the 'userDao' argument is required, I say, required.
@@ -7424,28 +7725,30 @@ following standard events:
| `RequestHandledEvent`
| A web-specific event telling all beans that an HTTP request has been serviced. This
- event is published__after__ the request is complete. This event is only applicable to
+ event is published __after__ the request is complete. This event is only applicable to
web applications using Spring's `DispatcherServlet`.
|===
You can also create and publish your own custom events. This example demonstrates a
simple class that extends Spring's `ApplicationEvent` base class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class BlackListEvent extends ApplicationEvent {
- private final String address;
- private final String test;
+ public class BlackListEvent extends ApplicationEvent {
- public BlackListEvent(Object source, String address, String test) {
- super(source);
- this.address = address;
- this.test = test;
- }
+ private final String address;
+ private final String test;
- // accessor and other methods...
-}
+ public BlackListEvent(Object source, String address, String test) {
+ super(source);
+ this.address = address;
+ this.test = test;
+ }
+
+ // accessor and other methods...
+
+ }
----
To publish a custom `ApplicationEvent`, call the `publishEvent()` method on an
@@ -7453,31 +7756,32 @@ To publish a custom `ApplicationEvent`, call the `publishEvent()` method on an
`ApplicationEventPublisherAware` and registering it as a Spring bean. The following
example demonstrates such a class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class EmailService implements ApplicationEventPublisherAware {
+ public class EmailService implements ApplicationEventPublisherAware {
- private List blackList;
- private ApplicationEventPublisher publisher;
+ private List blackList;
+ private ApplicationEventPublisher publisher;
- public void setBlackList(List blackList) {
- this.blackList = blackList;
- }
+ public void setBlackList(List blackList) {
+ this.blackList = blackList;
+ }
- public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
- this.publisher = publisher;
- }
+ public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
+ this.publisher = publisher;
+ }
- public void sendEmail(String address, String text) {
- if (blackList.contains(address)) {
- BlackListEvent event = new BlackListEvent(this, address, text);
- publisher.publishEvent(event);
- return;
- }
- // send email...
- }
-}
+ public void sendEmail(String address, String text) {
+ if (blackList.contains(address)) {
+ BlackListEvent event = new BlackListEvent(this, address, text);
+ publisher.publishEvent(event);
+ return;
+ }
+ // send email...
+ }
+
+ }
----
At configuration time, the Spring container will detect that `EmailService` implements
@@ -7490,21 +7794,22 @@ To receive the custom `ApplicationEvent`, create a class that implements
`ApplicationListener` and register it as a Spring bean. The following example
demonstrates such a class:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class BlackListNotifier implements ApplicationListener {
+ public class BlackListNotifier implements ApplicationListener {
- private String notificationAddress;
+ private String notificationAddress;
- public void setNotificationAddress(String notificationAddress) {
- this.notificationAddress = notificationAddress;
- }
+ public void setNotificationAddress(String notificationAddress) {
+ this.notificationAddress = notificationAddress;
+ }
- public void onApplicationEvent(BlackListEvent event) {
-// notify appropriate parties via notificationAddress...
- }
-}
+ public void onApplicationEvent(BlackListEvent event) {
+ // notify appropriate parties via notificationAddress...
+ }
+
+ }
----
Notice that `ApplicationListener` is generically parameterized with the type of your
@@ -7521,22 +7826,22 @@ event publication becomes necessary, refer to the JavaDoc for Spring's
The following example shows the bean definitions used to register and configure each of
the classes above:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
- known.spammer@example.org
- known.hacker@example.org
- john.doe@example.org
-
-
-
+
+
+
+ known.spammer@example.org
+ known.hacker@example.org
+ john.doe@example.org
+
+
+
-
-
-
+
+
+
----
Putting it all together, when the `sendEmail()` method of the `emailService` bean is
@@ -7610,20 +7915,25 @@ have a look at the Javadoc for the `ContextLoaderServlet`.
You can register an `ApplicationContext` using the `ContextLoaderListener` as follows:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-contextConfigLocation
-/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml
-
+
+ contextConfigLocation
+ /WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml
+
-
-org.springframework.web.context.ContextLoaderListener
-
+
+ org.springframework.web.context.ContextLoaderListener
+
-
----
The listener inspects the `contextConfigLocation` parameter. If the parameter does not
@@ -7642,13 +7952,13 @@ the `contextConfigLocation` parameter just as the listener does.
[[context-deploy-rar]]
==== Deploying a Spring ApplicationContext as a J2EE RAR file
-In Spring 2.5 and later, it is possible to deploy a Spring ApplicationContext as a RAR
-file, encapsulating the context and all of its required bean classes and library JARs in
-a J2EE RAR deployment unit. This is the equivalent of bootstrapping a standalone
-ApplicationContext, just hosted in J2EE environment, being able to access the J2EE
-servers facilities. RAR deployment is a more natural alternative to scenario of
-deploying a headless WAR file, in effect, a WAR file without any HTTP entry points that
-is used only for bootstrapping a Spring ApplicationContext in a J2EE environment.
+It is possible to deploy a Spring ApplicationContext as a RAR file, encapsulating the
+context and all of its required bean classes and library JARs in a J2EE RAR deployment
+unit. This is the equivalent of bootstrapping a standalone ApplicationContext, just hosted
+in J2EE environment, being able to access the J2EE servers facilities. RAR deployment is a
+more natural alternative to scenario of deploying a headless WAR file, in effect, a WAR
+file without any HTTP entry points that is used only for bootstrapping a Spring
+ApplicationContext in a J2EE environment.
RAR deployment is ideal for application contexts that do not need HTTP entry points but
rather consist only of message endpoints and scheduled jobs. Beans in such a context can
@@ -7659,7 +7969,7 @@ and JMX support facilities. Application components can also interact with the
application server's JCA WorkManager through Spring's `TaskExecutor` abstraction.
Check out the JavaDoc of the
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jca/context/SpringContextResourceAdapter.html[SpringContextResourceAdapter]
+{javadoc-baseurl}/org/springframework/jca/context/SpringContextResourceAdapter.html[SpringContextResourceAdapter]
class for the configuration details involved in RAR deployment.
__For a simple deployment of a Spring ApplicationContext as a J2EE RAR file:__ package
@@ -7702,7 +8012,7 @@ directly through a classic singleton lookup.
[[context-introduction-ctx-vs-beanfactory]]
-==== BeanFactory or `ApplicationContext`?
+==== BeanFactory or ApplicationContext?
Use an `ApplicationContext` unless you have a good reason for not doing so.
@@ -7710,7 +8020,7 @@ Because the `ApplicationContext` includes all functionality of the `BeanFactory`
generally recommended over the `BeanFactory`, except for a few situations such as in an
`Applet` where memory consumption might be critical and a few extra kilobytes might make
a difference. However, for most typical enterprise applications and systems, the
-`ApplicationContext` is what you will want to use. Spring 2.0 and later makes__heavy__
+`ApplicationContext` is what you will want to use. Spring makes __heavy__
use of the <> (to
effect proxying and so on). If you use only a plain `BeanFactory`, a fair amount of
support such as transactions and AOP will not take effect, at least not without some
@@ -7749,32 +8059,32 @@ The following table lists features provided by the `BeanFactory` and
To explicitly register a bean post-processor with a `BeanFactory` implementation, you
must write code like this:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ConfigurableBeanFactory factory = new XmlBeanFactory(...);
+ ConfigurableBeanFactory factory = new XmlBeanFactory(...);
-// now register any needed BeanPostProcessor instances
-MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
-factory.addBeanPostProcessor(postProcessor);
+ // now register any needed BeanPostProcessor instances
+ MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
+ factory.addBeanPostProcessor(postProcessor);
-// now start using the factory
+ // now start using the factory
----
To explicitly register a `BeanFactoryPostProcessor` when using a `BeanFactory`
implementation, you must write code like this:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
+ XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
-// bring in some property values from a Properties file
-PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
-cfg.setLocation(new FileSystemResource("jdbc.properties"));
+ // bring in some property values from a Properties file
+ PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
+ cfg.setLocation(new FileSystemResource("jdbc.properties"));
-// now actually do the replacement
-cfg.postProcessBeanFactory(factory);
+ // now actually do the replacement
+ cfg.postProcessBeanFactory(factory);
----
In both cases, the explicit registration step is inconvenient, which is one reason why
@@ -7811,7 +8121,7 @@ option for accessing shared Spring-managed components, such as in an EJB 2.1
environment, or when you want to share a single ApplicationContext as a parent to
WebApplicationContexts across WAR files. In this case you should look into using the
utility class
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html[`ContextSingletonBeanFactoryLocator`]
+{javadoc-baseurl}/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html[`ContextSingletonBeanFactoryLocator`]
locator that is described in this
http://blog.springsource.com/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/[SpringSource
team blog entry].
@@ -7846,34 +8156,36 @@ such as a method to check for the existence of the resource being pointed to.
Spring's `Resource` interface is meant to be a more capable interface for abstracting
access to low-level resources.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface Resource extends InputStreamSource {
+ public interface Resource extends InputStreamSource {
- boolean exists();
+ boolean exists();
- boolean isOpen();
+ boolean isOpen();
- URL getURL() throws IOException;
+ URL getURL() throws IOException;
- File getFile() throws IOException;
+ File getFile() throws IOException;
- Resource createRelative(String relativePath) throws IOException;
+ Resource createRelative(String relativePath) throws IOException;
- String getFilename();
+ String getFilename();
- String getDescription();
-}
+ String getDescription();
+
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface InputStreamSource {
+ public interface InputStreamSource {
- InputStream getInputStream() throws IOException;
-}
+ InputStream getInputStream() throws IOException;
+
+ }
----
Some of the most important methods from the `Resource` interface are:
@@ -7925,7 +8237,7 @@ box in Spring:
[[resources-implementations-urlresource]]
-==== UrlResource
+==== UrlResource
The `UrlResource` wraps a `java.net.URL`, and may be used to access any object that is
normally accessible via a URL, such as files, an HTTP target, an FTP target, etc. All
@@ -7946,7 +8258,7 @@ create a `UrlResource`.
[[resources-implementations-classpathresource]]
-==== ClassPathResource
+==== ClassPathResource
This class represents a resource which should be obtained from the classpath. This uses
either the thread context class loader, a given class loader, or a given class for
@@ -7967,7 +8279,7 @@ path, and create a `ClassPathResource` in that case.
[[resources-implementations-filesystemresource]]
-==== FileSystemResource
+==== FileSystemResource
This is a `Resource` implementation for `java.io.File` handles. It obviously supports
resolution as a `File`, and as a `URL`.
@@ -7975,7 +8287,7 @@ resolution as a `File`, and as a `URL`.
[[resources-implementations-servletcontextresource]]
-==== ServletContextResource
+==== ServletContextResource
This is a `Resource` implementation for `ServletContext` resources, interpreting
relative paths within the relevant web application's root directory.
@@ -7989,7 +8301,7 @@ dependent on the Servlet container.
[[resources-implementations-inputstreamresource]]
-==== InputStreamResource
+==== InputStreamResource
A `Resource` implementation for a given `InputStream`. This should only be used if no
specific `Resource` implementation is applicable. In particular, prefer
@@ -8003,7 +8315,7 @@ times.
[[resources-implementations-bytearrayresource]]
-==== ByteArrayResource
+==== ByteArrayResource
This is a `Resource` implementation for a given byte array. It creates a
`ByteArrayInputStream` for the given byte array.
@@ -8020,12 +8332,14 @@ single-use `InputStreamResource`.
The `ResourceLoader` interface is meant to be implemented by objects that can return
(i.e. load) `Resource` instances.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface ResourceLoader {
- Resource getResource(String location);
-}
+ public interface ResourceLoader {
+
+ Resource getResource(String location);
+
+ }
----
All application contexts implement the `ResourceLoader` interface, and therefore all
@@ -8036,10 +8350,10 @@ specified doesn't have a specific prefix, you will get back a `Resource` type th
appropriate to that particular application context. For example, assume the following
snippet of code was executed against a `ClassPathXmlApplicationContext` instance:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
+ Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
----
What would be returned would be a `ClassPathResource`; if the same method was executed
@@ -8053,25 +8367,25 @@ context.
On the other hand, you may also force `ClassPathResource` to be used, regardless of the
application context type, by specifying the special `classpath:` prefix:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
+ Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
----
Similarly, one can force a `UrlResource` to be used by specifying any of the standard
`java.net.URL` prefixes:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");
+ Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
+ Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
----
The following table summarizes the strategy for converting `String` s to `Resource` s:
@@ -8082,21 +8396,21 @@ The following table summarizes the strategy for converting `String` s to `Resour
| Prefix| Example| Explanation
| classpath:
-| `classpath:com/myapp/config.xml`
+| `classpath:com/myapp/config.xml`
| Loaded from the classpath.
| file:
-| `file:/data/config.xml`
-| Loaded as a `URL`, from the filesystem. footnote:[But see also
+| `file:/data/config.xml`
+| Loaded as a `URL`, from the filesystem. footnote:[But see also
pass:specialcharacters,macros[<>].]
| http:
-| `http://myserver/logo.png`
+| `http://myserver/logo.png`
| Loaded as a `URL`.
| (none)
-| `/data/config.xml`
-| Depends on the underlying `ApplicationContext`.
+| `/data/config.xml`
+| Depends on the underlying `ApplicationContext`.
|===
@@ -8108,13 +8422,13 @@ The following table summarizes the strategy for converting `String` s to `Resour
The `ResourceLoaderAware` interface is a special marker interface, identifying objects
that expect to be provided with a `ResourceLoader` reference.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface ResourceLoaderAware {
+ public interface ResourceLoaderAware {
- void setResourceLoader(ResourceLoader resourceLoader);
-}
+ void setResourceLoader(ResourceLoader resourceLoader);
+ }
----
When a class implements `ResourceLoaderAware` and is deployed into an application
@@ -8145,7 +8459,7 @@ annotation. For more information, see <>.
[[resources-as-dependencies]]
-=== Resources as dependencies
+=== Resources as dependencies
If the bean itself is going to determine and supply the resource path through some sort
of dynamic process, it probably makes sense for the bean to use the `ResourceLoader`
@@ -8160,12 +8474,12 @@ 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 follows:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
Note that the resource path has no prefix, so because the application context itself is
@@ -8177,16 +8491,16 @@ If there is a need to force a specific `Resource` type to be used, then a prefix
used. The following two examples show how to force a `ClassPathResource` and a
`UrlResource` (the latter being used to access a filesystem file).
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
@@ -8208,20 +8522,20 @@ that path and used to load the bean definitions, depends on and is appropriate t
specific application context. For example, if you create a
`ClassPathXmlApplicationContext` as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
----
The bean definitions will be loaded from the classpath, as a `ClassPathResource` will be
used. But if you create a `FileSystemXmlApplicationContext` as follows:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx =
- new FileSystemXmlApplicationContext("conf/appContext.xml");
+ ApplicationContext ctx =
+ new FileSystemXmlApplicationContext("conf/appContext.xml");
----
The bean definition will be loaded from a filesystem location, in this case relative to
@@ -8231,11 +8545,11 @@ Note that the use of the special classpath prefix or a standard URL prefix on th
location path will override the default type of `Resource` created to load the
definition. So this `FileSystemXmlApplicationContext`...
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx =
- new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
+ ApplicationContext ctx =
+ new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
----
... will actually load its bean definitions from the classpath. However, it is still a
@@ -8255,24 +8569,24 @@ will derive the path information from the supplied class.
An example will hopefully make this clear. Consider a directory layout that looks like
this:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
com/
foo/
- services.xml
- daos.xml
+ services.xml
+ daos.xml
MessengerService.class
----
A `ClassPathXmlApplicationContext` instance composed of the beans defined in the
`'services.xml'` and `'daos.xml'` could be instantiated like so...
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx = new ClassPathXmlApplicationContext(
- new String[] {"services.xml", "daos.xml"}, MessengerService.class);
+ ApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String[] {"services.xml", "daos.xml"}, MessengerService.class);
----
Please do consult the Javadocs for the `ClassPathXmlApplicationContext` class for
@@ -8304,13 +8618,13 @@ a resource points to just one resource at a time.
===== Ant-style Patterns
When the path location contains an Ant-style pattern, for example:
-[source]
+[literal]
[subs="verbatim,quotes"]
----
/WEB-INF/*-context.xml
- com/mycompany/**/applicationContext.xml
- file:C:/some/path/*-context.xml
- classpath:com/mycompany/**/applicationContext.xml
+ com/mycompany/**/applicationContext.xml
+ file:C:/some/path/*-context.xml
+ classpath:com/mycompany/**/applicationContext.xml
----
... the resolver follows a more complex but defined procedure to try to resolve the
@@ -8351,11 +8665,11 @@ environment before you rely on it.
When constructing an XML-based application context, a location string may use the
special `classpath*:` prefix:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx =
- new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
+ ApplicationContext ctx =
+ new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
----
This special prefix specifies that all classpath resources that match the given name
@@ -8398,7 +8712,7 @@ Ant-style patterns with " `classpath:`" resources are not guaranteed to find mat
resources if the root package to search is available in multiple class path locations.
This is because a resource such as
-[source]
+[literal]
[subs="verbatim,quotes"]
----
com/mycompany/package1/service-context.xml
@@ -8406,7 +8720,7 @@ com/mycompany/package1/service-context.xml
may be in only one location, but when a path such as
-[source]
+[literal]
[subs="verbatim,quotes"]
----
classpath:com/mycompany/**/service-context.xml
@@ -8421,7 +8735,7 @@ will search all class path locations that contain the root package.
[[resources-filesystemresource-caveats]]
-==== FileSystemResource caveats
+==== FileSystemResource caveats
A `FileSystemResource` that is not attached to a `FileSystemApplicationContext` (that
is, a `FileSystemApplicationContext` is not the actual `ResourceLoader`) will treat
@@ -8435,54 +8749,54 @@ 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 are equivalent:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx =
- new FileSystemXmlApplicationContext("conf/context.xml");
+ ApplicationContext ctx =
+ new FileSystemXmlApplicationContext("conf/context.xml");
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-ApplicationContext ctx =
- new FileSystemXmlApplicationContext("/conf/context.xml");
+ ApplicationContext ctx =
+ new FileSystemXmlApplicationContext("/conf/context.xml");
----
As are the following: (Even though it would make sense for them to be different, as one
case is relative and the other absolute.)
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-FileSystemXmlApplicationContext ctx = ...;
-ctx.getResource("some/resource/path/myTemplate.txt");
+ FileSystemXmlApplicationContext ctx = ...;
+ ctx.getResource("some/resource/path/myTemplate.txt");
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-FileSystemXmlApplicationContext ctx = ...;
-ctx.getResource("/some/resource/path/myTemplate.txt");
+ FileSystemXmlApplicationContext ctx = ...;
+ ctx.getResource("/some/resource/path/myTemplate.txt");
----
In practice, if true absolute filesystem paths are needed, it is better to forgo the use
of absolute paths with `FileSystemResource` / `FileSystemXmlApplicationContext`, and
just force the use of a `UrlResource`, by using the `file:` URL prefix.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-// actual context type doesn't matter, the Resource will always be UrlResource
-ctx.getResource("file:/some/resource/path/myTemplate.txt");
+ // actual context type doesn't matter, the Resource will always be UrlResource
+ ctx.getResource("file:/some/resource/path/myTemplate.txt");
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-// force this FileSystemXmlApplicationContext to load its definition via a UrlResource
-ApplicationContext ctx =
- new FileSystemXmlApplicationContext("file:/conf/context.xml");
+ // force this FileSystemXmlApplicationContext to load its definition via a UrlResource
+ ApplicationContext ctx =
+ new FileSystemXmlApplicationContext("file:/conf/context.xml");
----
@@ -8496,8 +8810,9 @@ ApplicationContext ctx =
[[validation-introduction]]
-=== IntroductionJSR-303/JSR-349 Bean Validation
+=== Introduction
+.JSR-303/JSR-349 Bean Validation
****
Spring Framework 4.0 supports Bean Validation 1.0 (JSR-303) and Bean Validation 1.1
(JSR-349) in terms of setup support, also adapting it to Spring's `Validator` interface.
@@ -8549,16 +8864,16 @@ validators can report validation failures to the `Errors` object.
Let's consider a small data object:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class Person {
+ public class Person {
- private String name;
- private int age;
+ private String name;
+ private int age;
- // the usual getters and setters...
-}
+ // the usual getters and setters...
+ }
----
We're going to provide validation behavior for the `Person` class by implementing the
@@ -8571,28 +8886,28 @@ following two methods of the `org.springframework.validation.Validator` interfac
Implementing a `Validator` is fairly straightforward, especially when you know of the
`ValidationUtils` helper class that the Spring Framework also provides.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class PersonValidator implements Validator {
+ public class PersonValidator implements Validator {
- /**
- * This Validator validates *just* Person instances
- */
- public boolean supports(Class clazz) {
- return Person.class.equals(clazz);
- }
+ /**
+ * This Validator validates *just* Person instances
+ */
+ public boolean supports(Class clazz) {
+ return Person.class.equals(clazz);
+ }
- public void validate(Object obj, Errors e) {
- ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
- Person p = (Person) obj;
- if (p.getAge() < 0) {
- e.rejectValue("age", "negativevalue");
- } else if (p.getAge() > 110) {
- e.rejectValue("age", "too.darn.old");
- }
- }
-}
+ public void validate(Object obj, Errors e) {
+ ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
+ Person p = (Person) obj;
+ if (p.getAge() < 0) {
+ e.rejectValue("age", "negativevalue");
+ } else if (p.getAge() > 110) {
+ e.rejectValue("age", "too.darn.old");
+ }
+ }
+ }
----
As you can see, the `static` `rejectIfEmpty(..)` method on the `ValidationUtils` class
@@ -8611,44 +8926,44 @@ within the `AddressValidator` class without resorting to copy-and-paste, you can
dependency-inject or instantiate an `AddressValidator` within your `CustomerValidator`,
and use it like so:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class CustomerValidator implements Validator {
+ public class CustomerValidator implements Validator {
- private final Validator addressValidator;
+ private final Validator addressValidator;
- public CustomerValidator(Validator addressValidator) {
- if (addressValidator == null) {
- throw new IllegalArgumentException(
- "The supplied [Validator] is required and must not be null.");
- }
- if (!addressValidator.supports(Address.class)) {
- throw new IllegalArgumentException(
- "The supplied [Validator] must support the validation of [Address] instances.");
- }
- this.addressValidator = addressValidator;
- }
+ public CustomerValidator(Validator addressValidator) {
+ if (addressValidator == null) {
+ throw new IllegalArgumentException("The supplied [Validator] is " +
+ "required and must not be null.");
+ }
+ if (!addressValidator.supports(Address.class)) {
+ throw new IllegalArgumentException("The supplied [Validator] must " +
+ support the validation of [Address] instances.");
+ }
+ this.addressValidator = addressValidator;
+ }
- /**
- * This Validator validates Customer instances, and any subclasses of Customer too
- */
- public boolean supports(Class clazz) {
- return Customer.class.isAssignableFrom(clazz);
- }
+ /**
+ * This Validator validates Customer instances, and any subclasses of Customer too
+ */
+ public boolean supports(Class clazz) {
+ return Customer.class.isAssignableFrom(clazz);
+ }
- public void validate(Object target, Errors errors) {
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
- ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
- Customer customer = (Customer) target;
- try {
- errors.pushNestedPath("address");
- ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
- } finally {
- errors.popNestedPath();
- }
- }
-}
+ public void validate(Object target, Errors errors) {
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
+ Customer customer = (Customer) target;
+ try {
+ errors.pushNestedPath("address");
+ ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
+ } finally {
+ errors.popNestedPath();
+ }
+ }
+ }
----
Validation errors are reported to the `Errors` object passed to the validator. In case
@@ -8680,9 +8995,9 @@ convenience to aid developers in targeting error messages and suchlike.
More information on the `MessageCodesResolver` and the default strategy can be found
online with the Javadocs for
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/MessageCodesResolver.html[MessageCodesResolver]
+{javadoc-baseurl}/org/springframework/validation/MessageCodesResolver.html[MessageCodesResolver]
and
-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/DefaultMessageCodesResolver.html[DefaultMessageCodesResolver]
+{javadoc-baseurl}/org/springframework/validation/DefaultMessageCodesResolver.html[DefaultMessageCodesResolver]
respectively.
@@ -8755,70 +9070,79 @@ and their out-of-the-box implementation, you should skip ahead to the section ab
Consider the following two classes:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class Company {
- private String name;
- private Employee managingDirector;
+ public class Company {
- public String getName() {
- return this.name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Employee getManagingDirector() {
- return this.managingDirector;
- }
- public void setManagingDirector(Employee managingDirector) {
- this.managingDirector = managingDirector;
- }
-}
+ private String name;
+ private Employee managingDirector;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Employee getManagingDirector() {
+ return this.managingDirector;
+ }
+
+ public void setManagingDirector(Employee managingDirector) {
+ this.managingDirector = managingDirector;
+ }
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class Employee {
- private String name;
- private float salary;
+ public class Employee {
- public String getName() {
- return this.name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public float getSalary() {
- return salary;
- }
- public void setSalary(float salary) {
- this.salary = salary;
- }
-}
+ private String name;
+
+ private float salary;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public float getSalary() {
+ return salary;
+ }
+
+ public void setSalary(float salary) {
+ this.salary = salary;
+ }
+ }
----
The following code snippets show some examples of how to retrieve and manipulate some of
the properties of instantiated `Companies` and `Employees`:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-BeanWrapper company = BeanWrapperImpl(new Company());
-// setting the company name..
-company.setPropertyValue("name", "Some Company Inc.");
-// ... can also be done like this:
-PropertyValue value = new PropertyValue("name", "Some Company Inc.");
-company.setPropertyValue(value);
+ BeanWrapper company = BeanWrapperImpl(new Company());
+ // setting the company name..
+ company.setPropertyValue("name", "Some Company Inc.");
+ // ... can also be done like this:
+ PropertyValue value = new PropertyValue("name", "Some Company Inc.");
+ company.setPropertyValue(value);
-// ok, let's create the director and tie it to the company:
-BeanWrapper jim = BeanWrapperImpl(new Employee());
-jim.setPropertyValue("name", "Jim Stravinsky");
-company.setPropertyValue("managingDirector", jim.getWrappedInstance());
+ // ok, let's create the director and tie it to the company:
+ BeanWrapper jim = BeanWrapperImpl(new Employee());
+ jim.setPropertyValue("name", "Jim Stravinsky");
+ company.setPropertyValue("managingDirector", jim.getWrappedInstance());
-// retrieving the salary of the managingDirector through the company
-Float salary = (Float) company.getPropertyValue("managingDirector.salary");
+ // retrieving the salary of the managingDirector through the company
+ Float salary = (Float) company.getPropertyValue("managingDirector.salary");
----
@@ -8929,14 +9253,14 @@ name as that class, with `'Editor'` appended; for example, one could have the fo
class and package structure, which would be sufficient for the `FooEditor` class to be
recognized and used as the `PropertyEditor` for `Foo`-typed properties.
-[source]
+[literal]
[subs="verbatim,quotes"]
----
com
chank
pop
Foo
- FooEditor // the PropertyEditor for the Foo class
+ FooEditor // the PropertyEditor for the Foo class
----
Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well
@@ -8946,39 +9270,39 @@ not-amazing-detail here]). Find below an example of using the `BeanInfo` mechani
explicitly registering one or more `PropertyEditor` instances with the properties of an
associated class.
-[source]
+[literal]
[subs="verbatim,quotes"]
----
com
chank
pop
Foo
- FooBeanInfo // the BeanInfo for the Foo class
+ FooBeanInfo // the BeanInfo for the Foo class
----
Here is the Java source code for the referenced `FooBeanInfo` class. This would
associate a `CustomNumberEditor` with the `age` property of the `Foo` class.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public class FooBeanInfo extends SimpleBeanInfo {
+ public class FooBeanInfo extends SimpleBeanInfo {
- public PropertyDescriptor[] getPropertyDescriptors() {
- try {
- final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true);
- PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Foo.class) {
- public PropertyEditor createPropertyEditor(Object bean) {
- return numberPE;
- };
- };
- return new PropertyDescriptor[] { ageDescriptor };
- }
- catch (IntrospectionException ex) {
- throw new Error(ex.toString());
- }
- }
-}
+ public PropertyDescriptor[] getPropertyDescriptors() {
+ try {
+ final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true);
+ PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Foo.class) {
+ public PropertyEditor createPropertyEditor(Object bean) {
+ return numberPE;
+ };
+ };
+ return new PropertyDescriptor[] { ageDescriptor };
+ }
+ catch (IntrospectionException ex) {
+ throw new Error(ex.toString());
+ }
+ }
+ }
----
@@ -9019,71 +9343,71 @@ support for additional `PropertyEditor` instances to an `ApplicationContext`.
Consider a user class `ExoticType`, and another class `DependsOnExoticType` which needs
`ExoticType` set as a property:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package example;
+ package example;
-public class ExoticType {
+ public class ExoticType {
- private String name;
+ private String name;
- public ExoticType(String name) {
- this.name = name;
- }
-}
+ public ExoticType(String name) {
+ this.name = name;
+ }
+ }
-public class DependsOnExoticType {
+ public class DependsOnExoticType {
- private ExoticType type;
+ private ExoticType type;
- public void setType(ExoticType type) {
- this.type = type;
- }
-}
+ public void setType(ExoticType type) {
+ this.type = type;
+ }
+ }
----
When things are properly set up, we want to be able to assign the type property as a
string, which a `PropertyEditor` will behind the scenes convert into an actual
`ExoticType` instance:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
+
+
+
----
The `PropertyEditor` implementation could look similar to this:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-// converts string representation to ExoticType object
-package example;
+ // converts string representation to ExoticType object
+ package example;
-public class ExoticTypeEditor extends PropertyEditorSupport {
+ public class ExoticTypeEditor extends PropertyEditorSupport {
- public void setAsText(String text) {
- setValue(new ExoticType(text.toUpperCase()));
- }
-}
+ public void setAsText(String text) {
+ setValue(new ExoticType(text.toUpperCase()));
+ }
+ }
----
Finally, we use `CustomEditorConfigurer` to register the new `PropertyEditor` with the
`ApplicationContext`, which will then be able to use it as needed:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
+
+
+
+
+
----
[[beans-beans-conversion-customeditor-registration-per]]
@@ -9106,21 +9430,21 @@ instances for each bean creation attempt.
Using a `PropertyEditorRegistrar` is perhaps best illustrated with an example. First
off, you need to create your own `PropertyEditorRegistrar` implementation:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package com.foo.editors.spring;
+ package com.foo.editors.spring;
-public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
+ public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
- public void registerCustomEditors(PropertyEditorRegistry registry) {
+ public void registerCustomEditors(PropertyEditorRegistry registry) {
- // it is expected that new PropertyEditor instances are created
- registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());
+ // it is expected that new PropertyEditor instances are created
+ registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());
- // you could register as many custom property editors as are required here...
- }
-}
+ // you could register as many custom property editors as are required here...
+ }
+ }
----
See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an example
@@ -9130,19 +9454,19 @@ See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an
Next we configure a `CustomEditorConfigurer` and inject an instance of our
`CustomPropertyEditorRegistrar` into it:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
----
Finally, and in a bit of a departure from the focus of this chapter, for those of you
@@ -9151,24 +9475,24 @@ conjunction with data-binding `Controllers` (such as `SimpleFormController`) can
convenient. Find below an example of using a `PropertyEditorRegistrar` in the
implementation of an `initBinder(..)` method:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public final class RegisterUserController extends SimpleFormController {
+ public final class RegisterUserController extends SimpleFormController {
- private final PropertyEditorRegistrar customPropertyEditorRegistrar;
+ private final PropertyEditorRegistrar customPropertyEditorRegistrar;
- public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) {
- this.customPropertyEditorRegistrar = propertyEditorRegistrar;
- }
+ public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) {
+ this.customPropertyEditorRegistrar = propertyEditorRegistrar;
+ }
- protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
- throws Exception {
- **this.customPropertyEditorRegistrar.registerCustomEditors(binder);**
- }
+ protected void initBinder(HttpServletRequest request,
+ ServletRequestDataBinder binder) throws Exception {
+ **this.customPropertyEditorRegistrar.registerCustomEditors(binder);**
+ }
- // other methods to do with registering a User
-}
+ // other methods to do with registering a User
+ }
----
This style of `PropertyEditor` registration can lead to concise code (the implementation
@@ -9180,7 +9504,7 @@ registration code to be encapsulated in a class and then shared amongst as many
[[core-convert]]
-=== Spring 3 Type Conversion
+=== Spring Type Conversion
Spring 3 introduces a `core.convert` package that provides a general type conversion
system. The system defines an SPI to implement type conversion logic, as well as an API
to execute type conversions at runtime. Within a Spring container, this system can be
@@ -9194,16 +9518,16 @@ application where type conversion is needed.
==== Converter SPI
The SPI to implement type conversion logic is simple and strongly typed:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.core.convert.converter;
+ package org.springframework.core.convert.converter;
-public interface Converter {
+ public interface Converter {
- T convert(S source);
+ T convert(S source);
-}
+ }
----
To create your own Converter, simply implement the interface above. Parameterize S as
@@ -9217,18 +9541,18 @@ Several converter implementations are provided in the `core.convert.support` pac
a convenience. These include converters from Strings to Numbers and other common types.
Consider `StringToInteger` as an example Converter implementation:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.core.convert.support;
+ package org.springframework.core.convert.support;
-final class StringToInteger implements Converter {
+ final class StringToInteger implements Converter {
- public Integer convert(String source) {
- return Integer.valueOf(source);
- }
+ public Integer convert(String source) {
+ return Integer.valueOf(source);
+ }
-}
+ }
----
@@ -9239,16 +9563,16 @@ When you need to centralize the conversion logic for an entire class hierarchy,
example, when converting from String to java.lang.Enum objects, implement
`ConverterFactory`:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.core.convert.converter;
+ package org.springframework.core.convert.converter;
-public interface ConverterFactory {
+ public interface ConverterFactory {
- Converter getConverter(Class targetType);
+ Converter getConverter(Class targetType);
-}
+ }
----
Parameterize S to be the type you are converting from and R to be the base type defining
@@ -9257,30 +9581,30 @@ where T is a subclass of R.
Consider the `StringToEnum` ConverterFactory as an example:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.core.convert.support;
+ package org.springframework.core.convert.support;
-final class StringToEnumConverterFactory implements ConverterFactory {
+ final class StringToEnumConverterFactory implements ConverterFactory {
- public Converter getConverter(Class targetType) {
- return new StringToEnumConverter(targetType);
- }
+ public Converter getConverter(Class targetType) {
+ return new StringToEnumConverter(targetType);
+ }
- private final class StringToEnumConverter implements Converter {
+ private final class StringToEnumConverter implements Converter {
- private Class enumType;
+ private Class enumType;
- public StringToEnumConverter(Class enumType) {
- this.enumType = enumType;
- }
+ public StringToEnumConverter(Class enumType) {
+ this.enumType = enumType;
+ }
- public T convert(String source) {
- return (T) Enum.valueOf(this.enumType, source.trim());
- }
- }
-}
+ public T convert(String source) {
+ return (T) Enum.valueOf(this.enumType, source.trim());
+ }
+ }
+ }
----
@@ -9294,18 +9618,18 @@ GenericConverter makes available source and target field context you can use whe
implementing your conversion logic. Such context allows a type conversion to be driven
by a field annotation, or generic information declared on a field signature.
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.core.convert.converter;
+ package org.springframework.core.convert.converter;
-public interface GenericConverter {
+ public interface GenericConverter {
- public Set getConvertibleTypes();
+ public Set getConvertibleTypes();
- Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
+ Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
-}
+ }
----
To implement a GenericConverter, have getConvertibleTypes() return the supported
@@ -9336,14 +9660,14 @@ such as static valueOf method, is defined on the target class.
ConditionalGenericConverter is an subinterface of GenericConverter that allows you to
define such custom matching criteria:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface ConditionalGenericConverter extends GenericConverter {
+ public interface ConditionalGenericConverter extends GenericConverter {
- boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
+ boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
-}
+ }
----
A good example of a ConditionalGenericConverter is an EntityConverter that converts
@@ -9359,22 +9683,22 @@ matches(TypeDescriptor, TypeDescriptor).
The ConversionService defines a unified API for executing type conversion logic at
runtime. Converters are often executed behind this facade interface:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.core.convert;
+ package org.springframework.core.convert;
-public interface ConversionService {
+ public interface ConversionService {
- boolean canConvert(Class> sourceType, Class> targetType);
+ boolean canConvert(Class> sourceType, Class> targetType);
- T convert(Object source, Class targetType);
+ T convert(Object source, Class targetType);
- boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
+ boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
- Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
+ Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
-}
+ }
----
Most ConversionService implementations also implement `ConverterRegistry`, which
@@ -9406,11 +9730,11 @@ system is used.
To register a default ConversionService with Spring, add the following bean definition
with id `conversionService`:
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
+
----
A default ConversionService can convert between strings, numbers, enums, collections,
@@ -9418,17 +9742,17 @@ maps, and other common types. To supplement or override the default converters w
own custom converter(s), set the `converters` property. Property values may implement
either of the Converter, ConverterFactory, or GenericConverter interfaces.
-[source,xml]
+[source,xml,indent=0]
[subs="verbatim,quotes"]
----
-
-
-
-
-
-
-
+
+
+
+
+
+
+
----
It is also common to use a ConversionService within a Spring MVC application. See
@@ -9445,28 +9769,28 @@ In certain situations you may wish to apply formatting during conversion. See
To work with a ConversionService instance programmatically, simply inject a reference to
it like you would for any other bean:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-@Service
-public class MyService {
+ @Service
+ public class MyService {
- @Autowired
- public MyService(ConversionService conversionService) {
- this.conversionService = conversionService;
- }
+ @Autowired
+ public MyService(ConversionService conversionService) {
+ this.conversionService = conversionService;
+ }
- public void doIt() {
- this.conversionService.convert(...)
- }
-}
+ public void doIt() {
+ this.conversionService.convert(...)
+ }
+ }
----
[[format]]
-=== Spring 3 Field Formatting
+=== Spring Field Formatting
As discussed in the previous section, <> is a
general-purpose type conversion system. It provides a unified ConversionService API as
well as a strongly-typed Converter SPI for implementing conversion logic from one type
@@ -9496,33 +9820,33 @@ ConversionService provides a unified type conversion API for both SPIs.
==== Formatter SPI
The Formatter SPI to implement field formatting logic is simple and strongly typed:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.format;
+ package org.springframework.format;
-public interface Formatter extends Printer, Parser {
-}
+ public interface Formatter extends Printer, Parser {
+ }
----
Where Formatter extends from the Printer and Parser building-block interfaces:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public interface Printer {
- String print(T fieldValue, Locale locale);
-}
+ public interface Printer {
+ String print(T fieldValue, Locale locale);
+ }
----
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-import java.text.ParseException;
+ import java.text.ParseException;
-public interface Parser {
- T parse(String clientValue, Locale locale) throws ParseException;
-}
+ public interface Parser {
+ T parse(String clientValue, Locale locale) throws ParseException;
+ }
----
To create your own Formatter, simply implement the Formatter interface above.
@@ -9534,48 +9858,48 @@ should throw a ParseException or IllegalArgumentException if a parse attempt fai
care to ensure your Formatter implementation is thread-safe.
Several Formatter implementations are provided in `format` subpackages as a convenience.
-The `number` package provides a NumberFormatter, CurrencyFormatter, and PercentFormatter
-to format java.lang.Number objects using a java.text.NumberFormat. The `datetime`
-package provides a DateFormatter to format java.util.Date objects with a
-java.text.DateFormat. The `datetime.joda` package provides comprehensive datetime
+The `number` package provides a `NumberFormatter`, `CurrencyFormatter`, and
+`PercentFormatter` to format `java.lang.Number` objects using a `java.text.NumberFormat`.
+The `datetime` package provides a `DateFormatter` to format `java.util.Date` objects with
+a `java.text.DateFormat`. The `datetime.joda` package provides comprehensive datetime
formatting support based on the http://joda-time.sourceforge.net[Joda Time library].
Consider `DateFormatter` as an example `Formatter` implementation:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.format.datetime;
+ package org.springframework.format.datetime;
-public final class DateFormatter implements Formatter {
+ public final class DateFormatter implements Formatter {
- private String pattern;
+ private String pattern;
- public DateFormatter(String pattern) {
- this.pattern = pattern;
- }
+ public DateFormatter(String pattern) {
+ this.pattern = pattern;
+ }
- public String print(Date date, Locale locale) {
- if (date == null) {
- return "";
- }
- return getDateFormat(locale).format(date);
- }
+ public String print(Date date, Locale locale) {
+ if (date == null) {
+ return "";
+ }
+ return getDateFormat(locale).format(date);
+ }
- public Date parse(String formatted, Locale locale) throws ParseException {
- if (formatted.length() == 0) {
- return null;
- }
- return getDateFormat(locale).parse(formatted);
- }
+ public Date parse(String formatted, Locale locale) throws ParseException {
+ if (formatted.length() == 0) {
+ return null;
+ }
+ return getDateFormat(locale).parse(formatted);
+ }
- protected DateFormat getDateFormat(Locale locale) {
- DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale);
- dateFormat.setLenient(false);
- return dateFormat;
- }
+ protected DateFormat getDateFormat(Locale locale) {
+ DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale);
+ dateFormat.setLenient(false);
+ return dateFormat;
+ }
-}
+ }
----
The Spring team welcomes community-driven Formatter contributions; see
@@ -9588,20 +9912,20 @@ http://jira.springframework.org[http://jira.springframework.org] to contribute.
As you will see, field formatting can be configured by field type or annotation. To bind
an Annotation to a formatter, implement AnnotationFormatterFactory:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-package org.springframework.format;
+ package org.springframework.format;
-public interface AnnotationFormatterFactory {
+ public interface AnnotationFormatterFactory {
- Set> getFieldTypes();
+ Set> getFieldTypes();
- Printer> getPrinter(A annotation, Class> fieldType);
+ Printer> getPrinter(A annotation, Class> fieldType);
- Parser> getParser(A annotation, Class> fieldType);
+ Parser> getParser(A annotation, Class> fieldType);
-}
+ }
----
Parameterize A to be the field annotationType you wish to associate formatting logic
@@ -9614,55 +9938,55 @@ The example AnnotationFormatterFactory implementation below binds the @NumberFor
Annotation to a formatter. This annotation allows either a number style or pattern to be
specified:
-[source,java]
+[source,java,indent=0]
[subs="verbatim,quotes"]
----
-public final class NumberFormatAnnotationFormatterFactory
- implements AnnotationFormatterFactory {
+ public final class NumberFormatAnnotationFormatterFactory
+ implements AnnotationFormatterFactory {
- public Set> getFieldTypes() {
- return new HashSet>(asList(new Class>[] {
- Short.class, Integer.class, Long.class, Float.class,
- Double.class, BigDecimal.class, BigInteger.class }));
- }
+ public Set> getFieldTypes() {
+ return new HashSet