diff --git a/spring-framework-reference/src/beans-annotation-config.xml b/spring-framework-reference/src/beans-annotation-config.xml new file mode 100644 index 00000000000..4a19f60078d --- /dev/null +++ b/spring-framework-reference/src/beans-annotation-config.xml @@ -0,0 +1,804 @@ + + +
+ 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 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 while others argue + that annotated classes are no longer POJOs and, furthermore, that the + configuration becomes decentralized and harder to control. + + No matter the choice, Spring can accommodate both styles and even mix + them together. It's worth pointing out that through its JavaConfig option, Spring allows 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 SpringSource Tool Suite. + + + An alternative to XML setups is provided by annotation-based + configuration which rely on the bytecode metadata for wiring up components + instead of angle-bracket declarations. Instead of using XML to describe a + bean wiring, the developer moves the configuration into the component class + itself by using annotations on the relevant class, method, or field + declaration. As mentioned in , using a + BeanPostProcessor in conjunction with + annotations is a common means of extending the Spring IoC container. For + example, Spring 2.0 introduced the possibility of enforcing required + properties with the @Required annotation. As of Spring 2.5, it is now possible to follow + that same general approach to drive Spring's dependency injection. + Essentially, the @Autowired annotation + provides the same capabilities as described in but with more fine-grained control and + wider applicability. Spring 2.5 also adds support for JSR-250 annotations + such as @Resource, + @PostConstruct, and + @PreDestroy. Spring 3.0 adds support for + JSR-330 (Dependency Injection for Java) annotations contained in the + javax.inject package such as @Inject, + @Qualifier, @Named, and @Provider if the JSR330 jar is + present on the classpath. Use of these annotations also requires that + certain BeanPostProcessors be registered + within the Spring container. Annotation injection is performed + before XML injection, thus the latter configuration + will override the former for properties wired through both approaches. + As always, you can register them as individual bean definitions, but + they can also be implicitly registered by including the following tag in an + XML-based Spring configuration (notice the inclusion of the + context namespace): + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:annotation-config/> + +</beans> + + (The implicitly registered post-processors include AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor, as + well as the aforementioned RequiredAnnotationBeanPostProcessor.) + + + <context:annotation-config/> only looks for + annotations on beans in the same application context in which it is + defined. This means that, if you put + <context:annotation-config/> in a + WebApplicationContext for a + DispatcherServlet, it only checks for + @Autowired beans in your controllers, and + not your services. See for more + information. + + +
+ <interfacename>@Required</interfacename> + + The @Required annotation applies to + bean property setter methods, as in the following example: + + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Required + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... +} + + This annotation simply indicates that the affected bean property must + be populated at configuration time, through an explicit property value in + a bean definition or through autowiring. The container throws an exception + if the affected bean property has not been populated; this allows for + eager and explicit failure, avoiding + NullPointerExceptions or the like later on. It is + still recommended that you put assertions into the bean class itself, for + example, into an init method. Doing so enforces those required references + and values even when you use the class outside of a container. +
+ +
+ <interfacename>@Autowired and @Inject</interfacename> + + As expected, you can apply the + @Autowired annotation to "traditional" + setter methods: + + + JSR 330's @Inject annotation can be used in place of Spring's + @Autowired in the examples below. + @Inject does not have a required property + unlike Spring's @Autowired annotation + which has a required property to indicate if the + value being injected is optional. This behavior is enabled automatically + if you have the JSR 330 JAR on the classpath. + + + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Autowired + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... +} + + You can also apply the annotation to methods with arbitrary names + and/or multiple arguments: + + public class MovieRecommender { + + private MovieCatalog movieCatalog; + + private CustomerPreferenceDao customerPreferenceDao; + + @Autowired + public void prepare(MovieCatalog movieCatalog, + CustomerPreferenceDao customerPreferenceDao) { + this.movieCatalog = movieCatalog; + this.customerPreferenceDao = customerPreferenceDao; + } + + // ... +} + + You can apply @Autowired to + constructors and fields: + + public class MovieRecommender { + + @Autowired + private MovieCatalog movieCatalog; + + private 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: + + public class MovieRecommender { + + @Autowired + private MovieCatalog[] movieCatalogs; + + // ... +} + + The same applies for typed collections: + + public class MovieRecommender { + + private Set<MovieCatalog> movieCatalogs; + + @Autowired + public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) { + this.movieCatalogs = movieCatalogs; + } + + // ... +} + + 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: + + public class MovieRecommender { + + private Map<String, MovieCatalog> movieCatalogs; + + @Autowired + public void setMovieCatalogs(Map<String, MovieCatalog> 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. + + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Autowired(required=false) + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... +} + + + Only one annotated constructor per-class can be + marked as required, but multiple non-required + constructors can be annotated. In that case, each is considered among + the candidates and Spring uses the greediest + constructor whose dependencies can be satisfied, that is the constructor + that has the largest number of arguments. + + @Autowired's + required attribute is recommended over the + @Required annotation. The + required attribute indicates that the property is + not required for autowiring purposes, the property is ignored if it + cannot be autowired. @Required, on the + other hand, is stronger in that it enforces the property that was set by + any means supported by the container. If no value is injected, a + corresponding exception is raised. + + + You can also use @Autowired for + interfaces that are well-known resolvable dependencies: + BeanFactory, + ApplicationContext, + ResourceLoader, + ApplicationEventPublisher, and + MessageSource. These interfaces and their + extended interfaces, such as + ConfigurableApplicationContext or + ResourcePatternResolver, are automatically + resolved, with no special setup necessary. + + public class MovieRecommender { + + @Autowired + private ApplicationContext context; + + public MovieRecommender() { + } + + // ... +} +
+ +
+ Fine-tuning annotation-based autowiring with qualifiers + + Because autowiring by type may lead to multiple candidates, it is + often necessary to have more control over the selection process. One way + to accomplish this is with Spring's + @Qualifier annotation. You can associate + qualifier values with specific 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: + + + JSR 330's @Qualifier annotation can + only be applied as a meta-annotation unlike Spring's @Qualifier which + takes a string property to discriminate among multiple injection + candidates and can be placed on annotations as well as types, fields, + methods, constructors, and parameters. + + + public class MovieRecommender { + + @Autowired + @Qualifier("main") + private MovieCatalog movieCatalog; + + // ... +} + + The @Qualifier annotation can also be + specified on individual constructor arguments or method parameters: + + public class MovieRecommender { + + private MovieCatalog movieCatalog; + + private 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. + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:annotation-config/> + + <bean class="example.SimpleMovieCatalog"> + <qualifier value="main"/> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean class="example.SimpleMovieCatalog"> + <qualifier value="action"/> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean id="movieRecommender" class="example.MovieRecommender"/> + +</beans> + + + For a fallback match, the bean name is considered a default qualifier + value. Thus you can define the bean with an id "main" instead of the + nested qualifier element, leading to the same matching result. However, + although you can use this convention to refer to specific beans by name, + @Autowired is fundamentally about + type-driven injection with optional semantic qualifiers. This means that + qualifier values, even with the bean name fallback, always have narrowing + semantics within the set of type matches; they do not semantically express + a reference to a unique bean id. Good qualifier values are "main" or + "EMEA" or "persistent", expressing characteristics of a specific component + that are independent from the bean id, which may be auto-generated in case + of an anonymous bean definition like the one in the preceding + example. + + Qualifiers also apply to typed collections, as discussed above, for + example, to Set<MovieCatalog>. In this case, all + matching beans according to the declared qualifiers are injected as a + collection. This implies that qualifiers do not have to be unique; they + rather simply constitute filtering criteria. For example, you can define + multiple MovieCatalog beans with the same qualifier + value "action"; all of which would be injected into a + Set<MovieCatalog> annotated with + @Qualifier("action"). + + + If you intend to express annotation-driven injection by name, do not + primarily use @Autowired, even if is + technically capable of referring to a bean name through + @Qualifier values. Instead, use the + JSR-250 @Resource annotation, which is + semantically defined to identify a specific target component by its + unique name, with the declared type being irrelevant for the matching + process. + + As a specific consequence of this semantic difference, beans that + are themselves defined as a collection or map type cannot be injected + through @Autowired, because type matching + is not properly applicable to them. Use + @Resource for such beans, referring to + the specific collection or map bean by unique name. + + @Autowired applies to fields, + constructors, and multi-argument methods, allowing for narrowing through + qualifier annotations at the parameter level. By contrast, + @Resource is supported only for fields + and bean property setter methods with a single argument. As a + consequence, stick with qualifiers if your injection target is a + constructor or a multi-argument method. + + + You can create your own custom qualifier annotations. Simply define an + annotation and provide the @Qualifier + annotation within your definition: + + + You can use JSR 330's @Qualifier + annotation in the manner described below in place of + Spring's @Qualifier annotation. This + behavior is enabled automatically if you have the JSR 330 jar on the + classpath. + + + @Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface Genre { + + String value(); +} + + Then you can provide the custom qualifier on autowired fields and + parameters: + + public class MovieRecommender { + + @Autowired + @Genre("Action") + private MovieCatalog actionCatalog; + + private MovieCatalog comedyCatalog; + + @Autowired + public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) { + this.comedyCatalog = comedyCatalog; + } + + // ... +} + + Next, provide the information for the candidate bean definitions. You + can add <qualifier/> tags as sub-elements of the + <bean/> tag and then specify the + type and value to match your custom + qualifier annotations. The type is matched against the 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. + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:annotation-config/> + + <bean class="example.SimpleMovieCatalog"> + <qualifier type="Genre" value="Action"/> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean class="example.SimpleMovieCatalog"> + <qualifier type="example.Genre" value="Comedy"/> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean id="movieRecommender" class="example.MovieRecommender"/> + +</beans> + + + In , you will see an + annotation-based alternative to providing the qualifier metadata in XML. + Specifically, see . + + In some cases, it may be sufficient to use an annotation without a + value. This may be useful when the annotation serves a more generic + purpose and can be applied across several different types of dependencies. + For example, you may provide an offline catalog that + would be searched when no Internet connection is available. First define + the simple annotation: + + @Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface Offline { + +} + + Then add the annotation to the field or property to be + autowired: + + public class MovieRecommender { + + @Autowired + @Offline + private MovieCatalog offlineCatalog; + + // ... +} + + Now the bean definition only needs a qualifier + type: + + <bean class="example.SimpleMovieCatalog"> + <qualifier type="Offline"/> + <!-- inject any dependencies required by this bean --> +</bean> + + You can also define custom qualifier annotations that accept named + attributes in addition to or instead of the simple + value attribute. If multiple attribute values are then + specified on a field or parameter to be autowired, a bean definition must + match all such attribute values to be considered an + autowire candidate. As an example, consider the following annotation + definition: + + @Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface MovieQualifier { + + String genre(); + + Format format(); +} + + In this case Format is an enum: + + 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. + + public class MovieRecommender { + + @Autowired + @MovieQualifier(format=Format.VHS, genre="Action") + private MovieCatalog actionVhsCatalog; + + @Autowired + @MovieQualifier(format=Format.VHS, genre="Comedy") + private MovieCatalog comedyVhsCatalog; + + @Autowired + @MovieQualifier(format=Format.DVD, genre="Action") + private MovieCatalog actionDvdCatalog; + + @Autowired + @MovieQualifier(format=Format.BLURAY, genre="Comedy") + private MovieCatalog comedyBluRayCatalog; + + // ... +} + + Finally, the bean definitions should contain matching qualifier + values. This example also demonstrates that bean meta + attributes may be used instead of the + <qualifier/> sub-elements. If available, the + <qualifier/> and its attributes take precedence, + but the autowiring mechanism falls back on the values provided within the + <meta/> tags if no such qualifier is present, as + in the last two bean definitions in the following example. + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:annotation-config/> + + <bean class="example.SimpleMovieCatalog"> + <qualifier type="MovieQualifier"> + <attribute key="format" value="VHS"/> + <attribute key="genre" value="Action"/> + </qualifier> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean class="example.SimpleMovieCatalog"> + <qualifier type="MovieQualifier"> + <attribute key="format" value="VHS"/> + <attribute key="genre" value="Comedy"/> + </qualifier> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean class="example.SimpleMovieCatalog"> + <meta key="format" value="DVD"/> + <meta key="genre" value="Action"/> + <!-- inject any dependencies required by this bean --> + </bean> + + <bean class="example.SimpleMovieCatalog"> + <meta key="format" value="BLURAY"/> + <meta key="genre" value="Comedy"/> + <!-- inject any dependencies required by this bean --> + </bean> + +</beans> +
+ +
+ <classname>CustomAutowireConfigurer</classname> + + The 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. + + <bean id="customAutowireConfigurer" + class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"> + <property name="customQualifierTypes"> + <set> + <value>example.CustomQualifier</value> + </set> + </property> +</bean> + + 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 <beans/> element. In Java 5 or + later, the presence of @Qualifier + annotations and any custom annotations registered with the + CustomAutowireConfigurer will also play a + role. + + 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. +
+ +
+ <interfacename>@Resource</interfacename> + + 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 in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring supports + this pattern for Spring-managed objects as well. + + @Resource takes a name attribute, and + by default Spring interprets that value as the bean name to be injected. + In other words, it follows by-name semantics, as + demonstrated in this example: + + public class SimpleMovieLister { + + private 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 setter method. In case of a field, it takes the field + name; in case of a setter method, it takes the bean property name. So the + following example is going to have the bean with name "movieFinder" + injected into its setter method: + + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Resource + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } +} + + + 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 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. + + + In the exclusive case of @Resource + usage with no explicit name specified, and similar to + @Autowired, + @Resource finds a primary type match + instead of a specific named bean and resolves well-known resolvable + dependencies: the + BeanFactory, + ApplicationContext, ResourceLoader, + ApplicationEventPublisher, and + MessageSource interfaces. + + Thus in the following example, the + customerPreferenceDao field first looks for a bean + named customerPreferenceDao, then falls back to a primary type match for + the type CustomerPreferenceDao. The "context" field + is injected based on the known resolvable dependency type + ApplicationContext. + + public class MovieRecommender { + + @Resource + private CustomerPreferenceDao customerPreferenceDao; + + @Resource + private ApplicationContext context; + + public MovieRecommender() { + } + + // ... +} +
+ +
+ <interfacename>@PostConstruct</interfacename> and + <interfacename>@PreDestroy</interfacename> + + The CommonAnnotationBeanPostProcessor not only + recognizes the @Resource annotation but + also the JSR-250 lifecycle annotations. Introduced in + Spring 2.5, the support for these annotations offers yet another + alternative to those described in initialization + callbacks and destruction + callbacks. Provided that the + CommonAnnotationBeanPostProcessor is registered + within the Spring ApplicationContext, a + method carrying one of these annotations is invoked at the same 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. + + public class CachingMovieLister { + + @PostConstruct + public void populateMovieCache() { + // populates the movie cache upon initialization... + } + + @PreDestroy + public void clearMovieCache() { + // clears the movie cache upon destruction... + } +} + + + For details about the effects of combining various lifecycle + mechanisms, see . + +
+
diff --git a/spring-framework-reference/src/beans-classpath-scanning.xml b/spring-framework-reference/src/beans-classpath-scanning.xml new file mode 100644 index 00000000000..52e5f4e851b --- /dev/null +++ b/spring-framework-reference/src/beans-classpath-scanning.xml @@ -0,0 +1,510 @@ + + +
+ Classpath scanning and managed components + + + + Most examples foo bar in this chapter use XML to specify the + configuration metadata that produces each + BeanDefinition within the Spring container. + The previous section () + demonstrates how to provide a lot of the configuration metadata through + source-level annotations. Even in those examples, however, the "base" bean + definitions are explicitly defined in the XML file, while the annotations + only drive the dependency injection. This section describes an option for + implicitly detecting the candidate components by + scanning the classpath. Candidate components are classes that match against + a filter criteria and have a corresponding bean definition registered with + the container. This removes the need to use XML to perform bean + registration, instead you can use annotations (for example @Component), + AspectJ type expressions, or your own custom filter criteria to select which + classes will have bean definitions registered with the container. + + + Starting with Spring 3.0, many features provided by the Spring JavaConfig + project are part of the core Spring Framework. This allows you to + define beans using Java rather than using the traditional XML files. Take + a look at the @Configuration, + @Bean, + @Import, and + @DependsOn annotations for examples of how + to use these new features. + + +
+ <interfacename>@Component</interfacename> 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 + . + + Spring 2.5 introduces 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 layers, + respectively. Therefore, you can annotate your component classes with + @Component, but by annotating them with + @Repository, + @Service, or + @Controller instead, your classes are more + properly suited for processing by tools or associating with aspects. For + example, these stereotype annotations make ideal targets for pointcuts. It + is also possible that @Repository, + @Service, and + @Controller may carry additional semantics + in future releases of the Spring Framework. Thus, if you are choosing + between using @Component or + @Service for your service layer, + @Service is clearly the better choice. + Similarly, as stated above, @Repository is + already supported as a marker for automatic exception translation in your + persistence layer. +
+ +
+ Automatically detecting classes and registering bean + definitions + + Spring can automatically detect stereotyped classes and register + corresponding BeanDefinitions with the + ApplicationContext. For example, the + following two classes are eligible for such autodetection: + + @Service +public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Autowired + public SimpleMovieLister(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } +} + + @Repository +public class JpaMovieFinder implements MovieFinder { + // implementation elided for clarity +} + + To autodetect these classes and register the corresponding beans, you + need to include the following element in XML, where the base-package + element is a common parent package for the two classes. (Alternatively, + you can specify a comma-separated list that includes the parent package of + each class.) + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:component-scan base-package="org.example"/> + +</beans> + + + The scanning of classpath packages requires the presence of + corresponding directory entries in the classpath. When you build JARs + with Ant, make sure that you do not activate the + files-only switch of the JAR task. + + + Furthermore, the + AutowiredAnnotationBeanPostProcessor and + CommonAnnotationBeanPostProcessor are both + included implicitly when you use the component-scan element. That means + that the two components are autodetected and wired + together - all without any bean configuration metadata provided in + XML. + + + You can disable the registration of + AutowiredAnnotationBeanPostProcessor and + CommonAnnotationBeanPostProcessor by + including the annotation-config attribute with a + value of false. + + + +
+ +
+ Using filters to customize scanning + + By default, classes annotated with + @Component, + @Repository, + @Service, + @Controller, or a custom annotation that + itself is annotated with @Component are the + only detected candidate components. However, you can modify and extend + this behavior simply by applying custom filters. Add them as + include-filter or exclude-filter + sub-elements of the component-scan element. Each filter + element requires the type and + expression attributes. The following table describes + the filtering options. + + + Filter Types + + + + + + + + + + + Filter Type + + Example Expression + + Description + + + + + + annotation + + org.example.SomeAnnotation + + An annotation to be present at the type level in target + components. + + + + assignable + + org.example.SomeClass + + A class (or interface) that the target components are + assignable to (extend/implement). + + + + aspectj + + org.example..*Service+ + + An AspectJ type expression to be matched by the target + components. + + + + regex + + org\.example\.Default.* + + A regex expression to be matched by the target components + class names. + + + + custom + + org.example.MyTypeFilter + + A custom implementation of the + org.springframework.core.type + .TypeFilter interface. + + + +
+ + The following example shows the XML configuration ignoring all + @Repository annotations and using "stub" + repositories instead. + + <beans> + + <context:component-scan base-package="org.example"> + <context:include-filter type="regex" expression=".*Stub.*Repository"/> + <context:exclude-filter type="annotation" + expression="org.springframework.stereotype.Repository"/> + </context:component-scan> + +</beans> + + + You can also disable the default filters by providing + use-default-filters="false" as an attribute of the + <component-scan/> element. This will in effect disable automatic + detection of classes annotated with + @Component, + @Repository, + @Service, or + @Controller. + +
+ +
+ Defining bean metadata within components + + Spring components can also contribute bean definition metadata to the + container. You do this with the same @Bean annotation + used to define bean metadata within @Configuration + annotated classes. Here is a simple example: + + @Component +public class FactoryMethodComponent { + + @Bean @Qualifier("public") + public TestBean publicInstance() { + return new TestBean("publicInstance"); + } + + public void doWork() { + // Component method implementation omitted + } +} + + This class is a Spring component that has application-specific code + contained in its doWork() method. However, it + also contributes a bean definition that has a factory 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: + + @Component +public class FactoryMethodComponent { + + private static int i; + + @Bean @Qualifier("public") + public TestBean publicInstance() { + return new TestBean("publicInstance"); + } + + // use of a custom qualifier and autowiring of method parameters + + @Bean @BeanAge(1) + 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(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 property on another bean named + privateInstance. A Spring Expression Language element + defines the value of the property through the notation #{ + <expression> }. For @Value annotations, + an expression resolver is preconfigured to look for bean names when + resolving expression text. + + The @Bean methods in a Spring component are + processed differently than their counterparts inside a Spring + @Configuration class. The difference is that + @Component 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 field within a @Component classes + @Bean method has standard Java + semantics. +
+ +
+ Naming autodetected components + + When a component is autodetected as part of the scanning process, its + bean name is generated by the + BeanNameGenerator strategy known to that + scanner. By default, any Spring stereotype annotation + (@Component, + @Repository, + @Service, and + @Controller) that contains a + name value will thereby provide that name to the + corresponding bean definition. + + + JSR 330's @Named annotation can be used as a means to both detect + components and to provide them with a name. This behavior is enabled + automatically if you have the JSR 330 JAR on the classpath. + + + If such an annotation contains no name value or for + any other detected component (such as those discovered by custom filters), + the default bean name generator returns the uncapitalized non-qualified + class name. For example, if the following two components were detected, + the names would be myMovieLister and movieFinderImpl: + + @Service("myMovieLister") +public class SimpleMovieLister { + // ... +} + + @Repository +public class MovieFinderImpl implements MovieFinder { + // ... +} + + + If you do not want to rely on the default bean-naming strategy, you + can provide a custom bean-naming strategy. First, implement the BeanNameGenerator interface, and + be sure to include a default no-arg constructor. Then, provide the + fully-qualified class name when configuring the scanner: + + + <beans> + + <context:component-scan base-package="org.example" + name-generator="org.example.MyNameGenerator" /> + +</beans> + + As a general rule, consider specifying the name with the annotation + whenever other components may be making explicit references to it. On the + other hand, the auto-generated names are adequate whenever the container + is responsible for wiring. +
+ +
+ Providing a scope for autodetected components + + As with Spring-managed components in general, the default and most + common scope for autodetected components is singleton. However, sometimes + you need other scopes, which Spring 2.5 provides with a new + @Scope annotation. Simply provide the name + of the scope within the annotation: + + @Scope("prototype") +@Repository +public class MovieFinderImpl implements MovieFinder { + // ... +} + + + To provide a custom strategy for scope resolution rather than + relying on the annotation-based approach, implement the ScopeMetadataResolver interface, + and be sure to include a default no-arg constructor. Then, provide the + fully-qualified class name when configuring the scanner: + + + <beans> + + <context:component-scan base-package="org.example" + scope-resolver="org.example.MyScopeResolver" /> + +</beans> + + When using certain non-singleton scopes, it may be necessary to + generate proxies for the 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: + + <beans> + + <context:component-scan base-package="org.example" + scoped-proxy="interfaces" /> + +</beans> +
+ +
+ Providing qualifier metadata with annotations + + The @Qualifier annotation is discussed + in . The examples + in that section demonstrate the use of the + @Qualifier annotation and custom qualifier + annotations to provide fine-grained control when you resolve autowire + candidates. Because those examples were based on XML bean definitions, the + qualifier metadata was provided on the candidate bean definitions using + the qualifier or meta sub-elements + of the bean element in the XML. When relying upon + classpath scanning for autodetection of components, you provide the + qualifier metadata with type-level annotations on the candidate class. The + following three examples demonstrate this technique: + + @Component +@Qualifier("Action") +public class ActionMovieCatalog implements MovieCatalog { + // ... +} + + @Component +@Genre("Action") +public class ActionMovieCatalog implements MovieCatalog { + // ... +} + + @Component +@Offline +public class CachingMovieCatalog implements MovieCatalog { + // ... +} + + + As with most annotation-based alternatives, keep in mind that the + annotation metadata is bound to the class definition itself, while the + use of XML allows for multiple beans of the same + type to provide variations in their qualifier metadata, + because that metadata is provided per-instance rather than + per-class. + +
+
diff --git a/spring-framework-reference/src/beans-context-additional.xml b/spring-framework-reference/src/beans-context-additional.xml new file mode 100644 index 00000000000..24ef24dd4c2 --- /dev/null +++ b/spring-framework-reference/src/beans-context-additional.xml @@ -0,0 +1,663 @@ + + +
+ Additional Capabilities of the + <interfacename>ApplicationContext</interfacename> + + + + 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 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 declarative fashion, not even creating it programmatically, but + instead relying on support classes such as + ContextLoader to automatically instantiate an + ApplicationContext as part of the normal + startup process of a J2EE web application. + + To enhance BeanFactory functionality in a + more framework-oriented style the context package also provides the + following functionality: + + + + Access to messages in i18n-style, through the + MessageSource interface. + + + + Access to resources, such as URLs and files, + through the ResourceLoader + interface. + + + + Event publication to beans implementing the + ApplicationListener interface, through + the use of the ApplicationEventPublisher + interface. + + + + Loading of multiple (hierarchical) contexts, + allowing each to be focused on one particular layer, such as the web + layer of an application, through the + HierarchicalBeanFactory interface. + + + +
+ Internationalization using + <interfacename>MessageSource</interfacename> + + + + The ApplicationContext interface + extends an interface called MessageSource, + and therefore provides internationalization (i18n) functionality. Spring + also provides the interface + HierarchicalMessageSource, which can resolve + messages hierarchically. Together these interfaces provide the foundation + upon which Spring effects message resolution. The methods defined on these + interfaces include: + + + + String getMessage(String code, Object[] args, String + default, Locale loc): The basic method used to retrieve a + message from the MessageSource. When no + message is found for the specified locale, the default message is + used. Any arguments passed in become replacement values, using the + MessageFormat functionality provided by + the standard library. + + + + String getMessage(String code, Object[] args, Locale + loc): Essentially the same as the previous method, but + with one difference: no default message can be specified; if the + message cannot be found, a + NoSuchMessageException is thrown. + + + + String getMessage(MessageSourceResolvable resolvable, + Locale locale): All properties used in the preceding + methods are also wrapped in a class named + MessageSourceResolvable, which you can + use with this method. + + + + When an ApplicationContext is loaded, + it automatically searches for a + MessageSource bean defined in the context. + The bean must have the name messageSource. If such a + bean is found, all calls to the preceding methods are delegated to the + message source. If no message source is found, the + ApplicationContext attempts to find a + parent containing a bean with the same name. If it does, it uses that bean + as the MessageSource. If the + ApplicationContext cannot find any source + for messages, an empty DelegatingMessageSource is + instantiated in order to be able to accept calls to the methods defined + above. + + Spring provides two MessageSource + implementations, ResourceBundleMessageSource and + StaticMessageSource. Both implement + HierarchicalMessageSource in order to do + nested messaging. The StaticMessageSource is rarely + used but provides programmatic ways to add messages to the source. The + ResourceBundleMessageSource is shown in the + following example: + + <beans> +<bean id="messageSource" + class="org.springframework.context.support.ResourceBundleMessageSource"> + <property name="basenames"> + <list> + <value>format</value> + <value>exceptions</value> + <value>windows</value> + </list> + </property> +</bean> +</beans> + + In the example it is assumed you have three resource bundles defined + in your classpath called format, + exceptions and windows. Any request + to resolve a message will be handled in the JDK standard way of resolving + messages through ResourceBundles. For the purposes of the example, assume + the contents of two of the above resource bundle files are... + + # in format.properties +message=Alligators rock! + + # 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. + + 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... + + Alligators rock! + + So to summarize, the MessageSource is defined + in a file called beans.xml, which exists at the root of + your classpath. The messageSource bean definition + refers to a number of resource bundles through its + basenames property. The three files that are passed in + the list to the basenames property exist as files at + the root of your classpath and are called + format.properties, + exceptions.properties, and + windows.properties respectively. + + 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. + + <beans> + + <!-- this MessageSource is being used in a web application --> + <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> + <property name="basename" value="test-messages"/> + </bean> + + <!-- lets inject the above MessageSource into this POJO --> + <bean id="example" class="com.foo.Example"> + <property name="messages" ref="messageSource"/> + </bean> + +</beans> + + public class Example { + + private MessageSource 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); + } + +} + + The resulting output from the invocation of the + execute() method will be... + + 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 would create + files called format_en_GB.properties, + exceptions_en_GB.properties, and + windows_en_GB.properties respectively. + + 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. + + # in exceptions_en_GB.properties +argument.required=Ebagum lad, the '{0}' argument is required, I say, required. + + 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... + + Ebagum lad, the 'userDao' argument is required, I say, required. + + You can also use the MessageSourceAware + interface to acquire a reference to any + MessageSource that has been defined. Any bean that + is defined in an ApplicationContext that implements + the MessageSourceAware interface is injected with + the application context's MessageSource when the + bean is created and configured. + + + As an alternative to + ResourceBundleMessageSource, Spring provides a + ReloadableResourceBundleMessageSource class. This + variant supports the same bundle file format but is more flexible than + the standard JDK based + ResourceBundleMessageSource + implementation. In particular, it allows for reading files + from any Spring resource location (not just from the classpath) and + supports hot reloading of bundle property files (while efficiently + caching them in between). Check out the + ReloadableResourceBundleMessageSource javadoc for + details. + +
+ +
+ Standard and Custom Events + + Event handling in the + ApplicationContext is provided through the + ApplicationEvent class and + ApplicationListener interface. If a bean + that implements the ApplicationListener + interface is deployed into the context, every time an + ApplicationEvent gets published to the + ApplicationContext, that bean is notified. + Essentially, this is the standard Observer design + pattern. Spring provides the following standard events: + + + Built-in Events + + + + + + + + + Event + + Explanation + + + + + + ContextRefreshedEvent + + Published when the + ApplicationContext is initialized + or refreshed, for example, using the + refresh() method on the + ConfigurableApplicationContext + interface. "Initialized" here means that all beans are loaded, + post-processor beans are detected and activated, singletons are + pre-instantiated, and the + ApplicationContext object is ready + for use. As long as the context has not been closed, a refresh can + be triggered multiple times, provided that the chosen + ApplicationContext actually + supports such "hot" refreshes. For example, + XmlWebApplicationContext supports hot + refreshes, but GenericApplicationContext + does not. + + + + ContextStartedEvent + + Published when the + ApplicationContext is started, + using the start() method on the + ConfigurableApplicationContext + interface. "Started" here means that all + Lifecycle beans receive an explicit + start signal. Typically this signal is used to restart beans after + an explicit stop, but it may also be used to start components that + have not been configured for autostart , for example, components + that have not already started on initialization. + + + + ContextStoppedEvent + + Published when the + ApplicationContext is stopped, + using the stop() method on the + ConfigurableApplicationContext + interface. "Stopped" here means that all + Lifecycle beans receive an explicit + stop signal. A stopped context may be restarted through a + start() call. + + + + ContextClosedEvent + + Published when the + ApplicationContext is closed, using + the close() method on the + ConfigurableApplicationContext + interface. "Closed" here means that all singleton beans are + destroyed. A closed context reaches its end of life; it cannot be + refreshed or restarted. + + + + 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 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: + + public class BlackListEvent extends ApplicationEvent { + private final String address; + private final String test; + + 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 + ApplicationEventPublisher. Typically this + is done by creating a class that implements + ApplicationEventPublisherAware and + registering it as a Spring bean. The following example demonstrates such a + class: + + blackList; + private ApplicationEventPublisher publisher; + + public void setBlackList(List blackList) { + this.blackList = blackList; + } + + 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... + + At configuration time, the Spring container will detect that + EmailService implements + ApplicationEventPublisherAware and will + automatically call + setApplicationEventPublisher(). In reality, the + parameter passed in will be the Spring container itself; you're simply + interacting with the application context via its + ApplicationEventPublisher interface. + + 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: + + { + + private String notificationAddress; + + public void setNotificationAddress(String notificationAddress) { + this.notificationAddress = notificationAddress; + } + + public void onApplicationEvent(BlackListEvent event) { +]]> // notify appropriate parties via notificationAddress... + + Notice that ApplicationListener is + generically parameterized with the type of your custom event, + BlackListEvent. This means that the + onApplicationEvent() method can remain type-safe, + avoiding any need for downcasting. You may register as many event + listeners as you wish, but note that by default event listeners receive + events synchronously. This means the + publishEvent() method blocks until all listeners + have finished processing the event. One advantage of this synchronous and + single-threaded approach is that when a listener receives an event, it + operates inside the transaction context of the publisher if a transaction + context is available. If another strategy for event publication becomes + necessary, refer to the JavaDoc for Spring's + ApplicationEventMulticaster + interface. + + The following example demonstrates the bean definitions used to + register and configure each of the classes above: + + + + black@list.org + white@list.org + john@doe.org + + + + + + +]]> + + Putting it all together, when the sendEmail() + method of the emailService bean is called, if there are + any emails that should be blacklisted, a custom event of type + BlackListEvent is published. The + blackListNotifier bean is registered as an + ApplicationListener and thus receives the + BlackListEvent, at which point it can notify + appropriate parties. + + + Spring's eventing mechanism is designed for simple communication + between Spring beans within the same application context. However, for + more sophisticated enterprise integration needs, the + separately-maintained Spring + Integration project provides complete support for building + lightweight, pattern-oriented, event-driven architectures that build upon + the well-known Spring programming model. + +
+ +
+ Convenient access to low-level resources + + For optimal usage and understanding of application contexts, users + should generally familiarize themselves with Spring's + Resource abstraction, as described in the + chapter . + + An application context is a + ResourceLoader, which can be used to load + Resources. A + Resource is essentially a more feature rich + version of the JDK class java.net.URL, in fact, the + implementations of the Resource wrap an + instance of java.net.URL where appropriate. A + Resource can obtain low-level resources + from almost any location in a transparent fashion, including from the + classpath, a filesystem location, anywhere describable with a standard + URL, and some other variations. If the resource location string is a + simple path without any special prefixes, where those resources come from + is specific and appropriate to the actual application context type. + + You can configure a bean deployed into the application context to + implement the special callback interface, + ResourceLoaderAware, to be automatically + called back at initialization time with the application context itself + passed in as the ResourceLoader. You can + also expose properties of type Resource, to + be used to access static resources; they will be injected into it like any + other properties. You can specify those + Resource properties as simple String paths, + and rely on a special JavaBean + PropertyEditor that is automatically + registered by the context, to convert those text strings to actual + Resource objects when the bean is + deployed. + + The location path or paths supplied to an + ApplicationContext constructor are actually + resource strings, and in simple form are treated appropriately to the + specific context implementation. + ClassPathXmlApplicationContext treats a simple + location path as a classpath location. You can also use location paths + (resource strings) with special prefixes to force loading of definitions + from the classpath or a URL, regardless of the actual context type. +
+ +
+ Convenient <interfacename>ApplicationContext</interfacename> + instantiation for web applications + + You can create ApplicationContext + instances declaratively by using, for example, a + ContextLoader. Of course you can also create + ApplicationContext instances + programmatically by using one of the + ApplicationContext implementations. + + The ContextLoader mechanism comes in two + flavors: the ContextLoaderListener and the + ContextLoaderServlet. They have the same + functionality but differ in that the listener version is not reliable in + Servlet 2.3 containers. In the Servlet 2.4 specification, Servlet context + listeners must execute immediately after the Servlet context for the web + application is created and is available to service the first request (and + also when the Servlet context is about to be shut down). As such a Servlet + context listener is an ideal place to initialize the Spring + ApplicationContext. All things being equal, + you should probably prefer ContextLoaderListener; + for more information on compatibility, have a look at the Javadoc for the + ContextLoaderServlet. + + You can register an ApplicationContext + using the ContextLoaderListener as follows: + + <context-param> +<param-name>contextConfigLocation</param-name> +<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value> +</context-param> + +<listener> +<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> +</listener> + +<!-- or use the ContextLoaderServlet instead of the above listener +<servlet> +<servlet-name>context</servlet-name> +<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> +<load-on-startup>1</load-on-startup> +</servlet> +--> + + The listener inspects the contextConfigLocation + parameter. If the parameter does not exist, the listener uses + /WEB-INF/applicationContext.xml as a default. When the + parameter does exist, the listener separates the + String by using predefined delimiters (comma, semicolon and whitespace) + and uses the values as locations where application contexts will be + searched. Ant-style path patterns are supported as well. Examples are + /WEB-INF/*Context.xml for all files with names ending + with "Context.xml", residing in the "WEB-INF" directory, and + /WEB-INF/**/*Context.xml, for all such files in any + subdirectory of "WEB-INF". + + You can use ContextLoaderServlet instead of + ContextLoaderListener. The Servlet uses the + contextConfigLocation parameter just as the listener + does. +
+ +
+ 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. + + 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 use application server resources such as + the JTA transaction manager and JNDI-bound JDBC DataSources and JMS + ConnectionFactory instances, and may also register with the platform's JMX + server - all through Spring's standard transaction management and JNDI 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 SpringContextResourceAdapter class for the configuration details + involved in RAR deployment. + + For a simple deployment of a Spring ApplicationContext as a + J2EE RAR file: package all application classes into a RAR file, + which is a standard JAR file with a different file extension. Add all + required library JARs into the root of the RAR archive. Add a + "META-INF/ra.xml" deployment descriptor (as shown in + SpringContextResourceAdapters JavaDoc) and the + corresponding Spring XML bean definition file(s) (typically + "META-INF/applicationContext.xml"), and drop the resulting RAR file into + your application server's deployment directory. + + + Such RAR deployment units are usually self-contained; they do not + expose components to the outside world, not even to other modules of the + same application. Interaction with a RAR-based ApplicationContext + usually occurs through JMS destinations that it shares with other + modules. A RAR-based ApplicationContext may also, for example, schedule + some jobs, reacting to new files in the file system (or the like). If it + needs to allow synchronous access from the outside, it could for example + export RMI endpoints, which of course may be used by other application + modules on the same machine. + +
+
diff --git a/spring-framework-reference/src/beans-customizing.xml b/spring-framework-reference/src/beans-customizing.xml new file mode 100644 index 00000000000..c9b8db67b83 --- /dev/null +++ b/spring-framework-reference/src/beans-customizing.xml @@ -0,0 +1,665 @@ + + +
+ Customizing the nature of a bean + +
+ Lifecycle callbacks + + + + To interact with the container's management of the bean lifecycle, you + can implement the Spring InitializingBean + and DisposableBean interfaces. The + container calls afterPropertiesSet() for the + former and destroy() for the latter to allow the + bean to perform certain actions upon initialization and destruction of + your beans. You can also achieve the same integration with the container + without coupling your classes to Spring interfaces through the use of + init-method and destroy method object definition metadata. + + Internally, the Spring Framework uses + BeanPostProcessor implementations to + process any callback interfaces it can find and call the appropriate + methods. If you need custom features or other lifecycle behavior Spring + does not offer out-of-the-box, you can implement a + BeanPostProcessor yourself. For more + information, see . + + In addition to the initialization and destruction callbacks, + Spring-managed objects may also implement the + Lifecycle interface so that those objects + can participate in the startup and shutdown process as driven by the + container's own lifecycle. + + The lifecycle callback interfaces are described in this + section. + +
+ Initialization callbacks + + The + org.springframework.beans.factory.InitializingBean + interface allows a bean to perform initialization work after all + necessary properties on the bean have been set by the container. The + InitializingBean interface specifies a + single method: + + void afterPropertiesSet() throws Exception; + + It is recommended that you do not use the + InitializingBean interface because it + unnecessarily couples the code to Spring. Alternatively, 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: + + <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> + + public class ExampleBean { + + public void init() { + // do some initialization work + } +} + + ...is exactly the same as... + + <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> + + public class AnotherExampleBean implements InitializingBean { + + public void afterPropertiesSet() { + // do some initialization work + } +} + + ... but does not couple the code to Spring. +
+ +
+ Destruction callbacks + + Implementing the + org.springframework.beans.factory.DisposableBean + interface allows a bean to get a callback when the container containing + it is destroyed. The DisposableBean + interface specifies a single method: + + 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, specify a + generic method that is supported by bean definitions. With XML-based + configuration metadata, you use the destroy-method + attribute on the <bean/>. For example, the + following definition: + + <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/> + + public class ExampleBean { + + public void cleanup() { + // do some destruction work (like releasing pooled connections) + } +} + + ...is exactly the same as... + + <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> + + public class AnotherExampleBean implements DisposableBean { + + public void destroy() { + // do some destruction work (like releasing pooled connections) + } +} + + ... but does not couple the code to Spring. +
+ +
+ Default initialization and destroy methods + + When you write initialization and destroy method callbacks that do + not use the Spring-specific + InitializingBean and + DisposableBean callback interfaces, you + typically write methods with names such as init(), + initialize(), dispose(), and so + on. Ideally, the names of such lifecycle callback methods are + standardized across a project so that all developers use the same method + names and ensure consistency. + + You can configure the Spring container to look + for named initialization and destroy callback method names on + every bean. This means that you, as an application + developer, can write your application classes and use an initialization + callback called init(), without having to configure + an init-method="init" attribute with each bean + definition. The Spring IoC container calls that method when the bean is + created (and in accordance with the standard lifecycle callback contract + described previously). This feature also enforces a consistent naming + convention for initialization and destroy method callbacks. + + 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. + + public class DefaultBlogService implements BlogService { + + private 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."); + } + } +} + + <beans default-init-method="init"> + + <bean id="blogService" class="com.foo.DefaultBlogService"> + <property name="blogDao" ref="blogDao" /> + </bean> + +</beans> + + The presence of the default-init-method attribute + on the top-level <beans/> element attribute + causes the Spring IoC container to recognize a method called + init on beans as the initialization method callback. + When a bean is created and assembled, if the bean class has such a + method, it is invoked at the appropriate time. + + You configure destroy method callbacks similarly (in XML, that is) + by using the default-destroy-method attribute on the + top-level <beans/> element. + + Where existing bean classes already have callback methods that are + named at variance with the convention, you can override the default by + specifying (in XML, that is) the method name using the + init-method and destroy-method + attributes of the <bean/> itself. + + The Spring container guarantees that a configured initialization + callback is called immediately after a bean is supplied with all + dependencies. Thus the initialization callback is called on the raw bean + reference, which means that AOP interceptors and so forth are not yet + applied to the bean. A target bean is fully created + first, then an AOP proxy (for + example) with its interceptor chain is applied. If the target bean and + the proxy are defined separately, your code can even interact with the + raw target bean, bypassing the proxy. Hence, it would be inconsistent to + apply the interceptors to the init method, because doing so would couple + the lifecycle of the target bean with its proxy/interceptors and leave + strange semantics when your code interacts directly to the raw target + bean. +
+ +
+ Combining lifecycle mechanisms + + As of Spring 2.5, you have three options for controlling bean + lifecycle behavior: the InitializingBean and DisposableBean callback + interfaces; custom init() and + destroy() methods; and the @PostConstruct and + @PreDestroy annotations. You can + combine these mechanisms to control a given bean. + + + If multiple lifecycle mechanisms are configured for a bean, and + each mechanism is configured with a different method name, then each + configured method is executed in the order listed below. However, if + the same method name is configured - for example, + init() for an initialization method - for more than + one of these lifecycle mechanisms, that method is executed once, as + explained in the preceding section. + + + Multiple lifecycle mechanisms configured for the same bean, with + different initialization methods, are called as follows: + + + + Methods annotated with + @PostConstruct + + + + afterPropertiesSet() as defined by the + InitializingBean callback + interface + + + + A custom configured init() method + + + + Destroy methods are called in the same order: + + + + Methods annotated with + @PreDestroy + + + + destroy() as defined by the + DisposableBean callback + interface + + + + A custom configured destroy() method + + +
+ +
+ Startup and shutdown callbacks + + The Lifecycle interface defines the + essential methods for any object that has its own lifecycle requirements + (e.g. starts and stops some background process): + + public interface Lifecycle { + + void start(); + + void stop(); + + boolean isRunning(); + +} + + Any Spring-managed object may implement that interface. Then, when + the ApplicationContext itself starts and stops, it will cascade those + calls to all Lifecycle implementations defined within that context. It + does this by delegating to a + LifecycleProcessor: + + public interface LifecycleProcessor extends Lifecycle { + + void onRefresh(); + + void onClose(); + +} + + Notice that the LifecycleProcessor is + itself an extension of the Lifecycle + interface. It also adds two other methods for reacting to the context + being refreshed and closed. + + The order of startup and shutdown invocations can be important. If a + "depends-on" relationship exists between any two objects, the dependent + side will start after its dependency, and it will + stop before its dependency. However, at times the + direct dependencies are unknown. You may only know that objects of a + certain type should start prior to objects of another type. In those + cases, the SmartLifecycle interface + defines another option, namely the getPhase() + method as defined on its super-interface, + Phased. + + public interface Phased { + + int getPhase(); + +} + + +public interface SmartLifecycle extends Lifecycle, Phased { + + boolean isAutoStartup(); + + void stop(Runnable callback); + +} + + When starting, the objects with the lowest phase start first, and + when stopping, the reverse order is followed. Therefore, an object that + implements SmartLifecycle and whose + getPhase() method returns Integer.MIN_VALUE would be + among the first to start and the last to stop. At the other end of the + spectrum, a phase value of Integer.MAX_VALUE would + indicate that the object should be started last and stopped first + (likely because it depends on other processes to be running). When + considering the phase value, it's also important to know that the + default phase for any "normal" Lifecycle + object that does not implement + SmartLifecycle would be 0. Therefore, any + negative phase value would indicate that an object should start before + those standard components (and stop after them), and vice versa for any + positive phase value. + + As you can see the stop method defined by + SmartLifecycle accepts a callback. Any + implementation must invoke that callback's run() + method after that implementation's shutdown process is complete. That + enables asynchronous shutdown where necessary since the default + implementation of the LifecycleProcessor + interface, DefaultLifecycleProcessor, will wait + up to its timeout value for the group of objects within each phase to + invoke that callback. The default per-phase timeout is 30 seconds. You + can override the default lifecycle processor instance by defining a bean + named "lifecycleProcessor" within the context. If you only want to + modify the timeout, then defining the following would be + sufficient: + + <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> + <!-- timeout value in milliseconds --> + <property name="timeoutPerShutdownPhase" value="10000"/> +</bean> + + As mentioned, the LifecycleProcessor + interface defines callback methods for the refreshing and closing of the + context as well. The latter will simply drive the shutdown process as if + stop() had been called explicitly, but it will happen when the context + is closing. The 'refresh' callback on the other hand enables another + feature of SmartLifecycle beans. When the + context is refreshed (after all objects have been instantiated and + initialized), that callback will be invoked, and at that point the + default lifecycle processor will check the boolean value returned by + each SmartLifecycle object's + isAutoStartup() method. If "true", then that + object will be started at that point rather than waiting for an explicit + invocation of the context's or its own start() method (unlike the + context refresh, the context start does not happen automatically for a + standard context implementation). The "phase" value as well as any + "depends-on" relationships will determine the startup order in the same + way as described above. +
+ +
+ Shutting down the Spring IoC container gracefully in non-web + applications + + + This section applies only to non-web applications. Spring's + web-based ApplicationContext + implementations already have code in place to shut down the Spring IoC + container gracefully when the relevant web application is shut + down. + + + If you are using Spring's IoC container in a non-web application + environment; for example, in a rich client desktop environment; you + register a shutdown hook with the JVM. Doing so ensures a graceful + shutdown and calls the relevant destroy methods on your singleton beans + so that all resources are released. Of course, you must still configure + and implement these destroy callbacks correctly. + + To register a shutdown hook, you call the + registerShutdownHook() method that is declared + on the AbstractApplicationContext class: + + import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public final class Boot { + + public static void main(final String[] args) throws Exception { + AbstractApplicationContext ctx + = new ClassPathXmlApplicationContext(new String []{"beans.xml"}); + + // add a shutdown hook for the above context... + ctx.registerShutdownHook(); + + // app runs here... + + // main method exits, hook is called prior to the app shutting down... + } +} +
+
+ +
+ <interfacename>ApplicationContextAware</interfacename> and + <interfacename>BeanNameAware</interfacename> + + When an ApplicationContext creates a + class that implements the + org.springframework.context.ApplicationContextAware + interface, the class is provided with a reference to that + ApplicationContext. + + public interface ApplicationContextAware { + + void setApplicationContext(ApplicationContext applicationContext) throws BeansException; +} + + Thus beans can manipulate programmatically the + ApplicationContext that created them, + through the ApplicationContext interface, + or by casting the reference to a known subclass of this interface, such as + ConfigurableApplicationContext, which exposes + additional functionality. One use would be the programmatic retrieval of + other beans. Sometimes this capability is useful; however, in general you + should avoid it, because it couples the code to Spring and does not follow + the Inversion of Control style, where collaborators are provided to beans + as properties. Other methods of the ApplicationContext provide access to + file resources, publishing application events, and accessing a + MessageSource. These additional features are described in + + As of Spring 2.5, autowiring is another alternative to obtain + reference to the ApplicationContext. The + "traditional" constructor and byType + autowiring modes (as described in ) can provide a dependency of type + ApplicationContext for a constructor + argument or setter method parameter, respectively. For more flexibility, + including the ability to autowire fields and multiple parameter methods, + use the new annotation-based autowiring features. If you do, the + ApplicationFactory is autowired into a + field, constructor argument, or method parameter that is expecting the + BeanFactory type if the field, constructor, + or method in question carries the + @Autowired annotation. For more + information, see . + + 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. + + public interface BeanNameAware { + + void setBeanName(string name) throws BeansException; +} + + The callback is invoked after population of normal bean properties but + before an initialization callback such as + InitializingBeans + afterPropertiesSet or a custom init-method. +
+ +
+ Other <interfacename>Aware</interfacename> interfaces + + Besides ApplicationContextAware and + BeanNameAware discussed above, Spring + offers a range of + Aware interfaces that + allow beans to indicate to the container that they require a certain + infrastructure dependency. The most important + Aware interfaces are summarized below - as + a general rule, the name is a good indication of the dependency + type: + + + <interfacename>Aware</interfacename> interfaces + + + + + + + Name + + Injected Dependency + + Explained in... + + + + + + ApplicationContextAware + + Declaring + ApplicationContext + + + + + + ApplicationEventPublisherAware + + Event publisher of the enclosing + ApplicationContext + + + + + + BeanClassLoaderAware + + Class loader used to load the bean + classes. + + + + + + BeanFactoryAware + + Declaring + BeanFactory + + + + + + BeanNameAware + + Name of the declaring bean + + + + + + BootstrapContextAware + + Resource adapter + BootstrapContext the container runs + in. Typically available only in JCA aware + ApplicationContexts + + + + + + LoadTimeWeaverAware + + Defined weaver for processing + class definition at load time + + + + + + MessageSourceAware + + Configured strategy for resolving messages (with + support for parametrization and + internationalization) + + + + + + NotificationPublisherAware + + Spring JMX notification publisher + + + + + + PortletConfigAware + + Current PortletConfig + the container runs in. Valid only in a web-aware Spring + ApplicationContext + + + + + + PortletContextAware + + Current PortletContext + the container runs in. Valid only in a web-aware Spring + ApplicationContext + + + + + + ResourceLoaderAware + + Configured loader for low-level access to + resources + + + + + + ServletConfigAware + + Current ServletConfig + the container runs in. Valid only in a web-aware Spring + ApplicationContext + + + + + + ServletContextAware + + Current ServletContext + the container runs in. Valid only in a web-aware Spring + ApplicationContext + + + + + +
+ + Note again that usage of these interfaces ties your code to the Spring + API and does not follow the Inversion of Control style. As such, they are + recommended for infrastructure beans that require programmatic access to + the container. +
+
diff --git a/spring-framework-reference/src/beans-dependencies.xml b/spring-framework-reference/src/beans-dependencies.xml new file mode 100644 index 00000000000..2f56f948b0b --- /dev/null +++ b/spring-framework-reference/src/beans-dependencies.xml @@ -0,0 +1,1567 @@ + + +
+ Dependencies + + A typical enterprise application does not consist of a single object (or + bean in the Spring parlance). Even the simplest application has a few + objects that work together to present what the end-user sees as a coherent + application. This next section explains how you go from defining a number of + bean definitions that stand alone to a fully realized application where + objects collaborate to achieve a goal. + +
+ Dependency injection + + + + Dependency injection (DI) 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 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 or location of its dependencies on its own + by using direct construction of classes, or the Service + Locator pattern. + + Code is cleaner with the DI principle and decoupling is more effective + when objects are provided with their dependencies. The object does not + look up its dependencies, and does not know the location or class of the + dependencies. As such, your classes become easier to test, in particular + when the dependencies are on interfaces or abstract base classes, which + allow for stub or mock implementations to be used in unit tests. + + DI exists in two major variants, Constructor-based dependency + injection and Setter-based + dependency injection. + +
+ Constructor-based dependency injection + + Constructor-based DI is accomplished by the + container invoking a constructor with a number of arguments, each + representing a dependency. Calling a static factory + method with specific arguments to construct the bean is nearly + equivalent, and this discussion treats arguments to a constructor and to + a static factory method similarly. The following + example shows a class that can only be dependency-injected with + constructor 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. + + public class SimpleMovieLister { + + // 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; + } + + // business logic that actually 'uses' the injected MovieFinder is omitted... +} + +
+ Constructor argument resolution + + Constructor argument resolution matching occurs using the + argument's type. If no potential ambiguity exists in the constructor + arguments of a bean definition, then the order in which the + constructor arguments are defined in a bean definition is the order in + which those arguments are supplied to the appropriate constructor when + the bean is being instantiated. Consider the following class: + + package x.y; + +public class Foo { + + public Foo(Bar bar, Baz baz) { + // ... + } +} + + No potential ambiguity exists, assuming that + Bar and Baz classes are + not related by inheritance. Thus the following configuration works + fine, and you do not need to specify the constructor argument indexes + and/or types explicitly in the + <constructor-arg/> element. + + <beans> + <bean id="foo" class="x.y.Foo"> + <constructor-arg ref="bar"/> + <constructor-arg ref="baz"/> + </bean> + + <bean id="bar" class="x.y.Bar"/> + <bean id="baz" class="x.y.Baz"/> + +</beans> + + 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 + <value>true<value>, Spring cannot + determine the type of the value, and so cannot match by type without + help. Consider the following class: + + package examples; + +public class ExampleBean { + + // No. of years to the calculate the Ultimate Answer + private int years; + + // The Answer to Life, the Universe, and Everything + private String ultimateAnswer; + + public ExampleBean(int years, String ultimateAnswer) { + this.years = years; + this.ultimateAnswer = ultimateAnswer; + } +} + +
+ Constructor argument type matching + + In the preceding scenario, the container + can use type matching with simple types if you + explicitly specify the type of the constructor argument using the + type attribute. For example: + + <bean id="exampleBean" class="examples.ExampleBean"> +<constructor-arg type="int" value="7500000"/> +<constructor-arg type="java.lang.String" value="42"/> +</bean> +
+ +
+ Constructor argument index + + Use the index attribute to specify explicitly + the index of constructor arguments. For example: + + <bean id="exampleBean" class="examples.ExampleBean"> +<constructor-arg index="0" value="7500000"/> +<constructor-arg index="1" value="42"/> +</bean> + + In addition to resolving the ambiguity of multiple simple + values, specifying an index resolves ambiguity where a constructor + has two arguments of the same type. Note that the index is + 0 based. +
+
+
+ +
+ 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. + + The following example shows a class that can only be + dependency-injected using pure setter injection. This class is + conventional Java. It is a POJO that has no dependencies on container + specific interfaces, base classes or annotations. + + public class SimpleMovieLister { + + // 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; + } + + // business logic that actually 'uses' the injected MovieFinder is omitted... +} + + The ApplicationContext supports + constructor- and setter-based DI for the beans it manages. It also + supports setter-based DI after some dependencies are already injected + through the constructor approach. You configure the dependencies in the + form of a BeanDefinition, which you use + with PropertyEditor instances to convert + properties from one format to another. However, most Spring users do not + work with these classes 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 dependencies. Note that the use + of a @Required + annotation on a setter can be used to make setters required + dependencies. + + The Spring team generally advocates setter injection, because + large numbers of constructor arguments can get unwieldy, especially + when properties are optional. Setter methods also make objects of that + class amenable to reconfiguration or re-injection later. Management + through JMX MBeans is a compelling use + case. + + Some purists favor constructor-based injection. Supplying all + object dependencies means that the object is always returned to client + (calling) code in a totally initialized state. The disadvantage is + that the object becomes less amenable to reconfiguration and + re-injection. + + Use the DI that makes the most sense for a particular class. + Sometimes, when dealing with third-party classes to which you do not + have the source, the choice is made for you. A legacy class may not + expose any setter methods, and so constructor injection is the only + available DI. + +
+ +
+ Dependency resolution process + + The container performs bean dependency resolution as follows: + + + + + + The ApplicationContext is created + and initialized with configuration metadata that describes all the + beans. Configuration metadata can be specified via XML, Java code or + annotations. + + + + For each bean, its dependencies are expressed in the form of + properties, constructor arguments, or arguments to the + static-factory method if you are using that instead of a normal + constructor. These dependencies are provided to the bean, + when the bean is actually created. + + + + Each property or constructor argument is an actual definition of + the value to set, or a reference to another bean in the + container. + + + + Each property or constructor argument which is a value is + converted from its specified format to the actual type of that + property or constructor argument. By default Spring can convert a + value supplied in string format to all built-in types, such as + int, long, + String, boolean, etc. + + + + The Spring container validates the configuration of each bean as the + container is created, including the validation of whether bean reference + properties refer to valid beans. However, the bean properties themselves + are not set until the bean is actually created. + Beans that are singleton-scoped and set to be pre-instantiated (the + default) are created when the container is created. Scopes are defined + in Otherwise, the bean is created + only when it is requested. 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. + + For example: Class A requires an instance of class B through + constructor injection, and class B requires an instance of class A + through constructor injection. If you configure beans for classes A + and B to be injected into each other, the Spring IoC container detects + this circular reference at runtime, and throws a + BeanCurrentlyInCreationException. + + One possible solution is to edit the source code of some classes + to be configured by setters rather than constructors. Alternatively, + avoid constructor injection and use setter injection only. In other + words, although it is not recommended, you can configure circular + dependencies with setter injection. + + Unlike the typical case (with no circular + dependencies), a circular dependency between bean A and bean B forces + one of the beans to be injected into the other prior to being fully + initialized itself (a classic chicken/egg scenario). + + + You can generally trust Spring to do the right thing. It detects + configuration problems, such as references to non-existent beans and + circular dependencies, at container load-time. Spring sets properties + and resolves dependencies as late as possible, when the bean is actually + created. This means that a Spring container which has loaded correctly + can later generate an exception when you request an object if there is a + problem creating that object or one of its dependencies. For example, + the bean throws an exception as a result of a missing or invalid + property. This potentially delayed visibility of some configuration + issues is why ApplicationContext + implementations by default pre-instantiate singleton beans. At the cost + of some upfront time and memory to create these beans before they are + actually needed, you discover configuration issues when the + ApplicationContext is created, not later. + You can still override this default behavior so that singleton beans + will lazy-initialize, rather than be pre-instantiated. + + If no circular dependencies exist, when one or more collaborating + beans are being injected into a dependent bean, each collaborating bean + is totally configured prior to being injected into + the dependent bean. This means that if bean A has a dependency on bean + B, the Spring IoC container completely configures bean B prior to + invoking the setter method on bean A. In other words, the bean is + instantiated (if not a pre-instantiated singleton), its dependencies are + set, and the relevant lifecycle methods (such as a configured init + method or the IntializingBean + callback method) are invoked. +
+ +
+ Examples of dependency injection + + 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: + + <bean id="exampleBean" class="examples.ExampleBean"> + +<!-- setter injection using the nested <ref/> element --> +<property name="beanOne"><ref bean="anotherExampleBean"/></property> + +<!-- setter injection using the neater 'ref' attribute --> +<property name="beanTwo" ref="yetAnotherBean"/> +<property name="integerProperty" value="1"/> +</bean> + +<bean id="anotherExampleBean" class="examples.AnotherBean"/> +<bean id="yetAnotherBean" class="examples.YetAnotherBean"/> + + public class ExampleBean { + + private AnotherBean beanOne; + private YetAnotherBean beanTwo; + private int i; + + public void setBeanOne(AnotherBean beanOne) { + this.beanOne = beanOne; + } + + public void setBeanTwo(YetAnotherBean beanTwo) { + this.beanTwo = beanTwo; + } + + 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: + + <bean id="exampleBean" class="examples.ExampleBean"> + +<!-- constructor injection using the nested <ref/> element --> +<constructor-arg> + <ref bean="anotherExampleBean"/> +</constructor-arg> + +<!-- constructor injection using the neater 'ref' attribute --> +<constructor-arg ref="yetAnotherBean"/> + +<constructor-arg type="int" value="1"/> +</bean> + +<bean id="anotherExampleBean" class="examples.AnotherBean"/> +<bean id="yetAnotherBean" class="examples.YetAnotherBean"/> + + public class ExampleBean { + + 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; + } +} + + The constructor arguments specified in the bean definition will be + used as arguments to 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: + + <bean id="exampleBean" class="examples.ExampleBean" + factory-method="createInstance"> +<constructor-arg ref="anotherExampleBean"/> +<constructor-arg ref="yetAnotherBean"/> +<constructor-arg value="1"/> +</bean> + +<bean id="anotherExampleBean" class="examples.AnotherBean"/> +<bean id="yetAnotherBean" class="examples.YetAnotherBean"/> + + public class 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) { + + ExampleBean eb = new ExampleBean (...); + // some other operations... + return eb; + } +} + + Arguments to the static factory method are + supplied via <constructor-arg/> elements, + exactly the same as if a constructor had actually been used. The type of + the class being returned by the factory method does not have to be of + the same type as the class that contains the static + factory method, although in this example it is. An instance (non-static) + factory method would be used in an essentially identical fashion (aside + from the use of the factory-bean attribute instead of + the class attribute), so details will not be + discussed here. +
+
+ +
+ Dependencies and configuration in detail + + As mentioned in the previous section, you can define bean properties + and constructor arguments as references to other managed beans + (collaborators), or as values defined inline. Spring's XML-based + configuration metadata supports sub-element types within its + <property/> and + <constructor-arg/> elements for this + purpose. + +
+ Straight values (primitives, <literal>Strings</literal>, and so + on) + + The value attribute of the + <property/> element specifies a property or + constructor argument as a human-readable string representation. As mentioned previously, + JavaBeans PropertyEditors are used to convert these + string values from a String to the actual type of + the property or argument. + + <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> + +<!-- results in a setDriverClassName(String) call --> +<property name="driverClassName" value="com.mysql.jdbc.Driver"/> +<property name="url" value="jdbc:mysql://localhost:3306/mydb"/> +<property name="username" value="root"/> +<property name="password" value="masterkaoli"/> +</bean> + + The following example uses the p-namespace for even more succinct XML configuration. + + <beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:p="http://www.springframework.org/schema/p" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> + +<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" + destroy-method="close" + p:driverClassName="com.mysql.jdbc.Driver" + p:url="jdbc:mysql://localhost:3306/mydb" + p:username="root" + p:password="masterkaoli"/> + +</beans> + + + + The preceding XML is more succinct; however, typos are discovered at + runtime rather than design time, unless you use an IDE such as IntelliJ IDEA or the SpringSource Tool + Suite (STS) that support automatic property completion when you + create bean definitions. Such IDE assistance is highly + recommended. + + You can also configure a java.util.Properties + instance as: + + <bean id="mappings" + class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> + + <!-- typed as a java.util.Properties --> + <property name="properties"> + <value> + jdbc.driver.className=com.mysql.jdbc.Driver + jdbc.url=jdbc:mysql://localhost:3306/mydb + </value> + </property> +</bean> + + The Spring container converts the text inside the + <value/> element into a + java.util.Properties instance by using the + JavaBeans PropertyEditor mechanism. This + is a nice shortcut, and is one of a few places where the Spring team do + favor the use of the nested <value/> element + over the value attribute style. + +
+ The <literal>idref</literal> element + + The idref element is simply an error-proof way + to pass the id (string value - not a reference) + of another bean in the container to a + <constructor-arg/> or + <property/> element. + + <bean id="theTargetBean" class="..."/> + +<bean id="theClientBean" class="..."> + <property name="targetName"> + <idref bean="theTargetBean" /> + </property> +</bean> + + The above bean definition snippet is exactly + equivalent (at runtime) to the following snippet: + + <bean id="theTargetBean" class="..." /> + +<bean id="client" class="..."> + <property name="targetName" value="theTargetBean" /> +</bean> + + The first form is preferable to the second, because using the + idref tag allows the container to validate + at deployment time that the referenced, named + bean actually exists. In the second variation, no validation is + performed on the value that is passed to the + targetName property of the + client bean. Typos are only discovered (with most + likely fatal results) when the client bean is + actually instantiated. If the client bean is a + prototype bean, this typo + and the resulting exception may only be discovered long after the + container is deployed. + + Additionally, if the referenced bean is in the same XML unit, and + the bean name is the 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. + + <property name="targetName"> + <!-- a bean with id 'theTargetBean' must exist; otherwise an exception will be thrown --> + <idref local="theTargetBean"/> +</property> + + A common place (at least in versions earlier than Spring 2.0) + where the <idref/> element brings value is in the configuration + of AOP interceptors in a + ProxyFactoryBean bean definition. Using + <idref/> elements when you specify the interceptor names + prevents you from misspelling an interceptor id. +
+
+ +
+ References to other beans (collaborators) + + The ref element is the final element inside a + <constructor-arg/> or + <property/> definition element. Here you set + the value of the specified property of a bean to be a reference to + another bean (a collaborator) managed by the container. The referenced + bean is a dependency of the bean whose property will be set, and it is + initialized on demand as needed before the property is set. (If the + collaborator is a singleton bean, it may be initialized already by the + container.) All references are ultimately a reference to another object. + Scoping and validation depend on whether you specify the id/name of the + other object through the + bean,local, or + parent attributes. + + Specifying the target bean through the bean + attribute of the <ref/> tag is the most general + form, and allows creation of a reference to any bean in the same + container or parent container, regardless of whether it is in the same + XML file. The value of the 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. + + <ref bean="someBean"/> + + Specifying the target bean through the local + attribute leverages the ability of the XML parser to validate XML id + references within the same file. The value of the + local attribute must be the same as the + id attribute of the target bean. The XML parser + issues an error if no matching element is found in the same file. As + such, using the 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. + + <ref local="someBean"/> + + Specifying the target bean through the parent + attribute creates a reference to a bean that is in a parent container of + the current container. The value of the parent + attribute may be the same as either the id attribute + of the target bean, or one of the values in the name + attribute of the target bean, and the target bean must be in a parent + container of the current one. You use this bean reference variant mainly + when you 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. + + <!-- in the parent context --> +<bean id="accountService" class="com.foo.SimpleAccountService"> + <!-- insert dependencies as required as here --> +</bean> + + <!-- in the child (descendant) context --> +<bean id="accountService" <-- bean name is the same as the parent bean --> + class="org.springframework.aop.framework.ProxyFactoryBean"> + <property name="target"> + <ref parent="accountService"/> <!-- notice how we refer to the parent bean --> + </property> + <!-- insert other configuration and dependencies as required here --> +</bean> +
+ +
+ Inner beans + + A <bean/> element inside the + <property/> or + <constructor-arg/> elements defines a so-called + inner bean. + + <bean id="outer" class="..."> +<!-- instead of using a reference to a target bean, simply define the target bean inline --> +<property name="target"> + <bean class="com.example.Person"> <!-- this is the inner bean --> + <property name="name" value="Fiona Apple"/> + <property name="age" value="25"/> + </bean> +</property> +</bean> + + An inner bean definition does not require a defined id or name; the + container ignores these values. It also ignores the + scope flag. Inner beans are + always anonymous and they are + always scoped as prototypes. It is + not possible to inject inner beans into + collaborating beans other than into the enclosing bean. +
+ +
+ Collections + + In the <list/>, + <set/>, <map/>, and + <props/> elements, you set the properties and + arguments of the Java Collection types + List, Set, + Map, and + Properties, respectively. + + <bean id="moreComplexObject" class="example.ComplexObject"> +<!-- results in a setAdminEmails(java.util.Properties) call --> +<property name="adminEmails"> + <props> + <prop key="administrator">administrator@example.org</prop> + <prop key="support">support@example.org</prop> + <prop key="development">development@example.org</prop> + </props> +</property> +<!-- results in a setSomeList(java.util.List) call --> +<property name="someList"> + <list> + <value>a list element followed by a reference</value> + <ref bean="myDataSource" /> + </list> +</property> +<!-- results in a setSomeMap(java.util.Map) call --> +<property name="someMap"> + <map> + <entry key="an entry" value="just some string"/> + <entry key ="a ref" value-ref="myDataSource"/> + </map> +</property> +<!-- results in a setSomeSet(java.util.Set) call --> +<property name="someSet"> + <set> + <value>just some string</value> + <ref bean="myDataSource" /> + </set> +</property> +</bean> + + The value of a map key or value, or a set value, can also + again be any of the following elements: + + bean | ref | idref | list | set | map | props | value | null + +
+ Collection merging + + As of Spring 2.0, the container supports the + merging of collections. An application developer + can define a parent-style <list/>, + <map/>, <set/> or + <props/> element, and have child-style + <list/>, <map/>, + <set/> or <props/> + elements inherit and override values from the parent collection. That + is, the child collection's values are the result of merging the + elements of the parent and child collections, with the child's + collection elements overriding values specified in the parent + collection. + + This section on merging discusses the parent-child bean + mechanism. Readers unfamiliar with parent and child bean definitions + may wish to read the relevant section before continuing. + + The following example demonstrates collection merging: + + <beans> +<bean id="parent" abstract="true" class="example.ComplexObject"> + <property name="adminEmails"> + <props> + <prop key="administrator">administrator@example.com</prop> + <prop key="support">support@example.com</prop> + </props> + </property> +</bean> +<bean id="child" parent="parent"> + <property name="adminEmails"> + <!-- the merge is specified on the *child* collection definition --> + <props merge="true"> + <prop key="sales">sales@example.com</prop> + <prop key="support">support@example.co.uk</prop> + </props> + </property> +</bean> +<beans> + + Notice the use of the merge=true attribute on + the <props/> element of the + adminEmails property of the + child bean definition. When the + child bean is resolved 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. + + administrator=administrator@example.com +sales=sales@example.com +support=support@example.co.uk + + The child Properties collection's value set + inherits all property elements from the parent + <props/>, and the child's value for the + support value overrides the value in the parent + collection. + + This merging behavior applies similarly to the + <list/>, <map/>, and + <set/> collection types. In the specific case + of the <list/> element, the semantics + associated with the List collection type, that + is, the notion of an ordered collection of values, + is maintained; the parent's values precede all of the child list's + values. In the case of the Map, + Set, and + Properties collection types, no + ordering exists. Hence no ordering semantics are in effect for the + collection types that underlie the associated + Map, + Set, and + Properties implementation types that + the container uses internally. +
+ +
+ Limitations of collection merging + + You cannot merge different collection types (such as a + Map and a + List), and if you 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. +
+ +
+ 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. + + public class Foo { + + private Map<String, Float> accounts; + + public void setAccounts(Map<String, Float> accounts) { + this.accounts = accounts; + } +} + + <beans> + <bean id="foo" class="x.y.Foo"> + <property name="accounts"> + <map> + <entry key="one" value="9.99"/> + <entry key="two" value="2.75"/> + <entry key="six" value="3.99"/> + </map> + </property> + </bean> +</beans> + + When the accounts property of the + foo bean is prepared for injection, the generics + information about the element type of the strongly-typed + Map<String, Float> is available by + reflection. Thus Spring's type conversion infrastructure recognizes + the various value elements as being of type + Float, and the string values 9.99, + 2.75, and 3.99 are converted into an + actual Float type. +
+
+ +
+ Null and empty string values + + Spring + treats empty arguments for properties and the like as empty + Strings. The following XML-based configuration + metadata snippet sets the email property to the empty + String value ("") + + <bean class="ExampleBean"> +<property name="email" value=""/> +</bean> + + The preceding example is equivalent to the following Java code: + exampleBean.setEmail(""). The + <null/> element handles null + values. For example: + + <bean class="ExampleBean"> +<property name="email"><null/></property> +</bean> + + The above configuration is equivalent to the following Java code: + exampleBean.setEmail(null). +
+ +
+ XML shortcut with the p-namespace + + The p-namespace enables you to use the bean + element's attributes, instead of nested + <property/> elements, to describe your property + values and/or collaborating beans. + + Spring 2.0 and later supports extensible configuration formats with namespaces, 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. + + <beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:p="http://www.springframework.org/schema/p" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> + + <bean name="classic" class="com.example.ExampleBean"> + <property name="email" value="foo@bar.com"/> + </bean> + + <bean name="p-namespace" class="com.example.ExampleBean" + p:email="foo@bar.com"/> +</beans> + + The example shows an attribute in the p-namespace called email in + the bean definition. This tells Spring to include a property + declaration. As previously mentioned, the p-namespace does not have a + schema definition, so you can set the name of the attribute to the + property name. + + This next example includes two more bean definitions that both have + a reference to another bean: + + <beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:p="http://www.springframework.org/schema/p" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> + + <bean name="john-classic" class="com.example.Person"> + <property name="name" value="John Doe"/> + <property name="spouse" ref="jane"/> + </bean> + + <bean name="john-modern" + class="com.example.Person" + p:name="John Doe" + p:spouse-ref="jane"/> + + <bean name="jane" class="com.example.Person"> + <property name="name" value="Jane Doe"/> + </bean> +</beans> + + As you can see, this example includes not only a property value + using the p-namespace, but also uses a special format to declare + property references. Whereas the first bean definition uses + <property name="spouse" ref="jane"/> to create + a reference from bean john to bean + jane, the second bean definition uses + p:spouse-ref="jane" as an attribute to do the exact + same thing. In this case spouse is the property name, + whereas the -ref part indicates that this is not a + straight value but rather a reference to another bean. + + + The p-namespace is not as flexible as the standard XML format. For + example, the format for declaring property references clashes with + properties that end in Ref, whereas the standard + XML format does not. We recommend that you choose your approach + carefully and communicate this to your team members, to avoid + producing XML documents that use all three approaches at the same + time. + +
+ +
+ Compound property names + + You can use compound or nested property names when you set bean + properties, as long as all components of the path except the final + property name are not null. Consider the following + bean definition. + + <bean id="foo" class="foo.Bar"> +<property name="fred.bob.sammy" value="123" /> +</bean> + + The foo bean has a fred + property, which has a bob property, which has a + sammy property, and that final + sammy property is being set to the value + 123. In order for this to work, the + fred property of foo, and the + bob property of fred must not be + null after the bean is constructed, or a + NullPointerException is thrown. +
+
+ +
+ Using <literal>depends-on</literal> + + 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 + <ref/> + 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 explicitly + force one or more beans to be initialized before the bean using this + element is initialized. The following example uses the + depends-on attribute to express a dependency on a + single bean: + + <bean id="beanOne" class="ExampleBean" depends-on="manager"/> + +<bean id="manager" class="ManagerBean" /> + + 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: + + <bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"> +<property name="manager" ref="manager" /> +</bean> + +<bean id="manager" class="ManagerBean" /> +<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" /> + + + The depends-on attribute in the bean definition + can specify both an initialization time dependency and, in the case of + singleton 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. + +
+ +
+ Lazy-initialized + beans<!--Changed to lazy-initialized from lazily instantiated because attribute is lazy-init, and there was a lot of inconsistency. --> + + By default, ApplicationContext + implementations eagerly create and configure all singleton beans as part of + the initialization process. Generally, this pre-instantiation is + desirable, because errors in the configuration or surrounding environment + are discovered immediately, as opposed to hours or even days later. When + this behavior is not desirable, you can prevent + pre-instantiation of a singleton bean by marking the bean definition as + lazy-initialized. A lazy-initialized bean tells the IoC container to + create a bean instance when it is first requested, rather than at + startup. + + In XML, this behavior is controlled by the + lazy-init attribute on the + <bean/> element; for example: + + <bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/> + +<bean name="not.lazy" class="com.foo.AnotherBean"/> + + When the preceding configuration is consumed by an + ApplicationContext, the bean named + lazy is not eagerly pre-instantiated when the + ApplicationContext is starting up, whereas + the not.lazy bean is eagerly pre-instantiated. + + However, when a lazy-initialized bean is a dependency of a singleton + bean that is not lazy-initialized, the + ApplicationContext creates the + lazy-initialized bean at startup, because it must satisfy the singleton's + dependencies. The lazy-initialized bean 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 + <beans/> element; for example: + + <beans default-lazy-init="true"> + <!-- no beans will be pre-instantiated... --> +</beans> +
+ +
+ Autowiring collaborators + + + + The Spring container can autowire relationships + between collaborating beans. You can allow Spring to resolve collaborators + (other beans) automatically for your bean by inspecting the contents of + the ApplicationContext. Autowiring has the + following advantages: + + + + Autowiring can significantly reduce the need to specify properties + or constructor arguments. (Other mechanisms such as a bean template + discussed elsewhere in + this chapter are also valuable in this regard.) + + + + Autowiring can update a configuration as your objects evolve. For + example, if you need to add a dependency to a class, that dependency + can be satisfied automatically without you needing to modify the + configuration. Thus autowiring can be especially useful during + development, without negating the option of switching to explicit + wiring when the code base becomes more stable. + + When using XML-based configuration metadata + See + , you specify autowire mode for a bean definition with the + autowire attribute of the + <bean/> element. The autowiring functionality has + five modes. You specify autowiring per bean and thus + can choose which ones to autowire. + + + Autowiring modes + + + + + + + + + Mode + + Explanation + + + + + + no + + (Default) No autowiring. Bean references must be + defined via a ref element. Changing the default + setting is not recommended for larger deployments, because + specifying collaborators explicitly gives greater control and + clarity. To some extent, it documents the structure of a + system. + + + + byName + + Autowiring by property name. Spring looks for a bean + with the same name as the property that needs to be autowired. For + example, if a bean definition is set to autowire by name, and it + contains a master property (that is, it has a + setMaster(..) method), Spring looks for a + bean definition named master, and uses it to + set the property. + + + + byType + + Allows a property to be autowired if exactly one bean + of the property type exists in the container. If more than one + exists, a fatal exception is thrown, which indicates that you may + not use byType autowiring for that bean. If + there are no matching beans, nothing happens; the property is not + set. + + + + constructor + + Analogous to byType, but applies + to constructor arguments. If there is not exactly one bean of the + constructor argument type in the container, a fatal error is + raised. + + + + +
+ + With byType or constructor + autowiring mode, you can wire arrays and typed-collections. In such cases + all autowire candidates within the container that + match the expected type are provided to satisfy the dependency. You can + autowire strongly-typed Maps if the expected key type is + String. An autowired Maps values will consist of + all bean instances that match the expected type, and the Maps keys will + contain the corresponding bean names. + + You can combine autowire behavior with dependency checking, which is + performed after autowiring completes. + +
+ Limitations and disadvantages of autowiring + + Autowiring works best when it is used consistently across a project. + If autowiring is not used in general, it might be confusing to + developers to use it to wire only one or 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, + 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, Spring is careful to avoid guessing in + case of ambiguity that might have unexpected results, the + relationships between your Spring-managed objects are no longer + documented explicitly. + + + + Wiring information may not be available to tools that may + generate documentation from a Spring container. + + + + + + Multiple bean definitions within the container may match the + type specified by the setter method or constructor argument to be + autowired. For arrays, collections, or Maps, this is not necessarily + a problem. However for dependencies that expect a single value, this + ambiguity is not arbitrarily resolved. If no unique bean definition + is available, an exception is thrown. + + + + In the latter scenario, you have several options: + + + + Abandon autowiring in favor of explicit wiring. + + + + Avoid autowiring for a bean definition by setting its + autowire-candidate attributes to + false as described in the next section. + + + + Designate a single bean definition as the + primary candidate by setting the + primary attribute of its + <bean/> element to + true. + + + + If you are using Java 5 or later, implement the more + fine-grained control available with annotation-based configuration, + as described in . + + +
+ +
+ Excluding a bean from autowiring + + On a per-bean basis, you can exclude a bean from autowiring. In + Spring's XML format, set the autowire-candidate + attribute of the <bean/> element to + false; the container makes that specific bean + definition unavailable to the autowiring infrastructure (including + annotation style configurations such as @Autowired). + + You can also limit autowire candidates based on pattern-matching + against bean names. The top-level <beans/> + 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 + 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. + + These techniques are useful for beans that you never want to be + injected into other beans by autowiring. It does not mean that an + excluded bean cannot itself be configured using autowiring. Rather, the + bean itself is not a candidate for autowiring other beans. + + +
+
+ +
+ Method injection + + In most application scenarios, most beans in the container are singletons. When a + singleton bean needs to collaborate with another singleton bean, or a + non-singleton bean needs to collaborate with another non-singleton bean, + you typically handle the dependency by defining one bean as a property of + the other. A problem arises when the bean lifecycles are different. + Suppose singleton bean A needs to use non-singleton (prototype) bean B, + perhaps on each method invocation on A. The container only creates the + singleton bean A once, and thus only gets one opportunity to set the + properties. The container cannot provide bean A with a new instance of + bean B every time one is needed. + + A solution is to forego some inversion of control. You can make bean A aware of the container by + implementing the ApplicationContextAware + interface, and by making a + getBean("B") call to the container ask for (a typically new) bean B + instance every time bean A needs it. The following is an example of this + approach: + + // 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; + +public class CommandManager implements ApplicationContextAware { + + 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(); + } + + 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; + } +} + + The preceding is not desirable, because the business code is aware of + and coupled to the Spring Framework. Method Injection, a somewhat advanced + feature of the Spring IoC container, allows this use case to be handled in + a clean + fashion. + + + You can read more about the motivation for Method Injection in + this blog entry. + + +
+ Lookup method injection + + + + Lookup method injection is the ability of the container to override + methods on container managed beans, to return the + lookup result for another named bean in the container. The lookup + typically involves a prototype bean as in the scenario described in the + preceding section. The Spring Framework implements this method injection + by using bytecode generation from the CGLIB library to generate + dynamically a subclass that overrides the + method. + + + For this dynamic subclassing to work, you must have the CGLIB + jar(s) in your classpath. The class that the Spring container will + subclass cannot be final, and the method to be + overridden cannot be final either. Also, testing a + class that has an abstract method requires you to + subclass the class yourself and to supply a stub implementation of the + abstract method. Finally, objects that have been + the target of method injection cannot be serialized. + + + Looking at the CommandManager class in the + previous code snippet, you see that the Spring container will + dynamically override the implementation of the + createCommand() method. Your + CommandManager class will not have any Spring + dependencies, as can be seen in the reworked example: + + package fiona.apple; + +// no more Spring imports! + +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(); + } + + // 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: + + <public|protected> [abstract] <return-type> 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: + + <!-- a stateful bean deployed as a prototype (non-singleton) --> +<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype"> +<!-- inject dependencies here as required --> +</bean> + +<!-- commandProcessor uses statefulCommandHelper --> +<bean id="commandManager" class="fiona.apple.CommandManager"> +<lookup-method name="createCommand" bean="command"/> +</bean> + + The bean identified as commandManager calls its + own method createCommand() whenever it needs a + new instance of the command bean. You must be + careful to deploy the command bean as a prototype, if + that is actually what is needed. If it is deployed as a singleton, the same + instance of the command bean is returned each + time. + + + 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, + ObjectFactoryCreatingFactoryBean, but it allows + you to specify your own lookup interface as opposed to a + Spring-specific lookup interface. Consult the JavaDocs for these + classes as well as this blog entry for additional information + ServiceLocatorFactoryBean. + +
+ +
+ Arbitrary method replacement + + A less useful form of method injection than lookup method Injection + is the ability to replace arbitrary methods in a managed bean with + another method implementation. Users may safely skip the rest of this + section until the functionality is actually + needed. + + With XML-based configuration metadata, you can use the + replaced-method element to replace an existing method + implementation with another, for a deployed bean. Consider the following + class, with a method computeValue, which we want to override: + + public class MyValueCalculator { + +public String computeValue(String input) { + // some real code... +} + +// some other methods... + +} + + A class implementing the + org.springframework.beans.factory.support.MethodReplacer + interface provides the new method definition. + + /** 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 ...; + } +} + + The bean definition to deploy the original class and specify the + method override would look like this: + + <bean id="myValueCalculator" class="x.y.z.MyValueCalculator"> + +<!-- arbitrary method replacement --> +<replaced-method name="computeValue" replacer="replacementComputeValue"> + <arg-type>String</arg-type> +</replaced-method> +</bean> + +<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/> + + You can use one or more contained + <arg-type/> elements within the + <replaced-method/> element to indicate the + method signature of the method being overridden. The signature for the + arguments is necessary only if the method is overloaded and multiple + variants exist within the class. For convenience, the type string for an + argument may be a substring of the fully qualified type name. For + example, the following all match + java.lang.String: + + java.lang.String + String + Str + + Because the number of arguments is often enough to distinguish + between each possible choice, this shortcut can save a lot of typing, by + allowing you to type only the shortest string that will match an + argument type. +
+
+
diff --git a/spring-framework-reference/src/beans-extension-points.xml b/spring-framework-reference/src/beans-extension-points.xml new file mode 100644 index 00000000000..e0c9747cfe3 --- /dev/null +++ b/spring-framework-reference/src/beans-extension-points.xml @@ -0,0 +1,519 @@ + + +
+ Container extension points + + Typically, an application developer does not need to subclass any + ApplicationContext implementation classes. + You can extend The Spring IoC container infinitely by plugging in + implementations of special integration interfaces. The next few sections + describe these integration interfaces. + +
+ Customizing beans using the + <interfacename>BeanPostProcessor</interfacename> Interface <literal> + </literal> + + The BeanPostProcessor interface defines + callback methods that you can implement to provide + your own (or override the container's default) instantiation logic, + dependency-resolution logic, and so forth. If you want to implement some + custom logic after the Spring container finishes instantiating, + configuring, and otherwise initializing a bean, you can plug in one or + more BeanPostProcessor + implementations. + + You can configure multiple BeanPostProcessor + interfaces. You can control the order in which these + BeanPostProcessor interfaces execute by setting the + order property. You can set this property only if the + BeanPostProcessor implements the + Ordered interface; if you write your own + BeanPostProcessor you should consider + implementing the Ordered interface too. For + more details, consult the Javadoc for the + BeanPostProcessor and + Ordered interfaces. + + + BeanPostProcessors operate on bean (or object) + instances; that is to say, the Spring IoC container + instantiates a bean instance and then + BeanPostProcessor interfaces do their work. + + BeanPostProcessor interfaces are scoped + per-container. This is only relevant if you are + using container hierarchies. If you define a + BeanPostProcessor in one container, it + will only do its work on the beans in that + container. Beans that are defined in one container are not + post-processed by a BeanPostProcessor in another + container, even if both containers are part of the same + hierarchy. + + To change the actual bean definition (that is, the recipe that + defines the bean), you instead need to use a + BeanFactoryPostProcessor, described below + in . + + + The + org.springframework.beans.factory.config.BeanPostProcessor + interface consists of exactly two callback methods. When such a class is + registered as a post-processor with the container, for each bean instance + that is created by the container, the post-processor gets a callback from + the container both before container initialization + methods (such as afterPropertiesSet and any declared + init method) are called, and also afterwards. The post-processor can take + any action with the bean instance, including ignoring the callback + completely. A bean post-processor typically checks for callback + interfaces, or may wrap a bean with a proxy. Some Spring AOP + infrastructure classes are implemented as bean post-processors and they do + this proxy-wrapping logic. + + An ApplicationContext + automatically detects any beans that are defined in + the configuration metadata it receives that implement the + BeanPostProcessor interface. The + ApplicationContext registers these beans as + post-processors, to be then called appropriately by the container upon + bean creation. You can then deploy the post-processors as you would any + bean. + + + <interfacename>BeanPostProcessors</interfacename> and AOP + auto-proxying + + Classes that implement the + BeanPostProcessor interface are + special, and so they are treated differently by the + container. All BeanPostProcessors + and their directly referenced beans are + instantiated on startup, as part of the special startup phase of the + ApplicationContext. Next, all those + BeanPostProcessors are registered in a + sorted fashion - and applied to all further beans. Because AOP + auto-proxying is implemented as a + BeanPostProcessor itself, no + BeanPostProcessors or directly referenced + beans are eligible for auto-proxying, and thus do not have aspects woven + into them. + + For any such bean, you should see an info log message: + Bean foo is not eligible for getting processed by all + BeanPostProcessor interfaces (for example: not eligible for + auto-proxying). + + + The following examples show how to write, register, and use + BeanPostProcessors in the context of an + ApplicationContext. + +
+ Example: Hello World, + <interfacename>BeanPostProcessor</interfacename>-style + + This first example illustrates basic usage. The example shows a + custom BeanPostProcessor implementation + that invokes the toString() method of each bean + as it is created by the container and prints the resulting string to the + system console. + + Find below the custom + BeanPostProcessor implementation class + definition: + + package scripting; + +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.BeansException; + +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... + } + + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + System.out.println("Bean '" + beanName + "' created : " + bean.toString()); + return bean; + } +} + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:lang="http://www.springframework.org/schema/lang" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/lang + http://www.springframework.org/schema/lang/spring-lang-3.0.xsd"> + + <lang:groovy id="messenger" + script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"> + <lang:property name="message" value="Fiona Apple Is Just So Dreamy."/> + </lang:groovy> + + <!-- + when the above bean (messenger) is instantiated, this custom + BeanPostProcessor implementation will output the fact to the system console + --> + <bean class="scripting.InstantiationTracingBeanPostProcessor"/> + +</beans> + + 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 + .) + + The following small driver script executes the preceding code and + configuration: + + import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.scripting.Messenger; + +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); + } +} + + The output of the preceding execution resembles the + following: + + Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 +org.springframework.scripting.groovy.GroovyMessenger@272961 +
+ +
+ Example: The + <classname>RequiredAnnotationBeanPostProcessor</classname> + + Using callback interfaces or annotations in conjunction with a + custom BeanPostProcessor implementation + is a common means of extending the Spring IoC container. An example is + Spring's RequiredAnnotationBeanPostProcessor -- a + BeanPostProcessor implementation that + ships with the Spring distribution which ensures that JavaBean + properties on beans that are marked with an (arbitrary) annotation are + actually (configured to be) dependency-injected with a value. +
+
+ +
+ Customizing configuration metadata with + <interfacename>BeanFactoryPostProcessor</interfacename> interface + + 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 the + BeanPostProcessor, with one major + difference: BeanFactoryPostProcessors 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 any beans other + than BeanFactoryPostProcessors. + + You can configure multiple + BeanFactoryPostProcessors. You can control the order in + which these BeanFactoryPostProcessors execute by + setting the order property. However, you can only set + this property if the + BeanFactoryPostProcessor implements the + Ordered interface. If you write your own + BeanFactoryPostProcessor, you should + consider implementing the Ordered interface + too; consult the Javadoc for the + BeanFactoryPostProcessor and + Ordered interfaces for more details. + + + If you want to change the actual bean instances + (the objects that are created from the configuration metadata), then you + instead need to use a BeanPostProcessor + (described above in . While + it is technically possible to work with bean instances within a + BeanFactoryPostProcessor (e.g. using + BeanFactory.getBean()), doing so causes + premature bean instantiation, violating the usual containter lifecycle. + This may cause negative side effects such as bypassing bean post + processing. + + Also, BeanFactoryPostProcessors are scoped + per-container. This is only relevant if you are + using container hierarchies. If you define a + BeanFactoryPostProcessor in one + container, it will only do its stuff on the bean + definitions in that container. Bean definitions in another container + will not be post-processed by + BeanFactoryPostProcessors in another container, even + if both containers are part of the same hierarchy. + + + A bean factory post-processor is executed automatically when it is + declared inside of an ApplicationContext, + in order to apply changes to the configuration metadata that defines a + container. Spring includes a number of pre-existing bean factory + post-processors, such as PropertyOverrideConfigurer + and PropertyPlaceholderConfigurer. A custom + BeanFactoryPostProcessor can also be used, + for example, to register custom property editors. + + + + An ApplicationContext detects any beans + that are deployed into it and that implement the + BeanFactoryPostProcessor interface. It + automatically uses these beans as bean factory post-processors, at the + appropriate time. You can then deploy these post-processor beans as you + would any other bean. + + + As with BeanPostProcessors, you typically do not + want BeanFactoryPostProcessors marked as + lazy-initialized. If they are marked as such, the Spring container never + instantiates them, and thus they cannot apply their custom logic. If you + use the default-lazy-init attribute on the + declaration of your <beans/> element, be sure + to mark your various + BeanFactoryPostProcessor bean definitions + with lazy-init="false". + + +
+ Example: the + <interfacename>PropertyPlaceholderConfigurer</interfacename> + + You use the + PropertyPlaceholderConfigurer to + externalize property values from a bean definition into another separate + file in the standard Java Properties format. + Doing so enables the person deploying an application to customize + environment-specific properties such as database URLs and passwords, + without the complexity or risk of modifying the main XML definition file + or files for the container. + + + + Consider the following XML-based configuration metadata fragment, + where a DataSource 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 / Log4J / JSP EL style. + + <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> + <property name="locations" value="classpath:com/foo/jdbc.properties"/> +</bean> + +<bean id="dataSource" destroy-method="close" + class="org.apache.commons.dbcp.BasicDataSource"> + <property name="driverClassName" value="${jdbc.driverClassName}"/> + <property name="url" value="${jdbc.url}"/> + <property name="username" value="${jdbc.username}"/> + <property name="password" value="${jdbc.password}"/> +</bean> + + The actual values come from another file in the standard Java + Properties format: + + jdbc.driverClassName=org.hsqldb.jdbcDriver +jdbc.url=jdbc:hsqldb:hsql://production:9002 +jdbc.username=sa +jdbc.password=root + + Therefore, the string ${jdbc.username} is replaced at runtime with + the value 'sa' and similarly for other placeholder values that match to + keys in the property file. The PropertyPlaceholderConfigurer checks for + placeholders in most locations of a bean definition and the placeholder + prefix and suffix can be customized. + + With the context namespace introduced in Spring + 2.5, it is possible to configure property placeholders with a dedicated + configuration element. You can provide multiple locations as a + comma-separated list in the location + attribute. + + <context:property-placeholder location="classpath:com/foo/jdbc.properties"/> + + The PropertyPlaceholderConfigurer does not + look for properties only in the Properties file + you specify, but also checks against the Java + System properties if it cannot find a property + you are trying to use. You can customize this behavior by setting the + systemPropertiesMode property of the configurer. It + has three values that specify configurer behavior: always override, + never override, and override only if the property + is not found in the properties file specified. + + + Consult the Javadoc for the + PropertyPlaceholderConfigurer for more + information. + + + Class name substitution + + You can use the + PropertyPlaceholderConfigurer to substitute + class names, which is sometimes useful when you have to pick a + particular implementation class at runtime. For example: + + <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> + <property name="locations"> + <value>classpath:com/foo/strategy.properties</value> + </property> + <property name="properties"> + <value>custom.strategy.class=com.foo.DefaultStrategy</value> + </property> +</bean> + +<bean id="serviceStrategy" class="${custom.strategy.class}"/> + + If the class cannot be resolved at runtime to a valid class, + resolution of the bean fails when it is about to be created, which is + during the preInstantiateSingletons() phase + of an ApplicationContext for a + non-lazy-init bean. + +
+ +
+ Example: the + <classname>PropertyOverrideConfigurer</classname> + + The PropertyOverrideConfigurer, another bean + factory post-processor, resembles the + PropertyPlaceholderConfigurer, but unlike + the latter, the original definitions can have default values or no + values at all for bean properties. If an overriding + Properties file does not have an entry for a + certain bean property, the default context definition is used. + + Note that the bean definition is not aware of + being overridden, so it is not immediately obvious from the XML + definition file that the override configurer is used. In case of + multiple PropertyOverrideConfigurer instances + that define different values for the same bean property, the last one + wins, due to the overriding mechanism. + + Properties file configuration lines take this format: + + beanName.property=value + + For example: + + dataSource.driverClassName=com.mysql.jdbc.Driver +dataSource.url=jdbc:mysql:mydb + + This example file is usable against a container definition that + contains a bean called dataSource, which has + driver and url + properties. + + Compound property names are also supported, as long as every + component of the path except the final property being overridden is + already non-null (presumably initialized by the constructors). In this + example... + + foo.fred.bob.sammy=123 + + ... the sammy property of the + bob property of the fred property + of the foo bean is set to the scalar value + 123. + + + Specified override values are always literal + values; they are not translated into bean references. This convention + also applies when the original value in the XML bean 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: + + <context:property-override location="classpath:override.properties"/> +
+
+ +
+ Customizing instantiation logic with the + <interfacename>FactoryBean</interfacename> Interface <literal> + </literal> + + You implement the + org.springframework.beans.factory.FactoryBean + interface for objects that are themselves + factories. + + The FactoryBean interface is a point of + pluggability into the Spring IoC container's instantiation logic. If you + have complex initialization code that is better expressed in Java as + opposed to a (potentially) verbose amount of XML, you can create your own + FactoryBean, write the complex + initialization inside that class, and then plug your custom + FactoryBean into the container. + + The FactoryBean interface provides + three methods: + + + + Object getObject(): returns an instance + of the object this factory creates. The instance can possibly be + shared, depending on whether this factory returns singletons or + prototypes. + + + + boolean isSingleton(): returns + true if this + FactoryBean returns singletons, + false otherwise. + + + + Class getObjectType(): returns the object + type returned by the getObject() method or + null if the type is not known in advance + + + + The FactoryBean concept and interface + is used in a number of places within the Spring Framework; more than 50 + implementations of the FactoryBean + interface ship with Spring itself. + + When you need to ask a container for an actual + FactoryBean instance itself, not the bean + it produces, you preface the bean id with the ampersand symbol + & (without quotes) when calling the + getBean() method of the + ApplicationContext. So for a given + FactoryBean with an id of + myBean, invoking getBean("myBean") + on the container returns the product of the + FactoryBean, and invoking + getBean("&myBean") returns the + FactoryBean instance + itself. +
+
diff --git a/spring-framework-reference/src/beans-java.xml b/spring-framework-reference/src/beans-java.xml new file mode 100644 index 00000000000..7d08848118d --- /dev/null +++ b/spring-framework-reference/src/beans-java.xml @@ -0,0 +1,908 @@ + + +
+ Java-based container configuration + +
+ Basic concepts: <literal>@Configuration</literal> and + <literal>@Bean</literal> + + The central artifact in Spring's new Java-configuration support is the + @Configuration-annotated class. These + classes consist principally of + @Bean-annotated methods that define + instantiation, configuration, and initialization logic for objects to be + managed by the Spring IoC container. + + Annotating a class with the + @Configuration indicates that the class can + be used by the Spring IoC container as a source of bean definitions. The + simplest possible @Configuration class + would read as follows: + @Configuration +public class AppConfig { + @Bean + public MyService myService() { + return new MyServiceImpl(); + } +} + + For those more familiar with Spring <beans/> + XML, the AppConfig class above would be equivalent to: + <beans> + <bean id="myService" class="com.acme.services.MyServiceImpl"/> +</beans> + As you can see, the @Bean annotation plays the same + role as the <bean/> element. The + @Bean annotation 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. +
+ +
+ Instantiating the Spring container using + <literal>AnnotationConfigApplicationContext</literal> + + The sections below document Spring's + AnnotationConfigApplicationContext, new in Spring 3.0. + This versatile ApplicationContext implementation is + capable of accepting not only @Configuration classes as + input, but also plain @Component classes and classes + annotated with JSR-330 metadata. + + When @Configuration classes are provided as input, + the @Configuration class itself is registered as a bean + definition, and all declared @Bean methods within the + class are also registered as bean definitions. + + When @Component and JSR-330 classes are provided, + they are registered as bean definitions, and it is assumed that DI + metadata such as @Autowired or + @Inject are used within those classes where + necessary. + +
+ Simple construction + + In much the same way that Spring XML files are used as input when + instantiating a ClassPathXmlApplicationContext, + @Configuration classes may be used as input when + instantiating an AnnotationConfigApplicationContext. + This allows for completely XML-free usage of the Spring container: + 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: + 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 dependency injection annotations such as + @Autowired. +
+ +
+ Building the container programmatically using + <literal>register(Class<?>...)</literal> + + An AnnotationConfigApplicationContext may be + instantiated using a no-arg constructor and then configured using the + register() method. This approach is particularly + useful when programmatically building an + AnnotationConfigApplicationContext. + 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(); +} +
+ +
+ Enabling component scanning with + <literal>scan(String...)</literal> + + Experienced Spring users will be familiar with the following + commonly-used XML declaration from Spring's context: + namespace + <beans> + <context:component-scan base-package="com.acme"/> +</beans> + In the example above, the com.acme package will be + scanned, looking for any @Component-annotated + classes, and those classes will be registered as Spring bean definitions + within the container. + AnnotationConfigApplicationContext exposes the + scan(String...) method to allow for the same + component-scanning + functionality:public static void main(String[] args) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.scan("com.acme"); + ctx.refresh(); + MyService myService = ctx.getBean(MyService.class); +} + + + 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. + +
+ +
+ Support for web applications with + <literal>AnnotationConfigWebApplicationContext</literal> + + A WebApplicationContext variant of + AnnotationConfigApplicationContext is available with + AnnotationConfigWebApplicationContext. This + implementation may be used when configuring the Spring + ContextLoaderListener servlet listener, Spring MVC + DispatcherServlet, etc. What follows is a + web.xml snippet that configures a typical Spring MVC + web application. Note the use of the contextClass + context-param and init-param: + +<web-app> + <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext + instead of the default XmlWebApplicationContext --> + <context-param> + <param-name>contextClass</param-name> + <param-value> + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + </param-value> + </context-param> + + <!-- Configuration locations must consist of one or more comma- or space-delimited + fully-qualified @Configuration classes. Fully-qualified packages may also be + specified for component-scanning --> + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value>com.acme.AppConfig</param-value> + </context-param> + + <!-- Bootstrap the root application context as usual using ContextLoaderListener --> + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> + + <!-- Declare a Spring MVC DispatcherServlet as usual --> + <servlet> + <servlet-name>dispatcher</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext + instead of the default XmlWebApplicationContext --> + <init-param> + <param-name>contextClass</param-name> + <param-value> + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + </param-value> + </init-param> + <!-- Again, config locations must consist of one or more comma- or space-delimited + and fully-qualified @Configuration classes --> + <init-param> + <param-name>contextConfigLocation</param-name> + <param-value>com.acme.web.MvcConfig</param-value> + </init-param> + </servlet> + + <!-- map all requests for /main/* to the dispatcher servlet --> + <servlet-mapping> + <servlet-name>dispatcher</servlet-name> + <url-pattern>/main/*</url-pattern> + </servlet-mapping> +</web-app> +
+
+ +
+ Composing Java-based configurations + +
+ Using the <literal>@Import</literal> annotation + + Much as the <import/> element is used + within Spring XML files to aid in modularizing configurations, the + @Import annotation allows for loading + @Bean definitions from another configuration + class:@Configuration +public class ConfigA { + public @Bean A a() { return new A(); } +} + +@Configuration +@Import(ConfigA.class) +public class ConfigB { + public @Bean 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: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); +} + 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. + +
+ Injecting dependencies on imported <literal>@Bean</literal> + definitions + + The example above works, but is simplistic. In most practical + scenarios, beans will have dependencies on one another across + configuration classes. When using XML, this is not an issue, per se, + because there is no compiler involved, and one can simply declare + ref="someBean" and trust that Spring will work it + out during container initialization. Of course, when using + @Configuration classes, the Java compiler places + constraints on the configuration model, in that references to other + beans must be valid Java syntax. + + Fortunately, solving this problem is simple. Remember that + @Configuration classes are ultimately just another + bean in the container - this means that they can take advantage 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:@Configuration +public class ServiceConfig { + private @Autowired AccountRepository accountRepository; + + public @Bean TransferService transferService() { + return new TransferServiceImpl(accountRepository); + } +} + +@Configuration +public class RepositoryConfig { + private @Autowired DataSource dataSource; + + public @Bean AccountRepository accountRepository() { + return new JdbcAccountRepository(dataSource); + } +} + +@Configuration +@Import({ServiceConfig.class, RepositoryConfig.class}) +public class SystemTestConfig { + public @Bean 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"); +} + +
+ Fully-qualifying imported beans for ease of navigation + + In the scenario above, using @Autowired works + well and provides the desired modularity, but determining exactly + where the autowired bean definitions are declared is still somewhat + ambiguous. For example, as a developer looking at + ServiceConfig, how do you know exactly where the + @Autowired AccountRepository bean is declared? + It's not explicit in the code, and this may be just fine. Remember + that the SpringSource Tool Suite provides tooling that can render + graphs showing how everything is wired up - that may be all you + need. Also, your Java IDE can easily find all declarations and uses + of the AccountRepository type, and will quickly + show you the location of @Bean methods that + return that type. + + In cases where this ambiguity is not acceptable and you wish to + have direct navigation from within your IDE from one + @Configuration class to another, consider + autowiring the configuration classes themselves: + @Configuration +public class ServiceConfig { + private @Autowired RepositoryConfig repositoryConfig; + + public @Bean 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: + @Configuration +public class ServiceConfig { + private @Autowired RepositoryConfig repositoryConfig; + + public @Bean TransferService transferService() { + return new TransferServiceImpl(repositoryConfig.accountRepository()); + } +} + +@Configuration +public interface RepositoryConfig { + @Bean AccountRepository accountRepository(); +} + +@Configuration +public class DefaultRepositoryConfig implements RepositoryConfig { + public @Bean AccountRepository accountRepository() { + return new JdbcAccountRepository(...); + } +} + +@Configuration +@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config! +public class SystemTestConfig { + public @Bean 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 DefaultRepositoryConfig, and + built-in IDE tooling is still useful: it will be easy for the + developer to get a type hierarchy of + RepositoryConfig implementations. In this way, + navigating @Configuration classes and their + dependencies becomes no different than the usual process of + navigating interface-based code. +
+
+
+ +
+ Combining Java and XML configuration + + Spring's @Configuration class support does not + aim to be a 100% complete replacement for Spring XML. Some facilities + such as Spring XML namespaces remain an ideal way to configure the + container. In cases where XML is convenient or necessary, you have a + choice: either instantiate the container in an "XML-centric" way using, + for example, ClassPathXmlApplicationContext, or in a + "Java-centric" fashion using + AnnotationConfigApplicationContext and the + @ImportResource annotation to import XML as + needed. + +
+ XML-centric use of <literal>@Configuration</literal> + classes + + It may be preferable to bootstrap the Spring container from XML + and include @Configuration classes in an ad-hoc + fashion. For example, in a large existing codebase that uses Spring + XML, it will be easier to create @Configuration + classes on an as-needed basis and include them from the existing XML + files. Below you'll find the options for using + @Configuration classes in this kind of + "XML-centric" situation. + +
+ Declaring <literal>@Configuration</literal> classes as plain + Spring <literal><bean/></literal> elements + + Remember that @Configuration classes are + ultimately just bean definitions in the container. In this example, + we create a @Configuration class named + AppConfig and include it within + system-test-config.xml as a + <bean/>definition. Because + <context:annotation-config/> is switched + on, the container will recognize the + @Configuration annotation, and process the + @Bean methods declared in + AppConfig + properly.@Configuration +public class AppConfig { + private @Autowired DataSource dataSource; + + public @Bean AccountRepository accountRepository() { + return new JdbcAccountRepository(dataSource); + } + + public @Bean TransferService transferService() { + return new TransferService(accountRepository()); + } +} + system-test-config.xml +<beans> + <!-- enable processing of annotations such as @Autowired and @Configuration --> + <context:annotation-config/> + <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> + + <bean class="com.acme.AppConfig"/> + + <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> + <property name="url" value="${jdbc.url}"/> + <property name="username" value="${jdbc.username}"/> + <property name="password" value="${jdbc.password}"/> + </bean> +</beans> + jdbc.properties +jdbc.url=jdbc:hsqldb:hsql://localhost/xdb +jdbc.username=sa +jdbc.password= + public static void main(String[] args) { + ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); + TransferService transferService = ctx.getBean(TransferService.class); + // ... +} + + + In system-test-config.xml above, the + AppConfig<bean/> does not declare an + id element. While it would be acceptable to do + so, it is unnecessary given that no other bean will ever refer to + it, and it is unlikely that it will be explicitly fetched from the + container by name. Likewise with the DataSource + bean - it is only ever autowired by type, so an explicit bean id + is not strictly required. + +
+ +
+ Using <literal><context:component-scan/></literal> to + pick up <literal>@Configuration</literal> classes + + Because @Configuration is meta-annotated with + @Component, + @Configuration-annotated classes are + automatically candidates for component scanning. Using the same + scenario as above, we can redefine + system-test-config.xml to take advantage of + component-scanning. Note that in this case, we don't need to + explicitly declare + <context:annotation-config/>, because + <context:component-scan/> enables all the + same + functionality.system-test-config.xml +<beans> + <!-- picks up and registers AppConfig as a bean definition --> + <context:component-scan base-package="com.acme"/> + <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> + + <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> + <property name="url" value="${jdbc.url}"/> + <property name="username" value="${jdbc.username}"/> + <property name="password" value="${jdbc.password}"/> + </bean> +</beans> +
+
+ +
+ <literal>@Configuration</literal> class-centric use of XML with + <literal>@ImportResource</literal> + + 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 scenarios, + simply use @ImportResource and define only as much + XML as is needed. Doing so achieves a "Java-centric" approach to + configuring the container and keeps XML to a bare minimum. + @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; + + public @Bean DataSource dataSource() { + return new DriverManagerDataSource(url, username, password); + } +} + properties-config.xml +<beans> + <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> +</beans> + jdbc.properties +jdbc.url=jdbc:hsqldb:hsql://localhost/xdb +jdbc.username=sa +jdbc.password= + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); + TransferService transferService = ctx.getBean(TransferService.class); + // ... +} +
+
+
+ +
+ Using the <interfacename>@Bean</interfacename> annotation + + @Bean is a method-level annotation and + a direct analog of the XML <bean/> element. The + annotation supports some of the attributes offered by + <bean/>, such as: init-method, destroy-method, autowiring and + name. + + You can use the @Bean annotation in a + @Configuration-annotated or in a + @Component-annotated class. + +
+ Declaring a bean + + To declare a bean, simply annotate a method with the + @Bean annotation. You use this 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: + @Configuration +public class AppConfig { + + @Bean + public TransferService transferService() { + return new TransferServiceImpl(); + } + +} + + The preceding configuration is exactly equivalent to the following + Spring XML: + <beans> + <bean id="transferService" class="com.acme.TransferServiceImpl"/> +</beans> + + Both declarations make a bean named transferService + available in the ApplicationContext, bound to an object + instance of type TransferServiceImpl: + +transferService -> com.acme.TransferServiceImpl + +
+ +
+ Injecting dependencies + + When @Beans have dependencies on one + another, expressing that dependency is as simple as having one bean + method call another: + @Configuration +public class AppConfig { + + @Bean + public Foo foo() { + return new Foo(bar()); + } + + @Bean + public Bar bar() { + return new Bar(); + } + +} + + In the example above, the foo bean receives a reference + to bar via constructor injection. +
+ +
+ Receiving lifecycle callbacks + + Beans declared in a + @Configuration-annotated class support + the regular lifecycle callbacks. Any classes defined with the + @Bean annotation can use the + @PostConstruct and @PreDestroy + annotations from JSR-250, see JSR-250 + annotations for further details. + + The regular Spring lifecycle callbacks are fully supported as well. If a bean + implements InitializingBean, DisposableBean, + or Lifecycle, their respective methods are called by the + container. + + The standard set of *Aware interfaces such as + BeanFactoryAware, + BeanNameAware, + MessageSourceAware, ApplicationContextAware, and + so on are also fully supported. + + The @Bean annotation supports + specifying arbitrary initialization and destruction callback methods, + much like Spring XML's init-method and + destroy-method attributes on the bean element: + public class Foo { + public void init() { + // initialization 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(); + } +} + + + Of course, in the case of Foo above, it would be + equally as valid to call the init() method directly during + construction: + @Configuration +public class AppConfig { + @Bean + public Foo foo() { + Foo foo = new Foo(); + foo.init(); + return foo; + } + + // ... +} + + + When you work directly in Java, you can do anything you like with + your objects and do not always need to rely on the container + lifecycle! + +
+ +
+ Specifying bean scope + +
+ Using the <interfacename>@Scope</interfacename> + annotation + + + + You can specify that your beans defined with the + @Bean annotation should have a specific + scope. You can use any of the standard scopes specified in the Bean Scopes section. + + The default scope is singleton, but you can + override this with the @Scope + annotation: + @Configuration +public class MyConfiguration { + @Bean + @Scope("prototype") + public Encryptor encryptor() { + // ... + } +} +
+ +
+ <code>@Scope and scoped-proxy</code> + + Spring offers a convenient way of working with scoped dependencies + through scoped + proxies. The easiest way to create such a proxy when using the + XML configuration is the <aop:scoped-proxy/> + element. Configuring your beans in Java with a @Scope annotation + offers equivalent support with the proxyMode attribute. The default is + no proxy (ScopedProxyMode.NO), but you can 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: + // 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; +} +
+ +
+ Lookup method injection + + As noted earlier, lookup method injection is an 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. + 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(); + } + + // 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: + @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(); + } + } +} +
+
+ +
+ Customizing bean naming + + 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. + @Configuration +public class AppConfig { + + @Bean(name = "myFoo") + public Foo foo() { + return new Foo(); + } + +} +
+ + + + +
+ Bean aliasing + + As discussed in , it is sometimes + desirable to give a single bean multiple names, otherwise known as + bean aliasing. The name + attribute of the @Bean annotation accepts a String + array for this purpose. + @Configuration +public class AppConfig { + + @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" }) + public DataSource dataSource() { + // instantiate, configure and return DataSource bean... + } + +} +
+
+ +
+ Further information about how Java-based configuration works + internally + + The following example shows a @Bean annotated + method being called twice: + + +@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 ClientDao clientDao() { + return new ClientDaoImpl(); + } +} + + clientDao() has been called once in + clientService1() and once in + clientService2(). Since this method creates a new + instance of ClientDaoImpl and returns it, you would + normally expect having 2 instances (one for each service). That definitely + would be problematic: in Spring, instantiated beans have a + singleton scope by default. This is where the magic + comes in: All @Configuration classes are subclassed at + startup-time with CGLIB. In the subclass, the child + method checks the container first for any cached (scoped) beans before it + calls the parent method and creates a new instance. + + The behavior could be different according to the scope of your + bean. We are talking about singletons here. + + + Beware that, in order for JavaConfig to work, you must include the + CGLIB jar in your list of dependencies. + + + There are a few restrictions due to the fact that CGLIB dynamically + adds features at startup-time: + + Configuration classes should not be final + + + They should have a constructor with no arguments + + + +
+
diff --git a/spring-framework-reference/src/beans-scopes.xml b/spring-framework-reference/src/beans-scopes.xml new file mode 100644 index 00000000000..4c994049411 --- /dev/null +++ b/spring-framework-reference/src/beans-scopes.xml @@ -0,0 +1,686 @@ + + +
+ Bean scopes + + When you create a bean definition, you create a + recipe for creating actual instances of the class + defined by that bean definition. The idea that a bean definition is a recipe + is important, because it means that, as with a class, you can create many + object instances from a single recipe. + + You can control not only the various dependencies and configuration + values that are to be plugged into an object that is created from a + particular bean definition, but also the scope of the + objects created from a particular bean definition. This approach is powerful + and flexible in that you can choose the scope of the + objects you create through configuration instead of having to bake in the + scope of an object at the Java class level. Beans can be defined to be + deployed in one of a number of scopes: out of the box, the Spring Framework + supports five scopes, three of which are available only if you use a + web-aware ApplicationContext. + + The following scopes are supported out of the box. You can also create + a custom scope. + + + Bean scopes + + + + + Scope + + Description + + + + + + singleton + + (Default) Scopes a single bean definition to a single + object instance per Spring IoC container. + + + + prototype + + Scopes a single bean definition to any number of object + instances. + + + + request + + 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. + + + + session + + Scopes a single bean definition to the lifecycle of an + HTTP Session. Only valid in the + context of a web-aware Spring + ApplicationContext. + + + + global session + + 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. + + + +
+ + + Thread-scoped beans + + As of Spring 3.0, a thread scope is available, + but is not registered by default. For more information, see the + documentation for SimpleThreadScope. For instructions on how to register this or + any other custom scope, see . + + +
+ The singleton scope + + Only one shared instance of a singleton bean is + managed, and all requests for beans with an id or ids matching that bean + definition result in that one specific bean 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 return the cached object. + + + + + + + + + + + + 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 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: + + <bean id="accountService" class="com.foo.DefaultAccountService"/> + +<!-- the following is equivalent, though redundant (singleton scope is the default) --> +<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/> +
+ +
+ The prototype scope + + The non-singleton, prototype scope of bean deployment results in the + creation of a new bean instance every time a request + for that specific bean is made. That is, the bean is injected into another + bean or you request it through a getBean() method call + on the container. As a rule, use the prototype scope for all stateful + beans and the singleton scope for stateless beans. + + The following diagram illustrates the Spring prototype scope. + A data access object (DAO) is not typically configured as a + prototype, because a typical DAO does not hold any conversational state; + it was just easier for this author to reuse the core of the singleton + diagram. + + + + + + + + + + + + The following example defines a bean as a prototype in XML: + + <!-- using spring-beans-2.0.dtd --> +<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/> + + 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 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 custom bean post-processor, which + holds a reference to beans that need to be cleaned up. + + In some respects, the Spring container's role in regard to a + prototype-scoped bean is a replacement for the Java new + operator. All lifecycle management past that point must be handled by the + client. (For details on the lifecycle of a bean in the Spring container, + see .) +
+ +
+ Singleton beans with prototype-bean dependencies + + When you use singleton-scoped beans with dependencies on prototype + beans, be aware that dependencies are resolved at instantiation + time. Thus if you dependency-inject a prototype-scoped bean + into a singleton-scoped bean, a new prototype bean is instantiated and + then dependency-injected into the singleton bean. The prototype instance + is the sole instance that is ever supplied to the singleton-scoped + bean. + + However, suppose you want the singleton-scoped bean to acquire a new + instance of the prototype-scoped bean repeatedly at runtime. You cannot + dependency-inject a prototype-scoped bean into your singleton bean, + because that injection occurs only once, when the + Spring container is instantiating the singleton bean and resolving and + injecting its dependencies. If you need a new instance of a prototype bean + at runtime more than once, see +
+ +
+ Request, session, and global session scopes + + The request, session, and + global session scopes are only + available if you use a web-aware Spring + ApplicationContext implementation (such as + XmlWebApplicationContext). If you use these scopes + with regular Spring IoC containers such as the + ClassPathXmlApplicationContext, you get an + IllegalStateException complaining about an unknown + bean scope. + +
+ Initial web configuration + + To support the scoping of beans at the request, + session, and global session levels + (web-scoped beans), some minor initial configuration is required before + you define your beans. (This initial setup is not + required for the standard scopes, singleton and prototype.) + + How you accomplish this initial setup depends on your particular + Servlet environment.. + + If you access scoped beans within Spring Web MVC, in effect, within + a request that is processed by the Spring + DispatcherServlet, or + DispatcherPortlet, then no special setup is + necessary: DispatcherServlet and + DispatcherPortlet already expose all 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: + + <web-app> +... +<listener> + <listener-class> + org.springframework.web.context.request.RequestContextListener + </listener-class> +</listener> +... +</web-app> + + If you use an older web container (Servlet 2.3), use the provided + javax.servlet.Filter implementation. The + following snippet of XML configuration must be included in the + web.xml file of your web application if you want to + access web-scoped beans in requests outside of Spring's + DispatcherServlet on a Servlet 2.3 container. (The filter mapping + depends on the surrounding web application configuration, so you must + change it as appropriate.) + + <web-app> +.. +<filter> + <filter-name>requestContextFilter</filter-name> + <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> +</filter> +<filter-mapping> + <filter-name>requestContextFilter</filter-name> + <url-pattern>/*</url-pattern> +</filter-mapping> +... +</web-app> + + DispatcherServlet, + RequestContextListener and + RequestContextFilter all do exactly the same + thing, namely bind the HTTP request object to the + Thread that is servicing that request. This makes + beans that are request- and session-scoped available further down the + call chain. +
+ +
+ Request scope + + Consider the following bean definition: + + <bean id="loginAction" class="com.foo.LoginAction" scope="request"/> + + The Spring container creates a new instance of the + LoginAction bean by using the + loginAction bean definition for each and every HTTP + request. That is, the loginAction bean is scoped at + the HTTP request level. You can change the internal state of the + instance that is created as much as you want, because other instances + created from the same loginAction bean definition + will not see these changes in state; they are particular to an + individual request. When the request completes processing, the bean that + is scoped to the request is discarded. +
+ +
+ Session scope + + Consider the following bean definition: + + <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> + + The Spring container creates a new instance of the + UserPreferences bean by using the + userPreferences bean definition for the lifetime of a + single HTTP Session. In other words, the + userPreferences bean is effectively scoped at the + HTTP Session level. As with + request-scoped beans, you can change the internal + state of the instance that is created as much as you want, knowing that + other HTTP Session instances that are + also using instances created from the same + userPreferences bean definition do not see these + changes in state, because they are particular to an individual HTTP + Session. When the HTTP + Session is eventually discarded, the bean + that is scoped to that particular HTTP + Session is also discarded. +
+ +
+ Global session scope + + Consider the following bean definition: + + <bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/> + + The global session scope is similar to the + standard HTTP Session scope (described above), and + applies only in the context of portlet-based web applications. The + portlet specification defines the notion of a global + Session that is shared among all portlets + that make up a single portlet web application. Beans defined at the + global session scope are scoped (or bound) to the + lifetime of the global portlet + Session. + + If you write a standard Servlet-based web application and you define + one or more beans as having global session scope, the + standard HTTP Session scope is used, and + no error is raised. +
+ +
+ Scoped beans as dependencies + + The Spring IoC container manages not only the instantiation of your + objects (beans), but also the wiring up of collaborators (or + dependencies). If you want to inject (for example) an HTTP request + scoped bean into another bean, you must inject an AOP proxy in place of + the scoped bean. That is, you need to inject a proxy object that exposes + the same public interface as the scoped object but that can also + retrieve the real, target object from the relevant scope (for example, + an HTTP request) and delegate method calls onto the real object. + + + You do not need to use the + <aop:scoped-proxy/> in conjunction with beans + that are scoped as singletons or + prototypes. If you try to create a scoped proxy for + a singleton bean, the + BeanCreationException is raised. + + + 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. + + + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/aop + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + + <!-- an HTTP Session-scoped bean exposed as a proxy --> + <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> + + <!-- this next element effects the proxying of the surrounding bean --> + <aop:scoped-proxy/> + </bean> + + <!-- a singleton-scoped bean injected with a proxy to the above bean --> + <bean id="userService" class="com.foo.SimpleUserService"> + + <!-- a reference to the proxied userPreferences bean --> + <property name="userPreferences" ref="userPreferences"/> + + </bean> +</beans> + + + To create such a proxy, you insert a child + <aop:scoped-proxy/> element into a scoped bean + definition. + (If + you choose class-based proxying, you also need the CGLIB library in your + classpath. See and .) Why do definitions of beans scoped at the + request, session, + globalSession and custom-scope levels require the + <aop:scoped-proxy/> 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.) + + <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> + +<bean id="userManager" class="com.foo.UserManager"> + <property name="userPreferences" ref="userPreferences"/> +</bean> + + In the preceding example, the singleton bean + userManager is injected with a reference to the HTTP + Session-scoped bean + userPreferences. The salient point here is that the + userManager bean is a singleton: it will be + instantiated exactly once per container, and its + dependencies (in this case only one, the + userPreferences bean) are also injected only once. + This means that the userManager bean will only + operate on the exact same userPreferences object, + that is, the one that it was originally injected with. + + + + This is not the behavior you want when + injecting a shorter-lived scoped bean into a longer-lived scoped bean, + for example injecting an HTTP + Session-scoped collaborating bean as a + dependency into singleton bean. Rather, you need a single + userManager object, and for the lifetime of an HTTP + Session, you need a + userPreferences object that is specific to said HTTP + Session. Thus the container creates an + object that exposes the exact same public interface as the + UserPreferences class (ideally an object that + is a UserPreferences + instance) which can fetch the real + UserPreferences object from the scoping mechanism + (HTTP request, Session, etc.). The + container injects this proxy object into the + userManager bean, which is unaware that this + UserPreferences reference is a proxy. In this + example, when a UserManager instance + invokes a method on the dependency-injected + UserPreferences object, it actually is invoking a + method on the proxy. The proxy then fetches the real + UserPreferences object from (in this case) the + HTTP Session, and delegates the 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: + + <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> + <aop:scoped-proxy/> +</bean> + +<bean id="userManager" class="com.foo.UserManager"> + <property name="userPreferences" ref="userPreferences"/> +</bean> + +
+ Choosing the type of proxy to create + + By default, when the Spring container creates a proxy for a bean + that is marked up with the + <aop:scoped-proxy/> element, a + CGLIB-based class proxy is created. This means that you + need to have the CGLIB library in the classpath of your + application. + + 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 the + proxy-target-class attribute of the + <aop:scoped-proxy/> element. Using JDK + interface-based proxies means that you do not need additional + libraries in your application classpath to effect such proxying. + However, it also means that the class of the scoped bean must + implement at least one interface, and that all + collaborators into which the scoped bean is injected must reference + the bean through one of its interfaces. + + <!-- DefaultUserPreferences implements the UserPreferences interface --> +<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"> + <aop:scoped-proxy proxy-target-class="false"/> +</bean> + +<bean id="userManager" class="com.foo.UserManager"> + <property name="userPreferences" ref="userPreferences"/> +</bean> + + For more detailed information about choosing class-based or + interface-based proxying, see . +
+
+
+ +
+ Custom scopes + + As of Spring 2.0, 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. + +
+ Creating a custom scope + + To integrate your custom scope(s) into the Spring container, you + need to implement the + 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 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 the scope, and allow them to be + destroyed. + + The following method returns the object from the underlying scope. + The session scope implementation, for example, returns the + session-scoped bean (and if it does not exist, the method returns a new + instance of the bean, after having bound it to the session for future + reference). + + Object get(String name, ObjectFactory objectFactory) + + The following method removes the object from the underlying scope. + The session scope implementation for example, removes the session-scoped + bean from the underlying session. The object should be returned, but you + can return null if the object with the specified name is not + found. + + 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. + + 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. + + String getConversationId() +
+ +
+ Using a custom scope + + After you write and test one or more custom + Scope implementations, you need to make + 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: + + void registerScope(String scopeName, Scope scope); + + This method is declared on the + ConfigurableBeanFactory interface, which + is available on most of the concrete + ApplicationContext implementations that + ship with Spring via the BeanFactory property. + + The first argument to the registerScope(..) + method is the unique name associated with a scope; examples of such + names in the Spring container itself are singleton + and prototype. The second argument to the + registerScope(..) method is an actual instance + of the custom Scope implementation that + you wish to register and use. + + Suppose that you write your custom + Scope implementation, and then register + it as below. + + + The example below uses SimpleThreadScope which + is included with Spring, but not registered by default. The + instructions would be the same for your own custom + Scope implementations. + + + +Scope threadScope = new SimpleThreadScope(); +beanFactory.registerScope("thread", threadScope); + + You then create bean definitions that adhere to the scoping rules of + your custom Scope: + + <bean id="..." class="..." scope="thread"> + + 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: + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/aop + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + + <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> + <property name="scopes"> + <map> + <entry key="thread"> + <bean class="org.springframework.context.support.SimpleThreadScope"/> + </entry> + </map> + </property> + </bean> + + <bean id="bar" class="x.y.Bar" scope="thread"> + <property name="name" value="Rick"/> + <aop:scoped-proxy/> + </bean> + + <bean id="foo" class="x.y.Foo"> + <property name="bar" ref="bar"/> + </bean> + +</beans> + + + When you place <aop:scoped-proxy/> in a + FactoryBean implementation, it is the + factory bean itself that is scoped, not the object returned from + getObject(). + +
+
+
diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml index dabb662d2ef..d4be73904dd 100644 --- a/spring-framework-reference/src/beans.xml +++ b/spring-framework-reference/src/beans.xml @@ -8,174 +8,176 @@ Introduction to the Spring IoC container and beans This chapter covers the Spring Framework implementation of the - Inversion of Control (IoC) - See + Inversion of Control (IoC) + See 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 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 or location of its - dependencies by using direct construction of classes, or a mechanism such - as the Service Locator pattern. + 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 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 or location of its + dependencies by using direct 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 BeanFactory - interface provides an advanced configuration mechanism capable of managing - any type of object. 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 for use in web - applications. + org.springframework.context packages are the basis for + Spring Framework's IoC container. The BeanFactory interface provides an advanced + configuration mechanism capable of managing any type of object. + 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 + 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 information on using the BeanFactory instead - of the ApplicationContext, refer to . + 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 information on using the BeanFactory instead + of the ApplicationContext, refer to . - In Spring, the objects that form the backbone of your application - and that are managed by the Spring IoC container - are called beans. A bean is an object that is - instantiated, assembled, and otherwise managed by a Spring IoC container. - Otherwise, a bean is simply one of many objects in your application. - Beans, and the dependencies among them, are - reflected in the configuration metadata used by a - container. + In Spring, the objects that form the backbone of your application and + that are managed by the Spring IoC container are + called beans. A bean is an object that is + instantiated, assembled, and otherwise managed by a Spring IoC container. + Otherwise, a bean is simply one of many objects in your application. + Beans, and the dependencies among them, are + reflected in the configuration metadata used by a + container.
Container overview The interface - org.springframework.context.ApplicationContext - represents the Spring IoC container and is responsible for instantiating, - configuring, and assembling the aforementioned beans. The container gets - its instructions on what objects to instantiate, configure, and assemble - by reading configuration metadata. The configuration metadata is - represented in XML, Java annotations, or Java code. It allows you to - express the objects that compose your application and the rich - interdependencies between such objects. + org.springframework.context.ApplicationContext + represents the Spring IoC container and is responsible for instantiating, + configuring, and assembling the aforementioned beans. The container gets + its instructions on what objects to instantiate, configure, and assemble + by reading configuration metadata. The configuration metadata is + represented in XML, Java annotations, or Java code. It allows you to + express the objects that compose your application and the rich + interdependencies 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 ClassPathXmlApplicationContext - or 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 providng a small amount - of XML configuration to declaratively enable support for these additional - metadata formats. + ApplicationContext interface are supplied + out-of-the-box with Spring. In standalone applications it is common to + create an instance of ClassPathXmlApplicationContext or 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 providng a small amount + of XML configuration to declaratively enable support for these 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 of the - application will typically suffice (see ). If you are using the SpringSource Tool - Suite Eclipse-powered development environment or Spring Roo this boilerplate - configuration can be easily created with few mouse clicks or - keystrokes. + 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 of the + application will typically suffice (see ). + If you are using the SpringSource Tool Suite Eclipse-powered development environment + or Spring Roo 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 created and initialized, - you have a fully configured and executable system or application. + application classes are combined with configuration metadata so that after + the ApplicationContext is created and initialized, + you have a fully configured and executable system or application. - - - + + + - The Spring IoC container + The Spring IoC container
Configuration metadata - As the preceding diagram shows, the Spring IoC container consumes - a form of configuration metadata; this - configuration metadata represents how you as an application developer - tell the Spring container to instantiate, configure, and assemble the - objects in your application. + As the preceding diagram shows, the Spring IoC container consumes a + form of configuration metadata; this configuration + metadata represents how you as an application developer tell the Spring + container to instantiate, configure, and assemble the objects in your + application. Configuration metadata is traditionally supplied in a simple and - intuitive XML format, which is what most of this chapter uses to convey - key concepts and features of the Spring IoC container. + intuitive XML format, which is what most of this chapter uses to convey + key concepts and features of the Spring IoC container. 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. + form of configuration metadata. The Spring IoC container itself is + totally decoupled from the format in which this + configuration metadata is actually written. - For information about using other forms of metadata with the - Spring container, see: + For information about using other forms of metadata with the Spring + container, see: Annotation-based - configuration: Spring 2.5 introduced support for - annotation-based configuration metadata. + configuration: Spring 2.5 introduced support for + annotation-based configuration metadata. Java-based configuration: - 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 and - @DependsOn annotations. + 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 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 - <bean/> elements inside a top-level - <beans/> element. + than one bean definition that the container must manage. XML-based + configuration metadata shows these beans configured as + <bean/> elements inside a top-level + <beans/> element. - These bean definitions correspond to the actual objects that make - up your application. Typically you define service layer objects, data - access objects (DAOs), presentation objects such as Struts - Action instances, infrastructure objects - such as Hibernate SessionFactories, JMS - Queues, and so forth. Typically one does - not configure fine-grained domain objects in the container, because it - is usually the responsibility of DAOs and business logic to create and - load domain objects. However, you can use Spring's integration with - AspectJ to configure objects that have been created outside the control - of an IoC container. See Using - AspectJ to dependency-inject domain objects with Spring. + These bean definitions correspond to the actual objects that make up + your application. Typically you define service layer objects, data + access objects (DAOs), presentation objects such as Struts + Action instances, infrastructure objects + such as Hibernate SessionFactories, JMS + Queues, and so forth. Typically one does + not configure fine-grained domain objects in the container, because it + is usually the responsibility of DAOs and business logic to create and + load domain objects. However, you can use Spring's integration with + AspectJ to configure objects that have been created outside the control + of an IoC container. See Using + AspectJ to dependency-inject domain objects with Spring. The following example shows the basic structure of XML-based - configuration metadata: + configuration metadata: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -196,40 +198,40 @@ The footnote should x-ref to first section in that chapter but I can't find the </beans> The id attribute is a string that you use to - identify the individual bean definition. The class - attribute defines the type of the bean and uses the fully qualified - classname. The value of the id attribute refers to collaborating - objects. The XML for referring to collaborating objects is not shown in - this example; see Dependencies - for more information. + identify the individual bean definition. The class + attribute defines the type of the bean and uses the fully qualified + classname. The value of the id attribute refers to collaborating + objects. The XML for referring to collaborating objects is not shown in + this example; see Dependencies + for more information.
Instantiating a container Instantiating a Spring IoC container is straightforward. The - location path or paths supplied to an - ApplicationContext constructor are - actually resource strings that allow 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. + location path or paths supplied to an + ApplicationContext constructor are + actually resource strings that allow 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. ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); - After you learn about Spring's IoC container, you may want to - know more about Spring's Resource - abstraction, as described in , which - provides a convenient mechanism for reading an InputSream from - locations defined in a URI syntax. In particular, - Resource paths are used to construct - applications contexts as described in . + After you learn about Spring's IoC container, you may want to know + more about Spring's Resource + abstraction, as described in , which + provides a convenient mechanism for reading an InputSream from + locations defined in a URI syntax. In particular, + Resource paths are used to construct + applications contexts as described in . The following example shows the service layer objects - (services.xml) configuration file: + (services.xml) configuration file: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -239,7 +241,7 @@ The footnote should x-ref to first section in that chapter but I can't find the <!-- services --> - <bean id="petStore" + <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="itemDao" ref="itemDao"/> @@ -252,7 +254,7 @@ The footnote should x-ref to first section in that chapter but I can't find the The following example shows the data access objects - daos.xml file: + daos.xml file: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -274,30 +276,30 @@ The footnote should x-ref to first section in that chapter but I can't find the </beans> 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 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 Dependencies. + PetStoreServiceImpl, and two data access objects + of the type SqlMapAccountDao and SqlMapItemDao + are based on the 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 Dependencies.
Composing XML-based configuration metadata - It can be useful to have bean definitions span multiple XML - files. Often each individual XML configuration file represents a - logical layer or module in your architecture. + It can be useful to have bean definitions span multiple XML files. + Often each individual XML configuration file represents a logical + layer or module in your architecture. You can use the application context constructor to load bean - definitions from all these XML fragments. This constructor takes - multiple Resource locations, as was - shown in the previous section. Alternatively, use one or more - occurrences of the <import/> element to load - bean definitions from another file or files. For example: + definitions from all these XML fragments. This constructor takes + multiple Resource locations, as was + shown in the previous section. Alternatively, use one or more + occurrences of the <import/> element to load + bean definitions from another file or files. For example: <beans> @@ -311,38 +313,38 @@ The footnote should x-ref to first section in that chapter but I can't find the </beans> In the preceding example, external bean definitions are loaded - from three files, services.xml, - messageSource.xml, and - themeSource.xml. All location paths are relative to - the definition file doing the importing, so - services.xml must be in the same directory or - classpath location as the file doing the importing, while - messageSource.xml and - themeSource.xml must be in a - resources location below the 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 <beans/> element, must be valid XML - bean definitions according to the Spring Schema or DTD. + from three files, services.xml, + messageSource.xml, and + themeSource.xml. All location paths are relative to + the definition file doing the importing, so + services.xml must be in the same directory or + classpath location as the file doing the importing, while + messageSource.xml and + themeSource.xml must be in a + resources location below the 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 <beans/> element, must be valid XML + bean definitions according to the Spring Schema or DTD. It is possible, but not recommended, to reference files in - parent directories using a relative "../" path. Doing so creates a - dependency on a file that is outside the current application. In - particular, this reference is not recommended for "classpath:" URLs - (for example, "classpath:../services.xml"), where the runtime - resolution process chooses the "nearest" classpath root and then - looks into its parent directory. Classpath configuration changes may - lead to the choice of a different, incorrect directory. + parent directories using a relative "../" path. Doing so creates a + dependency on a file that is outside the current application. In + particular, this reference is not recommended for "classpath:" URLs + (for example, "classpath:../services.xml"), where the runtime + resolution process chooses the "nearest" classpath root and then + looks into its parent directory. Classpath configuration changes may + lead to the choice of a different, incorrect directory. - You can always use fully qualified resource locations instead - of relative paths: for example, "file:C:/config/services.xml" or - "classpath:/config/services.xml". However, be aware that you are - coupling your application's configuration to specific absolute - locations. It is generally preferable to keep an indirection for - such absolute locations, for example, through "${...}" placeholders - that are resolved against JVM system properties at runtime. + You can always use fully qualified resource locations instead of + relative paths: for example, "file:C:/config/services.xml" or + "classpath:/config/services.xml". However, be aware that you are + coupling your application's configuration to specific absolute + locations. It is generally preferable to keep an indirection for + such absolute locations, for example, through "${...}" placeholders + that are resolved against JVM system properties at runtime.
@@ -351,13 +353,13 @@ The footnote should x-ref to first section in that chapter but I can't find the Using the container The ApplicationContext is the - interface for an advanced factory capable of maintaining a registry of - different beans and their dependencies. Using the method T - getBean(Stringname, Class<T> requiredType) you can - retrieve instances of your beans. + interface for an advanced factory capable of maintaining a registry of + different beans and their dependencies. Using the method T + getBean(Stringname, Class<T> requiredType) you can + retrieve instances of your beans. - The ApplicationContext enables you - to read bean definitions and access them as follows: + The ApplicationContext enables you to + read bean definitions and access them as follows: // create and configure beans ApplicationContext context = @@ -371,65 +373,65 @@ List userList service.getUsernameList(); You use getBean() to retrieve instances of - your beans. The ApplicationContext - interface has a few other methods for retrieving beans, but ideally your - application code should never use them. Indeed, your application code - should have no calls to the getBean() method at - all, and thus no dependency on Spring APIs at all. For example, Spring's - integration with web frameworks provides for dependency injection for - various web framework classes such as controllers and JSF-managed - beans. + your beans. The ApplicationContext + interface has a few other methods for retrieving beans, but ideally your + application code should never use them. Indeed, your application code + should have no calls to the getBean() method at + all, and thus no dependency on Spring APIs at all. For example, Spring's + integration with web frameworks provides for dependency injection for + various web framework classes such as controllers and JSF-managed + beans.
Bean overview - A Spring IoC container manages one or more - beans. These beans are created with the configuration - metadata that you supply to the container, for example, in the form of XML - <bean/> definitions. + A Spring IoC container manages one or more beans. + These beans are created with the configuration metadata that you supply to + the container, for example, in the form of XML + <bean/> definitions. - Within the container itself, these bean definitions are represented - as BeanDefinition objects, which contain - (among other information) the following metadata: + Within the container itself, these bean definitions are represented as + BeanDefinition objects, which contain + (among other information) the following metadata: - A package-qualified class name: typically - the actual implementation class of the bean being defined. + A package-qualified class name: typically the + actual implementation class of the bean being defined. Bean behavioral configuration elements, which state how the bean - should behave in the container (scope, lifecycle callbacks, and so - forth). + 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. + work; these 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. + for example, the number of connections to use in a bean that manages a + connection pool, or the size limit of the pool. - This metadata translates to a set of properties that make up each - bean definition. + This metadata translates to a set of properties that make up each bean + definition. The bean definition - + - + @@ -443,176 +445,173 @@ List userList service.getUsernameList(); class - - + name - + scope - - + constructor arguments - - + + properties - - + + autowiring mode - - + + lazy-initialization mode - - + + initialization method - + linkend="beans-factory-lifecycle-initializingbean"/> + destruction method - - +
In addition to bean definitions that contain information on how to - create a specific bean, the - ApplicationContext implementations also - permit the registration of existing objects that are created outside the - container, by users. This is done by accessing the ApplicationContext's - BeanFactory via the method getBeanFactory() which - returns the BeanFactory implementation - DefaultListableBeanFactory. - DefaultListableBeanFactory supports this - registration through the methods - registerSingleton(..) and - registerBeanDefinition(..). However, typical - applications work solely with beans defined through metadata bean - definitions. + create a specific bean, the + ApplicationContext implementations also + permit the registration of existing objects that are created outside the + container, by users. This is done by accessing the ApplicationContext's + BeanFactory via the method getBeanFactory() which + returns the BeanFactory implementation + DefaultListableBeanFactory. + DefaultListableBeanFactory supports this + registration through the methods + registerSingleton(..) and + registerBeanDefinition(..). However, typical + applications work solely with beans defined through metadata bean + definitions.
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. + 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. 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, and because it is a real XML - element ID attribute, the XML parser can do some extra validation when - other elements reference the id. As such, it is the preferred way to - specify a bean identifier. However, the XML specification does limit the - characters that are legal in XML ids. This is usually not a constraint, - but if you need to use one of these special XML characters, or 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. + id and/or name attributes to + specify the bean identifier(s). The id attribute + allows you to specify exactly one id, and because it is a real XML + element ID attribute, the XML parser can do some extra validation when + other elements reference the id. As such, it is the preferred way to + specify a bean identifier. However, the XML specification does limit the + characters that are legal in XML ids. This is usually not a constraint, + but if you need to use one of these special XML characters, or 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. You are not required to supply a name or id for a bean. If no name - or id is supplied explicitly, the container generates a unique name for - that bean. However, if you want to refer to that bean by name, through - the use of the ref element or Service Location style lookup, - you must provide a name. Motivations for not supplying a name are - related to using inner beans - and autowiring - collaborators. + or id is supplied explicitly, the container generates a unique name for + that bean. However, if you want to refer to that bean by name, through + the use of the ref element or Service Location style lookup, + you must provide a name. Motivations for not supplying a name are + related to using inner beans + and autowiring + collaborators. 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 from then on. Examples of such - names would be (without quotes) 'accountManager', - 'accountService', 'userDao', - 'loginController', and so forth. + 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 from then on. Examples of such + names would be (without quotes) 'accountManager', + 'accountService', 'userDao', + 'loginController', and so forth. - Naming beans consistently makes your configuration easier to - read and understand, and if you are using Spring AOP it helps a lot - when applying advice to a set of beans related by name. + Naming beans consistently makes your configuration easier to read + and understand, and if you are using Spring AOP it helps a lot when + applying advice to a set of beans related by name.
Aliasing a bean outside the bean definition - In a bean definition itself, you can supply more than one name - for the bean, by using a combination of up to one name specified by - the id attribute, and any number of other names in - the name attribute. These names can be equivalent - aliases to the same bean, and are useful for some situations, such as - allowing each component in an application to refer to a common - dependency by using a bean name that is specific to that component - itself. + In a bean definition itself, you can supply more than one name for + the bean, by using a combination of up to one name specified by the + id attribute, and any number of other names in the + name attribute. These names can be equivalent + aliases to the same bean, and are useful for some situations, such as + allowing each component in an application to refer to a common + dependency by using a bean name that is specific to that component + itself. Specifying all aliases where the bean is actually defined is not - always adequate, however. It is sometimes desirable to introduce an - alias for a bean that is defined elsewhere. This is commonly the case - in large systems where configuration is split amongst each subsystem, - each subsystem having its own set of object definitions. In XML-based - configuration metadata, you can use the - <alias/> element to accomplish this. + always adequate, however. It is sometimes desirable to introduce an + alias for a bean that is defined elsewhere. This is commonly the case + in large systems where configuration is split amongst each subsystem, + each subsystem having its own set of object definitions. In XML-based + configuration metadata, you can use the + <alias/> element to accomplish this. <alias name="fromName" alias="toName"/> 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. + 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 - 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 MyApp configuration metadata - the following aliases definitions: + 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 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 MyApp configuration metadata the following + aliases definitions: <alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/> <alias name="subsystemA-dataSource" alias="myApp-dataSource" /> 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. + 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.
@@ -620,37 +619,37 @@ List userList service.getUsernameList(); 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. + 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. If you use XML-based configuration metadata, you specify the type - (or class) of object that is to be instantiated in the - class attribute of the - <bean/> element. This class - attribute, which internally is a Class property - on a BeanDefinition instance, is usually - mandatory. (For exceptions, see and .) You use the - Class property in one of two ways: - - Typically, to specify the bean class to be constructed in - the case where the container itself directly creates the bean by - calling its constructor reflectively, somewhat equivalent to Java - code using the new operator. - + (or class) of object that is to be instantiated in the + class attribute of the + <bean/> element. This class + attribute, which internally is a Class property + on a BeanDefinition instance, is usually + mandatory. (For exceptions, see and .) You use the + Class property in one of two ways: + + Typically, to specify the bean class to be constructed in the + case where the container itself directly creates the bean by calling + its constructor reflectively, somewhat equivalent to Java code using + the new operator. + To specify the actual class containing the - static factory method that will be invoked to - create the object, in the less common case where the container - invokes a static, factory - method on a class to create the bean. The object type returned from - the invocation of the static factory method may - be the same class or another class entirely. + static factory method that will be invoked to + create the object, in the less common case where the container + invokes a static, factory + method on a class to create the bean. The object type returned from + the invocation of the static factory method may + be the same class or another class entirely. @@ -658,110 +657,109 @@ List userList service.getUsernameList(); 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. + static nested class, you have to use the + binary name of the inner class. - For example, if you have a class called - Foo in the com.example - package, and this Foo class has a - static inner class called - Bar, the value of the - 'class' attribute on a bean definition would - be... + For example, if you have a class called Foo + in the com.example package, and this + Foo class has a static inner + class called Bar, the value of the + 'class' attribute on a bean definition would + be... com.example.Foo$Bar Notice the use of the $ character in the name - to separate the inner class name from the outer class name. + to separate the inner class name from the outer class name.
Instantiation with a constructor When you create a bean by the constructor approach, all normal - classes are usable by and compatible with Spring. That is, the class - being developed does not need to implement any specific interfaces or - to be coded in a specific fashion. Simply specifying the bean class - should suffice. However, depending on what type of IoC you use for - that specific bean, you may need a default (empty) constructor. + classes are usable by and compatible with Spring. That is, the class + being developed does not need to implement any specific interfaces or + to be coded in a specific fashion. Simply specifying the bean class + should suffice. However, depending on what type of IoC you use for + that specific bean, you may need a default (empty) constructor. The Spring IoC container can manage virtually - any class you want it to manage; it is not - limited to managing true JavaBeans. Most Spring users prefer actual - JavaBeans with only a default (no-argument) constructor and - appropriate setters and getters modeled after the properties in the - container. You can also have more exotic non-bean-style classes in - your container. If, for example, you need to use a legacy connection - pool that absolutely does not adhere to the JavaBean specification, - Spring can manage it as well. + any class you want it to manage; it is not + limited to managing true JavaBeans. Most Spring users prefer actual + JavaBeans with only a default (no-argument) constructor and + appropriate setters and getters modeled after the properties in the + container. You can also have more exotic non-bean-style classes in + your container. If, for example, you need to use a legacy connection + pool that absolutely does not adhere to the JavaBean specification, + Spring can manage it as well. With XML-based configuration metadata you can specify your bean - class as follows: + class as follows: <bean id="exampleBean" class="examples.ExampleBean"/> <bean name="anotherExample" class="examples.ExampleBeanTwo"/> For details about the mechanism for supplying arguments to the - constructor (if required) and setting object instance properties after - the object is constructed, see Injecting - Dependencies. + constructor (if required) and setting object instance properties after + the object is constructed, see Injecting + Dependencies.
Instantiation with a static factory method - When defining a bean that you create with a static factory - method, you use the class attribute to specify the - class containing the static factory method and an - attribute named factory-method to specify the name - of the factory method itself. You should be able to call this method - (with optional arguments as described later) and return a live object, - which subsequently is treated as if it had been created through a - constructor. One use for such a bean definition is to call - static factories in legacy code. + When defining a bean that you create with a static factory method, + you use the class attribute to specify the class + containing the static factory method and an + attribute named factory-method to specify the name + of the factory method itself. You should be able to call this method + (with optional arguments as described later) and return a live object, + which subsequently is treated as if it had been created through a + constructor. One use for such a bean definition is to call + static factories in legacy code. The following bean definition specifies that the bean will be - created by calling a factory-method. The definition does not specify - the type (class) of the returned object, only the class containing the - factory method. In this example, the - createInstance() method must be a - static method. + created by calling a factory-method. The definition does not specify + the type (class) of the returned object, only the class containing the + factory method. In this example, the + createInstance() method must be a + static method. <bean id="clientService" class="examples.ClientService" factory-method="createInstance"/> - public class ClientService { - private static ClientService clientService = new ClientService(); - private ClientService() {} - - public static ClientService createInstance() { - return clientService; - } + public class ClientService { + private static ClientService clientService = new ClientService(); + private ClientService() {} + + public static ClientService createInstance() { + return clientService; + } } - For details about the mechanism for supplying (optional) - arguments to the factory method and setting object instance properties - after the object is returned from the factory, see Dependencies and - configuration in detail. + For details about the mechanism for supplying (optional) arguments + to the factory method and setting object instance properties after the + object is returned from the factory, see Dependencies and + configuration in detail.
Instantiation using an instance factory method Similar to instantiation through a static factory - method, instantiation with an instance factory method invokes a - non-static method of an existing bean from the container to create a - new bean. To use this mechanism, leave the class - attribute empty, and in the factory-bean - attribute, specify the name of a bean in the current (or - parent/ancestor) container that contains 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. + linkend="beans-factory-class-static-factory-method">static factory + method, instantiation with an instance factory method invokes a + non-static method of an existing bean from the container to create a + new bean. To use this mechanism, leave the class + attribute empty, and in the factory-bean + attribute, specify the name of a bean in the current (or + parent/ancestor) container that contains 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. <!-- the factory bean, which contains a method called createInstance() --> <bean id="serviceLocator" class="examples.DefaultServiceLocator"> @@ -773,3062 +771,96 @@ List userList service.getUsernameList(); factory-bean="serviceLocator" factory-method="createClientServiceInstance"/> - public class DefaultServiceLocator { - private static ClientService clientService = new ClientServiceImpl(); - private DefaultServiceLocator() {} - - public ClientService createClientServiceInstance() { - return clientService; - } + public class DefaultServiceLocator { + 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: + shown here: - + <bean id="serviceLocator" class="examples.DefaultServiceLocator"> <!-- inject any dependencies required by this locator bean --> </bean> <bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/> - + <bean id="accountService" factory-bean="serviceLocator" factory-method="createAccountServiceInstance"/> - public class DefaultServiceLocator { - private static ClientService clientService = new ClientServiceImpl(); - private static AccountService accountService = new AccountServiceImpl(); - - private DefaultServiceLocator() {} - - public ClientService createClientServiceInstance() { - return clientService; - } - - public AccountService createAccountServiceInstance() { - return accountService; - } + public class DefaultServiceLocator { + private static ClientService clientService = new ClientServiceImpl(); + private static AccountService accountService = new AccountServiceImpl(); + + private DefaultServiceLocator() {} + + public ClientService createClientServiceInstance() { + return clientService; + } + + public AccountService createAccountServiceInstance() { + return accountService; + } } This approach shows that the factory bean itself can be managed - and configured through dependency injection (DI). See Dependencies and - configuration in detail. + and configured through dependency injection (DI). See Dependencies and + configuration in detail. In Spring documentation, factory bean - refers to a bean that is configured in the Spring container that - will create objects through an instance - or static - factory method. By contrast, - FactoryBean (notice the - capitalization) refers to a Spring-specific - FactoryBean . + refers to a bean that is configured in the Spring container that + will create objects through an instance or static + factory method. By contrast, + FactoryBean (notice the + capitalization) refers to a Spring-specific + FactoryBean .
-
- Dependencies + - A typical enterprise application does not consist of a single object - (or bean in the Spring parlance). Even the simplest application has a few - objects that work together to present what the end-user sees as a coherent - application. This next section explains how you go from defining a number - of bean definitions that stand alone to a fully realized application where - objects collaborate to achieve a goal. + -
- Dependency injection - - - - Dependency injection (DI) 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 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 or location of its dependencies on its own - by using direct construction of classes, or the Service - Locator pattern. - - Code is cleaner with the DI principle and decoupling is more - effective when objects are provided with their dependencies. The object - does not look up its dependencies, and does not know the location or - class of the dependencies. As such, your classes become easier to test, - in particular when the dependencies are on interfaces or abstract base - classes, which allow for stub or mock implementations to be used in unit - tests. - - DI exists in two major variants, Constructor-based dependency - injection and Setter-based - dependency injection. - -
- Constructor-based dependency injection - - Constructor-based DI is accomplished by the - container invoking a constructor with a number of arguments, each - representing a dependency. Calling a static factory - method with specific arguments to construct the bean is nearly - equivalent, and this discussion treats arguments to a constructor and - to a static factory method similarly. The following - example shows a class that can only be dependency-injected with - constructor 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. - - public class SimpleMovieLister { - - // 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; - } - - // business logic that actually 'uses' the injected MovieFinder is omitted... -} - -
- Constructor argument resolution - - Constructor argument resolution matching occurs using the - argument's type. If no potential ambiguity exists in the constructor - arguments of a bean definition, then the order in which the - constructor arguments are defined in a bean definition is the order - in which those arguments are supplied to the appropriate constructor - when the bean is being instantiated. Consider the following - class: - - package x.y; - -public class Foo { - - public Foo(Bar bar, Baz baz) { - // ... - } -} - - No potential ambiguity exists, assuming that - Bar and Baz classes - are not related by inheritance. Thus the following configuration - works fine, and you do not need to specify the constructor argument - indexes and/or types explicitly in the - <constructor-arg/> element. - - <beans> - <bean id="foo" class="x.y.Foo"> - <constructor-arg ref="bar"/> - <constructor-arg ref="baz"/> - </bean> - - <bean id="bar" class="x.y.Bar"/> - <bean id="baz" class="x.y.Baz"/> - -</beans> - - 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 - <value>true<value>, Spring cannot - determine the type of the value, and so cannot match by type without - help. Consider the following class: - - package examples; - -public class ExampleBean { - - // No. of years to the calculate the Ultimate Answer - private int years; - - // The Answer to Life, the Universe, and Everything - private String ultimateAnswer; - - public ExampleBean(int years, String ultimateAnswer) { - this.years = years; - this.ultimateAnswer = ultimateAnswer; - } -} - -
- Constructor argument type matching - - In the preceding scenario, the container - can use type matching with simple types if - you explicitly specify the type of the constructor argument using - the type attribute. For example: - - <bean id="exampleBean" class="examples.ExampleBean"> - <constructor-arg type="int" value="7500000"/> - <constructor-arg type="java.lang.String" value="42"/> -</bean> -
- -
- Constructor argument index - - Use the index attribute to specify - explicitly the index of constructor arguments. For example: - - <bean id="exampleBean" class="examples.ExampleBean"> - <constructor-arg index="0" value="7500000"/> - <constructor-arg index="1" value="42"/> -</bean> - - In addition to resolving the ambiguity of multiple simple - values, specifying an index resolves ambiguity where a constructor - has two arguments of the same type. Note that the index - is 0 based. -
-
-
- -
- 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. - - The following example shows a class that can only be - dependency-injected using pure setter injection. This class is - conventional Java. It is a POJO that has no dependencies on container - specific interfaces, base classes or annotations. - - public class SimpleMovieLister { - - // 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; - } - - // business logic that actually 'uses' the injected MovieFinder is omitted... -} - - The ApplicationContext supports - constructor- and setter-based DI for the beans it manages. It also - supports setter-based DI after some dependencies are already injected - through the constructor approach. You configure the dependencies in - the form of a BeanDefinition, which you - use with PropertyEditor instances to - convert properties from one format to another. However, most Spring - users do not work with these classes 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 dependencies. Note that the - use of a @Required - annotation on a setter can be used to make setters required - dependencies. - - The Spring team generally advocates setter injection, because - large numbers of constructor arguments can get unwieldy, especially - when properties are optional. Setter methods also make objects of - that class amenable to reconfiguration or re-injection later. - Management through JMX MBeans is a - compelling use case. - - Some purists favor constructor-based injection. Supplying all - object dependencies means that the object is always returned to - client (calling) code in a totally initialized state. The - disadvantage is that the object becomes less amenable to - reconfiguration and re-injection. - - Use the DI that makes the most sense for a particular class. - Sometimes, when dealing with third-party classes to which you do not - have the source, the choice is made for you. A legacy class may not - expose any setter methods, and so constructor injection is the only - available DI. - -
- -
- Dependency resolution process - - The container performs bean dependency resolution as - follows: - - - - - - The ApplicationContext is - created and initialized with configuration metadata that describes - all the beans. Configuration metadata can be specified via XML, - Java code or annotations. - - - - For each bean, its dependencies are expressed in the form of - properties, constructor arguments, or arguments to the - static-factory method if you are using that instead of a normal - constructor. These dependencies are provided to the bean, - when the bean is actually created. - - - - Each property or constructor argument is an actual - definition of the value to set, or a reference to another bean - in the container. - - - - Each property or constructor argument which is a value is - converted from its specified format to the actual type of that - property or constructor argument. By default Spring can convert a - value supplied in string format to all built-in types, such as - int, long, - String, boolean, etc. - - - - The Spring container validates the configuration of each bean as - the container is created, including the validation of whether bean - reference properties refer to valid beans. However, the bean - properties themselves are not set until the bean is actually - created. Beans that are singleton-scoped and set to be - pre-instantiated (the default) are created when the container is - created. Scopes are defined in - Otherwise, the bean is created only when it is requested. 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. - - For example: Class A requires an instance of class B through - constructor injection, and class B requires an instance of class A - through constructor injection. If you configure beans for classes A - and B to be injected into each other, the Spring IoC container - detects this circular reference at runtime, and throws a - BeanCurrentlyInCreationException. - - One possible solution is to edit the source code of some - classes to be configured by setters rather than constructors. - Alternatively, avoid constructor injection and use setter injection - only. In other words, although it is not recommended, you can - configure circular dependencies with setter injection. - - Unlike the typical case (with no circular - dependencies), a circular dependency between bean A and bean B - forces one of the beans to be injected into the other prior to being - fully initialized itself (a classic chicken/egg scenario). - - - You can generally trust Spring to do the right thing. It detects - configuration problems, such as references to non-existent beans and - circular dependencies, at container load-time. Spring sets properties - and resolves dependencies as late as possible, when the bean is - actually created. This means that a Spring container which has loaded - correctly can later generate an exception when you request an object - if there is a problem creating that object or one of its dependencies. - For example, the bean throws an exception as a result of a missing or - invalid property. This potentially delayed visibility of some - configuration issues is why - ApplicationContext implementations by - default pre-instantiate singleton beans. At the cost of some upfront - time and memory to create these beans before they are actually needed, - you discover configuration issues when the - ApplicationContext is created, not - later. You can still override this default behavior so that singleton - beans will lazy-initialize, rather than be pre-instantiated. - - If no circular dependencies exist, when one or more - collaborating beans are being injected into a dependent bean, each - collaborating bean is totally configured prior to - being injected into the dependent bean. This means that if bean A has - a dependency on bean B, the Spring IoC container completely configures - bean B prior to invoking the setter method on bean A. In other words, - the bean is instantiated (if not a pre-instantiated singleton), its - dependencies are set, and the relevant lifecycle methods (such as a - configured - init method or the IntializingBean - callback method) are invoked. -
- -
- Examples of dependency injection - - 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: - - <bean id="exampleBean" class="examples.ExampleBean"> - - <!-- setter injection using the nested <ref/> element --> - <property name="beanOne"><ref bean="anotherExampleBean"/></property> - - <!-- setter injection using the neater 'ref' attribute --> - <property name="beanTwo" ref="yetAnotherBean"/> - <property name="integerProperty" value="1"/> -</bean> - -<bean id="anotherExampleBean" class="examples.AnotherBean"/> -<bean id="yetAnotherBean" class="examples.YetAnotherBean"/> - - public class ExampleBean { - - private AnotherBean beanOne; - private YetAnotherBean beanTwo; - private int i; - - public void setBeanOne(AnotherBean beanOne) { - this.beanOne = beanOne; - } - - public void setBeanTwo(YetAnotherBean beanTwo) { - this.beanTwo = beanTwo; - } - - 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: - - <bean id="exampleBean" class="examples.ExampleBean"> - - <!-- constructor injection using the nested <ref/> element --> - <constructor-arg> - <ref bean="anotherExampleBean"/> - </constructor-arg> - - <!-- constructor injection using the neater 'ref' attribute --> - <constructor-arg ref="yetAnotherBean"/> - - <constructor-arg type="int" value="1"/> -</bean> - -<bean id="anotherExampleBean" class="examples.AnotherBean"/> -<bean id="yetAnotherBean" class="examples.YetAnotherBean"/> - - public class ExampleBean { - - 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; - } -} - - The constructor arguments specified in the bean definition will - be used as arguments to 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: - - <bean id="exampleBean" class="examples.ExampleBean" - factory-method="createInstance"> - <constructor-arg ref="anotherExampleBean"/> - <constructor-arg ref="yetAnotherBean"/> - <constructor-arg value="1"/> -</bean> - -<bean id="anotherExampleBean" class="examples.AnotherBean"/> -<bean id="yetAnotherBean" class="examples.YetAnotherBean"/> - - public class 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) { - - ExampleBean eb = new ExampleBean (...); - // some other operations... - return eb; - } -} - - Arguments to the static factory method are - supplied via <constructor-arg/> elements, - exactly the same as if a constructor had actually been used. The type - of the class being returned by the factory method does not have to be - of the same type as the class that contains the - static factory method, although in this example it - is. An instance (non-static) factory method would be used in an - essentially identical fashion (aside from the use of the - factory-bean attribute instead of the - class attribute), so details will not be discussed - here. -
-
- -
- Dependencies and configuration in detail - - As mentioned in the previous section, you can define bean - properties and constructor arguments as references to other managed - beans (collaborators), or as values defined inline. Spring's XML-based - configuration metadata supports sub-element types within its - <property/> and - <constructor-arg/> elements for this - purpose. - -
- Straight values (primitives, <literal>Strings</literal>, and so - on) - - The value attribute of the - <property/> element specifies a property or - constructor argument as a human-readable string representation. As mentioned - previously, JavaBeans PropertyEditors are - used to convert these string values from a - String to the actual type of the property or - argument. - - <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> - - <!-- results in a setDriverClassName(String) call --> - <property name="driverClassName" value="com.mysql.jdbc.Driver"/> - <property name="url" value="jdbc:mysql://localhost:3306/mydb"/> - <property name="username" value="root"/> - <property name="password" value="masterkaoli"/> -</bean> - - The following example uses the p-namespace for even more succinct - XML configuration. - - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:p="http://www.springframework.org/schema/p" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> - - <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" - destroy-method="close" - p:driverClassName="com.mysql.jdbc.Driver" - p:url="jdbc:mysql://localhost:3306/mydb" - p:username="root" - p:password="masterkaoli"/> - -</beans> - - - - The preceding XML is more succinct; however, typos are - discovered at runtime rather than design time, unless you use an IDE - such as IntelliJ - IDEA or the SpringSource Tool - Suite (STS) that support automatic property completion when - you create bean definitions. Such IDE assistance is highly - recommended. - - You can also configure a - java.util.Properties instance as: - - <bean id="mappings" - class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> - - <!-- typed as a java.util.Properties --> - <property name="properties"> - <value> - jdbc.driver.className=com.mysql.jdbc.Driver - jdbc.url=jdbc:mysql://localhost:3306/mydb - </value> - </property> -</bean> - - The Spring container converts the text inside the - <value/> element into a - java.util.Properties instance by using the - JavaBeans PropertyEditor mechanism. - This is a nice shortcut, and is one of a few places where the Spring - team do favor the use of the nested <value/> - element over the value attribute style. - -
- The <literal>idref</literal> element - - The idref element is simply an error-proof - way to pass the id (string value - not a - reference) of another bean in the container to a - <constructor-arg/> or - <property/> element. - - <bean id="theTargetBean" class="..."/> - -<bean id="theClientBean" class="..."> - <property name="targetName"> - <idref bean="theTargetBean" /> - </property> -</bean> - - The above bean definition snippet is - exactly equivalent (at runtime) to the - following snippet: - - <bean id="theTargetBean" class="..." /> - -<bean id="client" class="..."> - <property name="targetName" value="theTargetBean" /> -</bean> - - The first form is preferable to the second, because using the - idref tag allows the container to validate - at deployment time that the referenced, named - bean actually exists. In the second variation, no validation is - performed on the value that is passed to the - targetName property of the - client bean. Typos are only discovered (with most - likely fatal results) when the client bean is - actually instantiated. If the client bean is a - prototype bean, this - typo and the resulting exception may only be discovered long after - the container is deployed. - - Additionally, if the referenced bean is in the same XML unit, - and the bean name is the 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. - - <property name="targetName"> - <!-- a bean with id 'theTargetBean' must exist; otherwise an exception will be thrown --> - <idref local="theTargetBean"/> -</property> - - A common place (at least in versions earlier than Spring 2.0) - where the <idref/> element brings value is in the - configuration of AOP interceptors - in a ProxyFactoryBean bean definition. Using - <idref/> elements when you specify the interceptor names - prevents you from misspelling an interceptor id. -
-
- -
- References to other beans (collaborators) - - The ref element is the final element inside a - <constructor-arg/> or - <property/> definition element. Here you set - the value of the specified property of a bean to be a reference to - another bean (a collaborator) managed by the container. The referenced - bean is a dependency of the bean whose property will be set, and it is - initialized on demand as needed before the property is set. (If the - collaborator is a singleton bean, it may be initialized already by the - container.) All references are ultimately a reference to another - object. Scoping and validation depend on whether you specify the - id/name of the other object through the - bean,local, or - parent attributes. - - Specifying the target bean through the bean - attribute of the <ref/> tag is the most - general form, and allows creation of a reference to any bean in the - same container or parent container, regardless of whether it is in the - same XML file. The value of the 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. - - <ref bean="someBean"/> - - Specifying the target bean through the local - attribute leverages the ability of the XML parser to validate XML id - references within the same file. The value of the - local attribute must be the same as the - id attribute of the target bean. The XML parser - issues an error if no matching element is found in the same file. As - such, using the 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. - - <ref local="someBean"/> - - Specifying the target bean through the parent - attribute creates a reference to a bean that is in a parent container - of the current container. The value of the parent - attribute may be the same as either the id - attribute of the target bean, or one of the values in the - name attribute of the target bean, and the target - bean must be in a parent container of the current one. You use this - bean reference variant mainly when you 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. - - <!-- in the parent context --> -<bean id="accountService" class="com.foo.SimpleAccountService"> - <!-- insert dependencies as required as here --> -</bean> - - <!-- in the child (descendant) context --> -<bean id="accountService" <-- bean name is the same as the parent bean --> - class="org.springframework.aop.framework.ProxyFactoryBean"> - <property name="target"> - <ref parent="accountService"/> <!-- notice how we refer to the parent bean --> - </property> - <!-- insert other configuration and dependencies as required here --> -</bean> -
- -
- Inner beans - - A <bean/> element inside the - <property/> or - <constructor-arg/> elements defines a - so-called inner bean. - - <bean id="outer" class="..."> - <!-- instead of using a reference to a target bean, simply define the target bean inline --> - <property name="target"> - <bean class="com.example.Person"> <!-- this is the inner bean --> - <property name="name" value="Fiona Apple"/> - <property name="age" value="25"/> - </bean> - </property> -</bean> - - An inner bean definition does not require a defined id or name; - the container ignores these values. It also ignores the - scope flag. Inner beans are - always anonymous and they are - always scoped as prototypes. It is - not possible to inject inner beans into - collaborating beans other than into the enclosing bean. -
- -
- Collections - - In the <list/>, - <set/>, <map/>, and - <props/> elements, you set the properties and - arguments of the Java Collection types - List, - Set, - Map, and - Properties, respectively. - - <bean id="moreComplexObject" class="example.ComplexObject"> - <!-- results in a setAdminEmails(java.util.Properties) call --> - <property name="adminEmails"> - <props> - <prop key="administrator">administrator@example.org</prop> - <prop key="support">support@example.org</prop> - <prop key="development">development@example.org</prop> - </props> - </property> - <!-- results in a setSomeList(java.util.List) call --> - <property name="someList"> - <list> - <value>a list element followed by a reference</value> - <ref bean="myDataSource" /> - </list> - </property> - <!-- results in a setSomeMap(java.util.Map) call --> - <property name="someMap"> - <map> - <entry key="an entry" value="just some string"/> - <entry key ="a ref" value-ref="myDataSource"/> - </map> - </property> - <!-- results in a setSomeSet(java.util.Set) call --> - <property name="someSet"> - <set> - <value>just some string</value> - <ref bean="myDataSource" /> - </set> - </property> -</bean> - - The value of a map key or value, or a set value, can - also again be any of the following elements: - - bean | ref | idref | list | set | map | props | value | null - -
- Collection merging - - As of Spring 2.0, the container supports the - merging of collections. An application - developer can define a parent-style - <list/>, <map/>, - <set/> or <props/> - element, and have child-style <list/>, - <map/>, <set/> or - <props/> elements inherit and override - values from the parent collection. That is, the child collection's - values are the result of merging the elements of the parent and - child collections, with the child's collection elements overriding - values specified in the parent collection. - - This section on merging discusses the parent-child - bean mechanism. Readers unfamiliar with parent and child bean - definitions may wish to read the relevant section - before continuing. - - The following example demonstrates collection merging: - - <beans> -<bean id="parent" abstract="true" class="example.ComplexObject"> - <property name="adminEmails"> - <props> - <prop key="administrator">administrator@example.com</prop> - <prop key="support">support@example.com</prop> - </props> - </property> -</bean> -<bean id="child" parent="parent"> - <property name="adminEmails"> - <!-- the merge is specified on the *child* collection definition --> - <props merge="true"> - <prop key="sales">sales@example.com</prop> - <prop key="support">support@example.co.uk</prop> - </props> - </property> -</bean> -<beans> - - Notice the use of the merge=true attribute - on the <props/> element of the - adminEmails property of the - child bean definition. When the - child bean is resolved 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. - - administrator=administrator@example.com -sales=sales@example.com -support=support@example.co.uk - - The child Properties collection's value - set inherits all property elements from the parent - <props/>, and the child's value for the - support value overrides the value in the parent - collection. - - This merging behavior applies similarly to the - <list/>, <map/>, - and <set/> collection types. In the - specific case of the <list/> element, the - semantics associated with the List collection - type, that is, the notion of an ordered - collection of values, is maintained; the parent's values precede all - of the child list's values. In the case of the - Map, - Set, and - Properties collection types, no - ordering exists. Hence no ordering semantics are in effect for the - collection types that underlie the associated - Map, - Set, and - Properties implementation types that - the container uses internally. -
- -
- Limitations of collection merging - - You cannot merge different collection types (such as a - Map and a - List), and if you 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. -
- -
- 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. - - public class Foo { - - private Map<String, Float> accounts; - - public void setAccounts(Map<String, Float> accounts) { - this.accounts = accounts; - } -} - - <beans> - <bean id="foo" class="x.y.Foo"> - <property name="accounts"> - <map> - <entry key="one" value="9.99"/> - <entry key="two" value="2.75"/> - <entry key="six" value="3.99"/> - </map> - </property> - </bean> -</beans> - - When the accounts property of the - foo bean is prepared for injection, the generics - information about the element type of the strongly-typed - Map<String, Float> is available by - reflection. Thus Spring's type conversion infrastructure recognizes - the various value elements as being of type - Float, and the string values 9.99, - 2.75, and 3.99 are converted into an - actual Float type. -
-
- -
- Null and empty string values - - Spring - treats empty arguments for properties and the like as empty - Strings. The following XML-based configuration - metadata snippet sets the email property to the empty - String value ("") - - <bean class="ExampleBean"> - <property name="email" value=""/> -</bean> - - The preceding example is equivalent to the following Java code: - exampleBean.setEmail(""). The - <null/> element handles - null values. For example: - - <bean class="ExampleBean"> - <property name="email"><null/></property> -</bean> - - The above configuration is equivalent to the following Java - code: exampleBean.setEmail(null). -
- -
- XML shortcut with the p-namespace - - The p-namespace enables you to use the bean - element's attributes, instead of nested - <property/> elements, to describe your - property values and/or collaborating beans. - - Spring 2.0 and later supports extensible configuration formats - with namespaces, 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. - - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:p="http://www.springframework.org/schema/p" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> - - <bean name="classic" class="com.example.ExampleBean"> - <property name="email" value="foo@bar.com"/> - </bean> - - <bean name="p-namespace" class="com.example.ExampleBean" - p:email="foo@bar.com"/> -</beans> - - The example shows an attribute in the p-namespace called email - in the bean definition. This tells Spring to include a property - declaration. As previously mentioned, the p-namespace does not have - a schema definition, so you can set the name of the attribute to the - property name. - - This next example includes two more bean definitions that both - have a reference to another bean: - - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:p="http://www.springframework.org/schema/p" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> - - <bean name="john-classic" class="com.example.Person"> - <property name="name" value="John Doe"/> - <property name="spouse" ref="jane"/> - </bean> - - <bean name="john-modern" - class="com.example.Person" - p:name="John Doe" - p:spouse-ref="jane"/> - - <bean name="jane" class="com.example.Person"> - <property name="name" value="Jane Doe"/> - </bean> -</beans> - - As you can see, this example includes not only a property value - using the p-namespace, but also uses a special format to declare - property references. Whereas the first bean definition uses - <property name="spouse" ref="jane"/> to - create a reference from bean john to bean - jane, the second bean definition uses - p:spouse-ref="jane" as an attribute to do the exact - same thing. In this case spouse is the property - name, whereas the -ref part indicates that this is - not a straight value but rather a reference to another bean. - - - The p-namespace is not as flexible as the standard XML format. - For example, the format for declaring property references clashes - with properties that end in Ref, whereas the - standard XML format does not. We recommend that you choose your - approach carefully and communicate this to your team members, to - avoid producing XML documents that use all three approaches at the - same time. - -
- -
- Compound property names - - You can use compound or nested property names when you set bean - properties, as long as all components of the path except the final - property name are not null. Consider the following - bean definition. - - <bean id="foo" class="foo.Bar"> - <property name="fred.bob.sammy" value="123" /> -</bean> - - The foo bean has a fred - property, which has a bob property, which has a - sammy property, and that final - sammy property is being set to the value - 123. In order for this to work, the - fred property of foo, and the - bob property of fred must not be - null after the bean is constructed, or a - NullPointerException is thrown. -
-
- -
- Using <literal>depends-on</literal> - - 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 <ref/> - 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 explicitly - force one or more beans to be initialized before the bean using this - element is initialized. The following example uses the - depends-on attribute to express a dependency on a - single bean: - - <bean id="beanOne" class="ExampleBean" depends-on="manager"/> - -<bean id="manager" class="ManagerBean" /> - - 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: - - <bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"> - <property name="manager" ref="manager" /> -</bean> - -<bean id="manager" class="ManagerBean" /> -<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" /> - - - The depends-on attribute in the bean - definition can specify both an initialization time dependency and, in - the case of singleton 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. - -
- -
- Lazy-initialized beans<!--Changed to lazy-initialized from lazily instantiated because attribute is lazy-init, and there was a lot of inconsistency. --> - - By default, ApplicationContext - implementations eagerly create and configure all singleton beans as part - of the initialization process. Generally, this pre-instantiation is - desirable, because errors in the configuration or surrounding - environment are discovered immediately, as opposed to hours or even days - later. When this behavior is not desirable, you can - prevent pre-instantiation of a singleton bean by marking the bean - definition as lazy-initialized. A lazy-initialized bean tells the IoC - container to create a bean instance when it is first requested, rather - than at startup. - - In XML, this behavior is controlled by the - lazy-init attribute on the - <bean/> element; for example: - - <bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/> - -<bean name="not.lazy" class="com.foo.AnotherBean"/> - - When the preceding configuration is consumed by an - ApplicationContext, the bean named - lazy is not eagerly pre-instantiated when the - ApplicationContext is starting up, - whereas the not.lazy bean is eagerly - pre-instantiated. - - However, when a lazy-initialized bean is a dependency of a - singleton bean that is not lazy-initialized, the - ApplicationContext creates the - lazy-initialized bean at startup, because it must satisfy the - singleton's dependencies. The lazy-initialized bean 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 - <beans/> element; for example: - - <beans default-lazy-init="true"> - <!-- no beans will be pre-instantiated... --> -</beans> -
- -
- Autowiring collaborators - - - - The Spring container can autowire - relationships between collaborating beans. You can allow Spring to - resolve collaborators (other beans) automatically for your bean by - inspecting the contents of the - ApplicationContext. Autowiring has the - following advantages: - - - - Autowiring can significantly reduce the need to specify - properties or constructor arguments. (Other mechanisms such as a - bean template discussed elsewhere in this - chapter are also valuable in this regard.) - - - - Autowiring can update a configuration as your objects - evolve. For example, if you need to add a dependency to a class, - that dependency can be satisfied automatically without you needing to - modify the configuration. Thus autowiring can be especially useful - during development, without negating the option of switching to - explicit wiring when the code base becomes more stable. - - - When using XML-based configuration metadataSee - , you - specify autowire mode for a bean definition with the - autowire attribute of the - <bean/> element. The autowiring functionality has - five modes. You specify autowiring per bean and thus - can choose which ones to autowire. - - - Autowiring modes - - - - - - - - - Mode - - Explanation - - - - - - no - - (Default) No autowiring. Bean references must be - defined via a ref element. Changing the - default setting is not recommended for larger deployments, - because specifying collaborators explicitly gives greater - control and clarity. To some extent, it documents the structure - of a system. - - - - byName - - Autowiring by property name. Spring looks for a - bean with the same name as the property that needs to be - autowired. For example, if a bean definition is set to autowire - by name, and it contains a master property - (that is, it has a setMaster(..) method), - Spring looks for a bean definition named - master, and uses it to set the - property. - - - - byType - - Allows a property to be autowired if exactly one - bean of the property type exists in the container. If more than - one exists, a fatal exception is thrown, which indicates that - you may not use byType autowiring for that - bean. If there are no matching beans, nothing happens; the - property is not set. - - - - constructor - - Analogous to byType, but - applies to constructor arguments. If there is not exactly one - bean of the constructor argument type in the container, a fatal - error is raised. - - - - -
- - With byType or - constructor autowiring mode, you can wire arrays - and typed-collections. In such cases all autowire - candidates within the container that match the expected type are - provided to satisfy the dependency. You can autowire strongly-typed Maps - if the expected key type is String. An autowired - Maps values will consist of all bean instances that match the expected - type, and the Maps keys will contain the corresponding bean - names. - - You can combine autowire behavior with dependency checking, which - is performed after autowiring completes. - -
- Limitations and disadvantages of autowiring - - Autowiring works best when it is used consistently across a - project. If autowiring is not used in general, it might be confusing - to developers to use it to wire only one or 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, - 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, Spring is careful to avoid guessing in - case of ambiguity that might have unexpected results, the - relationships between your Spring-managed objects are no longer - documented explicitly. - - - - Wiring information may not be available to tools that may - generate documentation from a Spring container. - - - - - - Multiple bean definitions within the container may match the - type specified by the setter method or constructor argument to be - autowired. For arrays, collections, or Maps, this is not - necessarily a problem. However for dependencies that expect a - single value, this ambiguity is not arbitrarily resolved. If no - unique bean definition is available, an exception is - thrown. - - - - In the latter scenario, you have several options: - - - - Abandon autowiring in favor of explicit wiring. - - - - Avoid autowiring for a bean definition by setting its - autowire-candidate attributes to - false as described in the next section. - - - - Designate a single bean definition as the - primary candidate by setting the - primary attribute of its - <bean/> element to - true. - - - - If you are using Java 5 or later, implement the more - fine-grained control available with annotation-based - configuration, as described in . - - -
- -
- Excluding a bean from autowiring - - On a per-bean basis, you can exclude a bean from autowiring. In - Spring's XML format, set the autowire-candidate - attribute of the <bean/> element to - false; the container makes that specific bean - definition unavailable to the autowiring infrastructure (including - annotation style configurations such as @Autowired). - - You can also limit autowire candidates based on pattern-matching - against bean names. The top-level <beans/> - 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 - 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. - - These techniques are useful for beans that you never want to be - injected into other beans by autowiring. It does not mean that an - excluded bean cannot itself be configured using autowiring. Rather, - the bean itself is not a candidate for autowiring other beans. - - -
-
- -
- Method injection - - In most application scenarios, most beans in the container are - singletons. When a - singleton bean needs to collaborate with another singleton bean, or a - non-singleton bean needs to collaborate with another non-singleton bean, - you typically handle the dependency by defining one bean as a property - of the other. A problem arises when the bean lifecycles are different. - Suppose singleton bean A needs to use non-singleton (prototype) bean B, - perhaps on each method invocation on A. The container only creates the - singleton bean A once, and thus only gets one opportunity to set the - properties. The container cannot provide bean A with a new instance of - bean B every time one is needed. - - A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the - ApplicationContextAware interface, and by - making a getBean("B") call to the - container ask for (a typically new) bean B instance every time - bean A needs it. The following is an example of this approach: - - // 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; - -public class CommandManager implements ApplicationContextAware { - - 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(); - } - - 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; - } -} - - The preceding is not desirable, because the business code is aware - of and coupled to the Spring Framework. Method Injection, a somewhat - advanced feature of the Spring IoC container, allows this use case to be - handled in a clean fashion. - - - You can read more about the motivation for Method Injection in - this - blog entry. - - -
- Lookup method injection - - - - Lookup method injection is the ability of the container to - override methods on container managed beans, to - return the lookup result for another named bean in the container. The - lookup typically involves a prototype bean as in the scenario - described in the preceding section. The Spring Framework implements - this method injection by using bytecode generation from the CGLIB - library to generate dynamically a subclass that overrides the - method. - - - For this dynamic subclassing to work, you must have the CGLIB - jar(s) in your classpath. The class that the Spring container will - subclass cannot be final, and the method to be - overridden cannot be final either. Also, testing - a class that has an abstract method requires you - to subclass the class yourself and to supply a stub implementation - of the abstract method. Finally, objects that - have been the target of method injection cannot be - serialized. - - - Looking at the CommandManager class in - the previous code snippet, you see that the Spring container will - dynamically override the implementation of the - createCommand() method. Your - CommandManager class will not have any Spring - dependencies, as can be seen in the reworked example: - - package fiona.apple; - -// no more Spring imports! - -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(); - } - - // 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: - - <public|protected> [abstract] <return-type> 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: - - <!-- a stateful bean deployed as a prototype (non-singleton) --> -<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype"> - <!-- inject dependencies here as required --> -</bean> - -<!-- commandProcessor uses statefulCommandHelper --> -<bean id="commandManager" class="fiona.apple.CommandManager"> - <lookup-method name="createCommand" bean="command"/> -</bean> - - The bean identified as commandManager calls - its own method createCommand() whenever it - needs a new instance of the command bean. You - must be careful to deploy the command bean as a - prototype, if that is actually what is needed. If it is deployed as a - singleton, the - same instance of the command bean is returned each - time. - - - 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, - ObjectFactoryCreatingFactoryBean, but it - allows you to specify your own lookup interface as opposed to a - Spring-specific lookup interface. Consult the JavaDocs for these - classes as well as this blog - entry for additional information - ServiceLocatorFactoryBean. - -
- -
- Arbitrary method replacement - - A less useful form of method injection than lookup method - Injection is the ability to replace arbitrary methods in a managed - bean with another method implementation. Users may safely skip the - rest of this section until the functionality is actually needed. - - With XML-based configuration metadata, you can use the - replaced-method element to replace an existing - method implementation with another, for a deployed bean. Consider the - following class, with a method computeValue, which we want to - override: - - public class MyValueCalculator { - - public String computeValue(String input) { - // some real code... - } - - // some other methods... - -} - - A class implementing the - org.springframework.beans.factory.support.MethodReplacer - interface provides the new method definition. - - /** 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 ...; - } -} - - The bean definition to deploy the original class and specify the - method override would look like this: - - <bean id="myValueCalculator" class="x.y.z.MyValueCalculator"> - - <!-- arbitrary method replacement --> - <replaced-method name="computeValue" replacer="replacementComputeValue"> - <arg-type>String</arg-type> - </replaced-method> -</bean> - -<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/> - - You can use one or more contained - <arg-type/> elements within the - <replaced-method/> element to indicate the - method signature of the method being overridden. The signature for the - arguments is necessary only if the method is overloaded and multiple - variants exist within the class. For convenience, the type string for - an argument may be a substring of the fully qualified type name. For - example, the following all match - java.lang.String: - - java.lang.String - String - Str - - Because the number of arguments is often enough to distinguish - between each possible choice, this shortcut can save a lot of typing, - by allowing you to type only the shortest string that will match an - argument type. -
-
-
- -
- Bean scopes - - When you create a bean definition, you create a - recipe for creating actual instances of the class - defined by that bean definition. The idea that a bean definition is a - recipe is important, because it means that, as with a class, you can - create many object instances from a single recipe. - - You can control not only the various dependencies and configuration - values that are to be plugged into an object that is created from a - particular bean definition, but also the scope of - the objects created from a particular bean definition. This approach is - powerful and flexible in that you can choose the - scope of the objects you create through configuration instead of having to - bake in the scope of an object at the Java class level. Beans can be - defined to be deployed in one of a number of scopes: out of the box, the - Spring Framework supports five scopes, three of which are available only - if you use a web-aware - ApplicationContext. - - The following scopes are supported out of the box. You can also - create a custom - scope. - - - Bean scopes - - - - - Scope - - Description - - - - - - singleton - - - (Default) Scopes a single bean definition to a single object - instance per Spring IoC container. - - - - prototype - - - Scopes a single bean definition to any number of - object instances. - - - - request - - - 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. - - - - session - - - Scopes a single bean definition to the lifecycle of - an HTTP Session. Only valid in the - context of a web-aware Spring - ApplicationContext. - - - - global - session - - 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. - - - -
- - - Thread-scoped beans - - As of Spring 3.0, a thread scope is - available, but is not registered by default. For more information, see - the documentation for SimpleThreadScope. - For instructions on how to register this or any other custom scope, see - . - - -
- The singleton scope - - Only one shared instance of a singleton bean - is managed, and all requests for beans with an id or ids matching that - bean definition result in that one specific bean 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 return the cached - object. - - - - - - - - - - - - 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 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: - - <bean id="accountService" class="com.foo.DefaultAccountService"/> - -<!-- the following is equivalent, though redundant (singleton scope is the default) --> -<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/> -
- -
- The prototype scope - - The non-singleton, prototype scope of bean deployment results in - the creation of a new bean instance every time a - request for that specific bean is made. That is, the bean is injected - into another bean or you request it through a - getBean() method call on the container. As a rule, - use the prototype scope for all stateful beans and the singleton scope - for stateless beans. - - The following diagram illustrates the Spring prototype scope. - A data access object (DAO) is not typically configured as a - prototype, because a typical DAO does not hold any conversational state; - it was just easier for this author to reuse the core of the singleton - diagram. - - - - - - - - - - - - The following example defines a bean as a prototype in XML: - - <!-- using spring-beans-2.0.dtd --> -<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/> - - 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 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 custom - bean post-processor, - which holds a reference to beans that need to be cleaned up. - - In some respects, the Spring container's role in regard to a - prototype-scoped bean is a replacement for the Java - new operator. All lifecycle management past that - point must be handled by the client. (For details on the lifecycle of a - bean in the Spring container, see .) -
- -
- Singleton beans with prototype-bean dependencies - - When you use singleton-scoped beans with dependencies on prototype - beans, be aware that dependencies are resolved at - instantiation time. Thus if you dependency-inject a - prototype-scoped bean into a singleton-scoped bean, a new prototype bean - is instantiated and then dependency-injected into the singleton bean. - The prototype instance is the sole instance that is ever supplied to the - singleton-scoped bean. - - However, suppose you want the singleton-scoped bean to acquire a - new instance of the prototype-scoped bean repeatedly at runtime. You - cannot dependency-inject a prototype-scoped bean into your singleton - bean, because that injection occurs only once, when - the Spring container is instantiating the singleton bean and resolving - and injecting its dependencies. If you need a new instance of a - prototype bean at runtime more than once, see -
- -
- Request, session, and global session scopes - - The request, session, and - global session scopes are only - available if you use a web-aware Spring - ApplicationContext implementation (such - as XmlWebApplicationContext). If you use these - scopes with regular Spring IoC containers such as the - ClassPathXmlApplicationContext, you get an - IllegalStateException complaining about an - unknown bean scope. - -
- Initial web configuration - - To support the scoping of beans at the - request, session, and - global session levels (web-scoped beans), some - minor initial configuration is required before you define your beans. - (This initial setup is not required for the - standard scopes, singleton and prototype.) - - How you accomplish this initial setup depends on your particular - Servlet environment.. - - If you access scoped beans within Spring Web MVC, in effect, - within a request that is processed by the Spring - DispatcherServlet, or - DispatcherPortlet, then no special setup is - necessary: DispatcherServlet and - DispatcherPortlet already expose all 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: - - <web-app> - ... - <listener> - <listener-class> - org.springframework.web.context.request.RequestContextListener - </listener-class> - </listener> - ... -</web-app> - - If you use an older web container (Servlet 2.3), use the - provided javax.servlet.Filter - implementation. The following snippet of XML configuration must be - included in the web.xml file of your web - application if you want to access web-scoped beans in requests outside - of Spring's DispatcherServlet on a Servlet 2.3 container. (The filter - mapping depends on the surrounding web application configuration, so - you must change it as appropriate.) - - <web-app> - .. - <filter> - <filter-name>requestContextFilter</filter-name> - <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>requestContextFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - ... -</web-app> - - DispatcherServlet, - RequestContextListener and - RequestContextFilter all do exactly the same - thing, namely bind the HTTP request object to the - Thread that is servicing that request. This - makes beans that are request- and session-scoped available further - down the call chain. -
- -
- Request scope - - Consider the following bean definition: - - <bean id="loginAction" class="com.foo.LoginAction" scope="request"/> - - The Spring container creates a new instance of the - LoginAction bean by using the - loginAction bean definition for each and every HTTP - request. That is, the loginAction bean is scoped at - the HTTP request level. You can change the internal state of the - instance that is created as much as you want, because other instances - created from the same loginAction bean definition - will not see these changes in state; they are particular to an - individual request. When the request completes processing, the bean - that is scoped to the request is discarded. -
- -
- Session scope - - Consider the following bean definition: - - <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> - - The Spring container creates a new instance of the - UserPreferences bean by using the - userPreferences bean definition for the lifetime of - a single HTTP Session. In other words, - the userPreferences bean is effectively scoped at - the HTTP Session level. As with - request-scoped beans, you can change the internal - state of the instance that is created as much as you want, knowing - that other HTTP Session instances that - are also using instances created from the same - userPreferences bean definition do not see these - changes in state, because they are particular to an individual HTTP - Session. When the HTTP - Session is eventually discarded, the - bean that is scoped to that particular HTTP - Session is also discarded. -
- -
- Global session scope - - Consider the following bean definition: - - <bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/> - - The global session scope is similar to the - standard HTTP Session scope (described above), and - applies only in the context of portlet-based web applications. The - portlet specification defines the notion of a global - Session that is shared among all - portlets that make up a single portlet web application. Beans defined - at the global session scope are scoped (or bound) - to the lifetime of the global portlet - Session. - - If you write a standard Servlet-based web application and you - define one or more beans as having global session - scope, the standard HTTP Session scope - is used, and no error is raised. -
- -
- Scoped beans as dependencies - - The Spring IoC container manages not only the instantiation of - your objects (beans), but also the wiring up of collaborators (or - dependencies). If you want to inject (for example) an HTTP request - scoped bean into another bean, you must inject an AOP proxy in place - of the scoped bean. That is, you need to inject a proxy object that - exposes the same public interface as the scoped object but that can - also retrieve the real, target object from the relevant scope (for - example, an HTTP request) and delegate method calls onto the real - object. - - - You do not need to use the - <aop:scoped-proxy/> in conjunction with - beans that are scoped as singletons or - prototypes. If you try to create a scoped proxy - for a singleton bean, the - BeanCreationException is - raised. - - - 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. - - - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - - <!-- an HTTP Session-scoped bean exposed as a proxy --> - <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> - - <!-- this next element effects the proxying of the surrounding bean --> - <aop:scoped-proxy/> - </bean> - - <!-- a singleton-scoped bean injected with a proxy to the above bean --> - <bean id="userService" class="com.foo.SimpleUserService"> - - <!-- a reference to the proxied userPreferences bean --> - <property name="userPreferences" ref="userPreferences"/> - - </bean> -</beans> - - - To create such a proxy, you insert a child - <aop:scoped-proxy/> element into a scoped - bean definition. (If - you choose class-based proxying, you also need the CGLIB library in - your classpath. See and .) Why do definitions of beans scoped at the - request, session, - globalSession and custom-scope levels require the - <aop:scoped-proxy/> 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.) - - <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> - -<bean id="userManager" class="com.foo.UserManager"> - <property name="userPreferences" ref="userPreferences"/> -</bean> - - In the preceding example, the singleton bean - userManager is injected with a reference to the - HTTP Session-scoped bean - userPreferences. The salient point here is that the - userManager bean is a singleton: it will be - instantiated exactly once per container, and its - dependencies (in this case only one, the - userPreferences bean) are also injected only once. - This means that the userManager bean will only - operate on the exact same userPreferences object, - that is, the one that it was originally injected with. - - - - This is not the behavior you want when - injecting a shorter-lived scoped bean into a longer-lived scoped bean, - for example injecting an HTTP - Session-scoped collaborating bean as a - dependency into singleton bean. Rather, you need a single - userManager object, and for the lifetime of an HTTP - Session, you need a - userPreferences object that is specific to said - HTTP Session. Thus the container - creates an object that exposes the exact same public interface as the - UserPreferences class (ideally an object that - is a UserPreferences - instance) which can fetch the real - UserPreferences object from the scoping - mechanism (HTTP request, Session, - etc.). The container injects this proxy object into the - userManager bean, which is unaware that this - UserPreferences reference is a proxy. In this - example, when a UserManager instance - invokes a method on the dependency-injected - UserPreferences object, it actually is invoking - a method on the proxy. The proxy then fetches the real - UserPreferences object from (in this case) the - HTTP Session, and delegates the 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: - - <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> - <aop:scoped-proxy/> -</bean> - -<bean id="userManager" class="com.foo.UserManager"> - <property name="userPreferences" ref="userPreferences"/> -</bean> - -
- Choosing the type of proxy to create - - By default, when the Spring container creates a proxy for a - bean that is marked up with the - <aop:scoped-proxy/> element, a - CGLIB-based class proxy is created. This means that you - need to have the CGLIB library in the classpath of your - application. - - 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 the - proxy-target-class attribute of the - <aop:scoped-proxy/> element. Using JDK - interface-based proxies means that you do not need additional - libraries in your application classpath to effect such proxying. - However, it also means that the class of the scoped bean must - implement at least one interface, and that all - collaborators into which the scoped bean is injected must reference - the bean through one of its interfaces. - - <!-- DefaultUserPreferences implements the UserPreferences interface --> -<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"> - <aop:scoped-proxy proxy-target-class="false"/> -</bean> - -<bean id="userManager" class="com.foo.UserManager"> - <property name="userPreferences" ref="userPreferences"/> -</bean> - - For more detailed information about choosing class-based or - interface-based proxying, see . -
-
-
- -
- Custom scopes - - As of Spring 2.0, 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. - -
- Creating a custom scope - - To integrate your custom scope(s) into the Spring container, you - need to implement the - 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 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 the scope, and allow them to - be destroyed. - - The following method returns the object from the underlying - scope. The session scope implementation, for example, returns the - session-scoped bean (and if it does not exist, the method returns a - new instance of the bean, after having bound it to the session for - future reference). - - Object get(String name, ObjectFactory objectFactory) - - The following method removes the object from the underlying - scope. The session scope implementation for example, removes the - session-scoped bean from the underlying session. The object should be - returned, but you can return null if the object with the specified - name is not found. - - 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. - - 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. - - String getConversationId() -
- -
- Using a custom scope - - After you write and test one or more custom - Scope implementations, you need to make - 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: - - void registerScope(String scopeName, Scope scope); - - This method is declared on the - ConfigurableBeanFactory interface, - which is available on most of the concrete - ApplicationContext implementations that - ship with Spring via the BeanFactory property. - - The first argument to the - registerScope(..) method is the unique name - associated with a scope; examples of such names in the Spring - container itself are singleton and - prototype. The second argument to the - registerScope(..) method is an actual - instance of the custom Scope - implementation that you wish to register and use. - - Suppose that you write your custom - Scope implementation, and then register - it as below. - - - The example below uses SimpleThreadScope - which is included with Spring, but not registered by default. The - instructions would be the same for your own custom - Scope implementations. - - - -Scope threadScope = new SimpleThreadScope(); -beanFactory.registerScope("thread", threadScope); - - You then create bean definitions that adhere to the scoping - rules of your custom Scope: - - <bean id="..." class="..." scope="thread"> - - 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: - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - - <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> - <property name="scopes"> - <map> - <entry key="thread"> - <bean class="org.springframework.context.support.SimpleThreadScope"/> - </entry> - </map> - </property> - </bean> - - <bean id="bar" class="x.y.Bar" scope="thread"> - <property name="name" value="Rick"/> - <aop:scoped-proxy/> - </bean> - - <bean id="foo" class="x.y.Foo"> - <property name="bar" ref="bar"/> - </bean> - -</beans> - - - When you place <aop:scoped-proxy/> in a - FactoryBean implementation, it is the - factory bean itself that is scoped, not the object returned from - getObject(). - -
-
-
- -
- Customizing the nature of a bean - -
- Lifecycle callbacks - - - - To interact with the container's management of the bean lifecycle, - you can implement the Spring - InitializingBean and - DisposableBean interfaces. The container - calls afterPropertiesSet() for the former and - destroy() for the latter to allow the bean to - perform certain actions upon initialization and destruction of your - beans. You can also achieve the same integration with the container - without coupling your classes to Spring interfaces through the use of - init-method and destroy method object definition metadata. - - Internally, the Spring Framework uses - BeanPostProcessor implementations to - process any callback interfaces it can find and call the appropriate - methods. If you need custom features or other lifecycle behavior Spring - does not offer out-of-the-box, you can implement a - BeanPostProcessor yourself. For more - information, see . - - In addition to the initialization and destruction callbacks, - Spring-managed objects may also implement the - Lifecycle interface so that those objects - can participate in the startup and shutdown process as driven by the - container's own lifecycle. - - The lifecycle callback interfaces are described in this - section. - -
- Initialization callbacks - - The - org.springframework.beans.factory.InitializingBean - interface allows a bean to perform initialization work after all - necessary properties on the bean have been set by the container. The - InitializingBean interface specifies a - single method: - - void afterPropertiesSet() throws Exception; - - It is recommended that you do not use the - InitializingBean interface because it - unnecessarily couples the code to Spring. Alternatively, 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: - - <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> - - public class ExampleBean { - - public void init() { - // do some initialization work - } -} - - ...is exactly the same as... - - <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> - - public class AnotherExampleBean implements InitializingBean { - - public void afterPropertiesSet() { - // do some initialization work - } -} - - ... but does not couple the code to Spring. -
- -
- Destruction callbacks - - Implementing the - org.springframework.beans.factory.DisposableBean - interface allows a bean to get a callback when the container - containing it is destroyed. The - DisposableBean interface specifies a - single method: - - 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, - specify a generic method that is supported by bean definitions. With - XML-based configuration metadata, you use the - destroy-method attribute on the - <bean/>. For example, the following - definition: - - <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/> - - public class ExampleBean { - - public void cleanup() { - // do some destruction work (like releasing pooled connections) - } -} - - ...is exactly the same as... - - <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> - - public class AnotherExampleBean implements DisposableBean { - - public void destroy() { - // do some destruction work (like releasing pooled connections) - } -} - - ... but does not couple the code to Spring. -
- -
- Default initialization and destroy methods - - When you write initialization and destroy method callbacks that - do not use the Spring-specific - InitializingBean and - DisposableBean callback interfaces, you - typically write methods with names such as init(), - initialize(), dispose(), and so - on. Ideally, the names of such lifecycle callback methods are - standardized across a project so that all developers use the same - method names and ensure consistency. - - You can configure the Spring container to - look for named initialization and destroy callback - method names on every bean. This means that you, - as an application developer, can write your application classes and - use an initialization callback called init(), - without having to configure an init-method="init" - attribute with each bean definition. The Spring IoC container calls - that method when the bean is created (and in accordance with the - standard lifecycle callback contract described previously). This - feature also enforces a consistent naming convention for - initialization and destroy method callbacks. - - 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. - - public class DefaultBlogService implements BlogService { - - private 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."); - } - } -} - - <beans default-init-method="init"> - - <bean id="blogService" class="com.foo.DefaultBlogService"> - <property name="blogDao" ref="blogDao" /> - </bean> - -</beans> - - The presence of the default-init-method - attribute on the top-level <beans/> element - attribute causes the Spring IoC container to recognize a method called - init on beans as the initialization method - callback. When a bean is created and assembled, if the bean class has - such a method, it is invoked at the appropriate time. - - You configure destroy method callbacks similarly (in XML, that - is) by using the default-destroy-method attribute - on the top-level <beans/> element. - - Where existing bean classes already have callback methods that - are named at variance with the convention, you can override the - default by specifying (in XML, that is) the method name using the - init-method and destroy-method - attributes of the <bean/> itself. - - The Spring container guarantees that a configured initialization - callback is called immediately after a bean is supplied with all - dependencies. Thus the initialization callback is called on the raw - bean reference, which means that AOP interceptors and so forth are not - yet applied to the bean. A target bean is fully created - first, then an AOP proxy - (for example) with its interceptor chain is applied. If the target - bean and the proxy are defined separately, your code can even interact - with the raw target bean, bypassing the proxy. Hence, it would be - inconsistent to apply the interceptors to the init method, because - doing so would couple the lifecycle of the target bean with its - proxy/interceptors and leave strange semantics when your code - interacts directly to the raw target bean. -
- -
- Combining lifecycle mechanisms - - As of Spring 2.5, you have three options for controlling bean - lifecycle behavior: the InitializingBean - and DisposableBean - callback interfaces; custom init() and - destroy() methods; and the @PostConstruct - and @PreDestroy annotations. You - can combine these mechanisms to control a given bean. - - - If multiple lifecycle mechanisms are configured for a bean, - and each mechanism is configured with a different method name, then - each configured method is executed in the order listed below. - However, if the same method name is configured - for example, - init() for an initialization method - for more - than one of these lifecycle mechanisms, that method is executed - once, as explained in the preceding section. - - - Multiple lifecycle mechanisms configured for the same bean, with - different initialization methods, are called as follows: - - - - Methods annotated with - @PostConstruct - - - - afterPropertiesSet() as defined by the - InitializingBean callback - interface - - - - A custom configured init() method - - - - Destroy methods are called in the same order: - - - - Methods annotated with - @PreDestroy - - - - destroy() as defined by the - DisposableBean callback - interface - - - - A custom configured destroy() - method - - -
- -
- Startup and shutdown callbacks - - The Lifecycle interface defines - the essential methods for any object that has its own lifecycle - requirements (e.g. starts and stops some background process): - - public interface Lifecycle { - - void start(); - - void stop(); - - boolean isRunning(); - -} - - Any Spring-managed object may implement that interface. Then, - when the ApplicationContext itself starts and stops, it will cascade - those calls to all Lifecycle implementations defined within that - context. It does this by delegating to a - LifecycleProcessor: - - public interface LifecycleProcessor extends Lifecycle { - - void onRefresh(); - - void onClose(); - -} - - Notice that the - LifecycleProcessor is itself an - extension of the Lifecycle interface. - It also adds two other methods for reacting to the context being - refreshed and closed. - - The order of startup and shutdown invocations can be important. - If a "depends-on" relationship exists between any two objects, the - dependent side will start after its dependency, - and it will stop before its dependency. However, - at times the direct dependencies are unknown. You may only know that - objects of a certain type should start prior to objects of another - type. In those cases, the - SmartLifecycle interface defines - another option, namely the getPhase() method - as defined on its super-interface, - Phased. - - public interface Phased { - - int getPhase(); - -} - - -public interface SmartLifecycle extends Lifecycle, Phased { - - boolean isAutoStartup(); - - void stop(Runnable callback); - -} - - When starting, the objects with the lowest phase start first, - and when stopping, the reverse order is followed. Therefore, an object - that implements SmartLifecycle and - whose getPhase() method returns Integer.MIN_VALUE - would be among the first to start and the last to stop. At the other - end of the spectrum, a phase value of - Integer.MAX_VALUE would indicate that the object - should be started last and stopped first (likely because it depends on - other processes to be running). When considering the phase value, it's - also important to know that the default phase for any "normal" - Lifecycle object that does not - implement SmartLifecycle would be 0. - Therefore, any negative phase value would indicate that an object - should start before those standard components (and stop after them), - and vice versa for any positive phase value. - - As you can see the stop method defined by - SmartLifecycle accepts a callback. Any - implementation must invoke that callback's run() - method after that implementation's shutdown process is complete. That - enables asynchronous shutdown where necessary since the default - implementation of the - LifecycleProcessor interface, - DefaultLifecycleProcessor, will wait up to its - timeout value for the group of objects within each phase to invoke - that callback. The default per-phase timeout is 30 seconds. You can - override the default lifecycle processor instance by defining a bean - named "lifecycleProcessor" within the context. If you only want to - modify the timeout, then defining the following would be - sufficient: - - <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> - <!-- timeout value in milliseconds --> - <property name="timeoutPerShutdownPhase" value="10000"/> -</bean> - - As mentioned, the - LifecycleProcessor interface defines - callback methods for the refreshing and closing of the context as - well. The latter will simply drive the shutdown process as if stop() - had been called explicitly, but it will happen when the context is - closing. The 'refresh' callback on the other hand enables another - feature of SmartLifecycle beans. When - the context is refreshed (after all objects have been instantiated and - initialized), that callback will be invoked, and at that point the - default lifecycle processor will check the boolean value returned by - each SmartLifecycle object's - isAutoStartup() method. If "true", then that - object will be started at that point rather than waiting for an - explicit invocation of the context's or its own start() method (unlike - the context refresh, the context start does not happen automatically - for a standard context implementation). The "phase" value as well as - any "depends-on" relationships will determine the startup order in the - same way as described above. -
- -
- Shutting down the Spring IoC container gracefully in non-web - applications - - - This section applies only to non-web applications. Spring's - web-based ApplicationContext - implementations already have code in place to shut down the Spring - IoC container gracefully when the relevant web application is shut - down. - - - If you are using Spring's IoC container in a non-web application - environment; for example, in a rich client desktop environment; you - register a shutdown hook with the JVM. Doing so ensures a graceful - shutdown and calls the relevant destroy methods on your singleton - beans so that all resources are released. Of course, you must still - configure and implement these destroy callbacks correctly. - - To register a shutdown hook, you call the - registerShutdownHook() method that is - declared on the AbstractApplicationContext - class: - - import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -public final class Boot { - - public static void main(final String[] args) throws Exception { - AbstractApplicationContext ctx - = new ClassPathXmlApplicationContext(new String []{"beans.xml"}); - - // add a shutdown hook for the above context... - ctx.registerShutdownHook(); - - // app runs here... - - // main method exits, hook is called prior to the app shutting down... - } -} -
-
- -
- <interfacename>ApplicationContextAware</interfacename> and - <interfacename>BeanNameAware</interfacename> - - When an ApplicationContext creates - a class that implements the - org.springframework.context.ApplicationContextAware - interface, the class is provided with a reference to that - ApplicationContext. - - public interface ApplicationContextAware { - - void setApplicationContext(ApplicationContext applicationContext) throws BeansException; -} - - Thus beans can manipulate programmatically the - ApplicationContext that created them, - through the ApplicationContext interface, - or by casting the reference to a known subclass of this interface, such - as ConfigurableApplicationContext, which exposes - additional functionality. One use would be the programmatic retrieval of - other beans. Sometimes this capability is useful; however, in general - you should avoid it, because it couples the code to Spring and does not - follow the Inversion of Control style, where collaborators are provided - to beans as properties. Other methods of the ApplicationContext provide - access to file resources, publishing application events, and accessing a - MessageSource. These additional features are described in - - As of Spring 2.5, autowiring is another alternative to obtain - reference to the ApplicationContext. The - "traditional" constructor and - byType autowiring modes (as described in ) can provide a dependency of type - ApplicationContext for a constructor - argument or setter method parameter, respectively. For more flexibility, - including the ability to autowire fields and multiple parameter methods, - use the new annotation-based autowiring features. If you do, the - ApplicationFactory is autowired into a - field, constructor argument, or method parameter that is expecting the - BeanFactory type if the field, - constructor, or method in question carries the - @Autowired annotation. For more - information, see . - - 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. - - public interface BeanNameAware { - - void setBeanName(string name) throws BeansException; -} - - The callback is invoked after population of normal bean properties - but before an initialization callback such as - InitializingBeans - afterPropertiesSet or a custom init-method. -
- -
- Other <interfacename>Aware</interfacename> interfaces - - Besides ApplicationContextAware and - BeanNameAware discussed above, Spring - offers a range of - Aware interfaces - that allow beans to indicate to the container that they require a - certain infrastructure dependency. The most - important Aware interfaces are summarized - below - as a general rule, the name is a good indication of the - dependency type: - - - <interfacename>Aware</interfacename> interfaces - - - - - - - Name - - Injected Dependency - - Explained in... - - - - - - ApplicationContextAware - - Declaring - ApplicationContext - - - - - - ApplicationEventPublisherAware - - Event publisher of the enclosing - ApplicationContext - - - - - - BeanClassLoaderAware - - Class loader used to load the bean - classes. - - - - - - BeanFactoryAware - - Declaring - BeanFactory - - - - - - BeanNameAware - - Name of the declaring bean - - - - - - BootstrapContextAware - - Resource adapter - BootstrapContext the container - runs in. Typically available only in JCA aware - ApplicationContexts - - - - - - LoadTimeWeaverAware - - Defined weaver for processing - class definition at load time - - - - - - MessageSourceAware - - Configured strategy for resolving messages (with - support for parametrization and - internationalization) - - - - - - NotificationPublisherAware - - Spring JMX notification publisher - - - - - - PortletConfigAware - - Current - PortletConfig the container runs - in. Valid only in a web-aware Spring - ApplicationContext - - - - - - PortletContextAware - - Current - PortletContext the container runs - in. Valid only in a web-aware Spring - ApplicationContext - - - - - - ResourceLoaderAware - - Configured loader for low-level access to - resources - - - - - - ServletConfigAware - - Current - ServletConfig the container runs - in. Valid only in a web-aware Spring - ApplicationContext - - - - - - ServletContextAware - - Current - ServletContext the container runs - in. Valid only in a web-aware Spring - ApplicationContext - - - - - -
- - Note again that usage of these interfaces ties your code to the - Spring API and does not follow the Inversion of Control style. As such, - they are recommended for infrastructure beans that require programmatic - access to the container. -
-
+
Bean definition inheritance A bean definition can contain a lot of configuration information, - including constructor arguments, property values, and container-specific - information such as initialization method, static factory method name, and - so on. A child bean definition inherits configuration data from a parent - definition. The child definition can override some values, or add others, - as needed. Using parent and child bean definitions can save a lot of - typing. Effectively, this is a form of templating. + including constructor arguments, property values, and container-specific + information such as initialization method, static factory method name, and + so on. A child bean definition inherits configuration data from a parent + definition. The child definition can override some values, or add others, + as needed. Using parent and child bean definitions can save a lot of + typing. Effectively, this is a form of templating. - If you work with an - ApplicationContext interface - programmatically, child bean definitions are represented by the - ChildBeanDefinition class. Most users do not work - with them on this level, instead configuring bean definitions - declaratively in something 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. + If you work with an ApplicationContext + interface programmatically, child bean definitions are represented by the + ChildBeanDefinition class. Most users do not work + with them on this level, instead configuring bean definitions + declaratively in something 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. <bean id="inheritedTestBean" abstract="true" class="org.springframework.beans.TestBean"> @@ -3839,33 +871,33 @@ public final class Boot { <bean id="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean" init-method="initialize"> - + <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --> </bean> - A child bean definition uses the bean class from the parent - definition if none is specified, but can also override it. In the latter - case, the child bean class must be compatible with the parent, that is, it - must accept the parent's property values. + A child bean definition uses the bean class from the parent definition + if none is specified, but can also override it. In the latter case, the + child bean class must be compatible with the parent, that is, it must + accept the parent's property values. - A child bean definition inherits constructor argument values, - property values, and method overrides from the parent, with the option to - add new values. Any initialization method, destroy method, and/or - static factory method settings that you specify will - override the corresponding parent settings. + A child bean definition inherits constructor argument values, property + values, and method overrides from the parent, with the option to add new + values. Any initialization method, destroy method, and/or + static factory method settings that you specify will + override the corresponding parent settings. - The remaining settings are always taken from - the child definition: depends on, autowire - mode, dependency check, - singleton, scope, lazy - init. + The remaining settings are always taken from the + child definition: depends on, autowire + mode, dependency check, + singleton, scope, lazy + init. The preceding example explicitly marks the parent bean definition as - abstract by using the abstract attribute. If the parent - definition does not specify a class, explicitly marking the parent bean - definition as abstract is required, as follows: + abstract by using the abstract attribute. If the parent + definition does not specify a class, explicitly marking the parent bean + definition as abstract is required, as follows: <bean id="inheritedTestBeanWithoutClass" abstract="true"> <property name="name" value="parent"/> @@ -3879,2783 +911,46 @@ public final class Boot { </bean> The parent bean cannot be instantiated on its own because it is - incomplete, and it is also explicitly marked as - abstract. When a definition is - abstract like this, it is usable only as a pure - template bean definition that serves as a parent definition for child - definitions. Trying to use such an abstract parent bean - on its own, by referring to it as a ref property of another bean or doing - an explicit getBean() call with the parent bean - id, returns an error. Similarly, the container's internal - preInstantiateSingletons() method ignores bean - definitions that are defined as abstract. + incomplete, and it is also explicitly marked as + abstract. When a definition is + abstract like this, it is usable only as a pure + template bean definition that serves as a parent definition for child + definitions. Trying to use such an abstract parent bean + on its own, by referring to it as a ref property of another bean or doing + an explicit getBean() call with the parent bean + id, returns an error. Similarly, the container's internal + preInstantiateSingletons() method ignores bean + definitions that are defined as abstract. ApplicationContext pre-instantiates all - singletons by default. Therefore, it is important (at least for - singleton beans) that if you have a (parent) bean definition which you - intend to use only as a template, and this definition specifies a class, - you must make sure to set the abstract attribute to - true, otherwise the application context will - actually (attempt to) pre-instantiate the abstract - bean. + singletons by default. Therefore, it is important (at least for + singleton beans) that if you have a (parent) bean definition which you + intend to use only as a template, and this definition specifies a class, + you must make sure to set the abstract attribute to + true, otherwise the application context will + actually (attempt to) pre-instantiate the abstract + bean.
-
- Container extension points + - Typically, an application developer does not need to subclass any - ApplicationContext implementation classes. - You can extend The Spring IoC container infinitely by plugging in - implementations of special integration interfaces. The next few sections - describe these integration interfaces. + -
- Customizing beans using the - <interfacename>BeanPostProcessor</interfacename> Interface <literal> - </literal> + - The BeanPostProcessor interface - defines callback methods that you can implement - to provide your own (or override the container's default) instantiation - logic, dependency-resolution logic, and so forth. If you want to - implement some custom logic after the Spring container finishes - instantiating, configuring, and otherwise initializing a bean, you can - plug in one or more BeanPostProcessor - implementations. - - You can configure multiple BeanPostProcessor - interfaces. You can control the order in which these - BeanPostProcessor interfaces execute by setting the - order property. You can set this property only if the - BeanPostProcessor implements the - Ordered interface; if you write your own - BeanPostProcessor you should consider - implementing the Ordered interface too. - For more details, consult the Javadoc for the - BeanPostProcessor and - Ordered interfaces. - - - BeanPostProcessors operate on bean (or - object) instances; that is to say, the Spring IoC - container instantiates a bean instance and then - BeanPostProcessor interfaces do their work. - - BeanPostProcessor interfaces are scoped - per-container. This is only relevant if you are - using container hierarchies. If you define a - BeanPostProcessor in one container, it - will only do its work on the beans in that - container. Beans that are defined in one container are not - post-processed by a BeanPostProcessor in another - container, even if both containers are part of the same - hierarchy. - - To change the actual bean definition (that is, the recipe that - defines the bean), you instead need to use a - BeanFactoryPostProcessor, described - below in . - - - The - org.springframework.beans.factory.config.BeanPostProcessor - interface consists of exactly two callback methods. When such a class is - registered as a post-processor with the container, for each bean - instance that is created by the container, the post-processor gets a - callback from the container both before container - initialization methods (such as afterPropertiesSet - and any declared init method) are called, and also afterwards. The - post-processor can take any action with the bean instance, including - ignoring the callback completely. A bean post-processor typically checks - for callback interfaces, or may wrap a bean with a proxy. Some Spring - AOP infrastructure classes are implemented as bean post-processors and - they do this proxy-wrapping logic. - - An ApplicationContext - automatically detects any beans that are defined in - the configuration metadata it receives that implement the - BeanPostProcessor interface. The - ApplicationContext registers these beans - as post-processors, to be then called appropriately by the container - upon bean creation. You can then deploy the post-processors as you would - any bean. - - - <interfacename>BeanPostProcessors</interfacename> and AOP - auto-proxying - - Classes that implement the - BeanPostProcessor interface are - special, and so they are treated differently by - the container. All BeanPostProcessors - and their directly referenced beans are - instantiated on startup, as part of the special startup phase of the - ApplicationContext. Next, all those - BeanPostProcessors are registered in a - sorted fashion - and applied to all further beans. Because AOP - auto-proxying is implemented as a - BeanPostProcessor itself, no - BeanPostProcessors or directly - referenced beans are eligible for auto-proxying, and thus do not have - aspects woven into them. - - For any such bean, you should see an info log message: - Bean foo is not eligible for getting processed by all - BeanPostProcessor interfaces (for example: not eligible for - auto-proxying). - - - The following examples show how to write, register, and use - BeanPostProcessors in the context of an - ApplicationContext. - -
- Example: Hello World, - <interfacename>BeanPostProcessor</interfacename>-style - - This first example illustrates basic usage. The example shows a - custom BeanPostProcessor implementation - that invokes the toString() method of each - bean as it is created by the container and prints the resulting string - to the system console. - - Find below the custom - BeanPostProcessor implementation class - definition: - - package scripting; - -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.BeansException; - -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... - } - - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - System.out.println("Bean '" + beanName + "' created : " + bean.toString()); - return bean; - } -} - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:lang="http://www.springframework.org/schema/lang" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/lang - http://www.springframework.org/schema/lang/spring-lang-3.0.xsd"> - - <lang:groovy id="messenger" - script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"> - <lang:property name="message" value="Fiona Apple Is Just So Dreamy."/> - </lang:groovy> - - <!-- - when the above bean (messenger) is instantiated, this custom - BeanPostProcessor implementation will output the fact to the system console - --> - <bean class="scripting.InstantiationTracingBeanPostProcessor"/> - -</beans> - - 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 .) - - The following small driver script executes the preceding code - and configuration: - - import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.scripting.Messenger; - -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); - } -} - - The output of the preceding execution resembles the - following: - - Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 -org.springframework.scripting.groovy.GroovyMessenger@272961 -
- -
- Example: The - <classname>RequiredAnnotationBeanPostProcessor</classname> - - Using callback interfaces or annotations in conjunction with a - custom BeanPostProcessor implementation - is a common means of extending the Spring IoC container. An example is - Spring's RequiredAnnotationBeanPostProcessor -- a - BeanPostProcessor implementation that - ships with the Spring distribution which ensures that JavaBean - properties on beans that are marked with an (arbitrary) annotation are - actually (configured to be) dependency-injected with a value. -
-
- -
- Customizing configuration metadata with - <interfacename>BeanFactoryPostProcessor</interfacename> - interface - - 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 the - BeanPostProcessor, with one major - difference: BeanFactoryPostProcessors 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 any beans other - than BeanFactoryPostProcessors. - - You can configure multiple - BeanFactoryPostProcessors. You can control the order - in which these BeanFactoryPostProcessors execute by - setting the order property. However, you can only set - this property if the - BeanFactoryPostProcessor implements the - Ordered interface. If you write your own - BeanFactoryPostProcessor, you should - consider implementing the Ordered - interface too; consult the Javadoc for the - BeanFactoryPostProcessor and - Ordered interfaces for more - details. - - - If you want to change the actual bean - instances (the objects that are created from the - configuration metadata), then you instead need to use a - BeanPostProcessor (described above in - . While it is technically - possible to work with bean instances within a - BeanFactoryPostProcessor (e.g. using - BeanFactory.getBean()), doing so causes - premature bean instantiation, violating the usual containter lifecycle. - This may cause negative side effects such as bypassing bean post - processing. - - Also, BeanFactoryPostProcessors are scoped - per-container. This is only relevant if you are - using container hierarchies. If you define a - BeanFactoryPostProcessor in one - container, it will only do its stuff on the bean - definitions in that container. Bean definitions in another container - will not be post-processed by - BeanFactoryPostProcessors in another container, - even if both containers are part of the same hierarchy. - - - A bean factory post-processor is executed automatically when it is - declared inside of an ApplicationContext, - in order to apply changes to the configuration metadata that defines a - container. Spring includes a number of pre-existing bean factory - post-processors, such as - PropertyOverrideConfigurer and - PropertyPlaceholderConfigurer. A custom - BeanFactoryPostProcessor can also be - used, for example, to register custom property editors. - - - - An ApplicationContext detects any - beans that are deployed into it and that implement the - BeanFactoryPostProcessor interface. It - automatically uses these beans as bean factory post-processors, at the - appropriate time. You can then deploy these post-processor beans as you - would any other bean. - - - As with BeanPostProcessors, you typically do - not want BeanFactoryPostProcessors marked as - lazy-initialized. If they are marked as such, the Spring container - never instantiates them, and thus they cannot apply their custom - logic. If you use the default-lazy-init attribute - on the declaration of your <beans/> element, - be sure to mark your various - BeanFactoryPostProcessor bean - definitions with lazy-init="false". - - -
- Example: the - <interfacename>PropertyPlaceholderConfigurer</interfacename> - - You use the - PropertyPlaceholderConfigurer to - externalize property values from a bean definition into another - separate file in the standard Java Properties - format. Doing so enables the person deploying an application to - customize environment-specific properties such as database URLs and - passwords, without the complexity or risk of modifying the main XML - definition file or files for the container. - - - - Consider the following XML-based configuration metadata - fragment, where a DataSource 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 / Log4J / JSP EL style. - - <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> - <property name="locations" value="classpath:com/foo/jdbc.properties"/> -</bean> - -<bean id="dataSource" destroy-method="close" - class="org.apache.commons.dbcp.BasicDataSource"> - <property name="driverClassName" value="${jdbc.driverClassName}"/> - <property name="url" value="${jdbc.url}"/> - <property name="username" value="${jdbc.username}"/> - <property name="password" value="${jdbc.password}"/> -</bean> - - The actual values come from another file in the standard Java - Properties format: - - jdbc.driverClassName=org.hsqldb.jdbcDriver -jdbc.url=jdbc:hsqldb:hsql://production:9002 -jdbc.username=sa -jdbc.password=root - - Therefore, the string ${jdbc.username} is replaced at runtime - with the value 'sa' and similarly for other placeholder values that - match to keys in the property file. The PropertyPlaceholderConfigurer - checks for placeholders in most locations of a bean definition and the - placeholder prefix and suffix can be customized. - - With the context namespace introduced in - Spring 2.5, it is possible to configure property placeholders with a - dedicated configuration element. You can provide multiple locations as - a comma-separated list in the location - attribute. - - <context:property-placeholder location="classpath:com/foo/jdbc.properties"/> - - The PropertyPlaceholderConfigurer does - not look for properties only in the Properties - file you specify, but also checks against the Java - System properties if it cannot find a property - you are trying to use. You can customize this behavior by setting the - systemPropertiesMode property of the configurer. It - has three values that specify configurer behavior: always override, - never override, and override only if the property - is not found in the properties file specified. - - Consult the Javadoc for the - PropertyPlaceholderConfigurer for more - information. - - - Class name substitution - - You can use the - PropertyPlaceholderConfigurer to substitute - class names, which is sometimes useful when you have to pick a - particular implementation class at runtime. For example: - - <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> - <property name="locations"> - <value>classpath:com/foo/strategy.properties</value> - </property> - <property name="properties"> - <value>custom.strategy.class=com.foo.DefaultStrategy</value> - </property> -</bean> - -<bean id="serviceStrategy" class="${custom.strategy.class}"/> - - If the class cannot be resolved at runtime to a valid class, - resolution of the bean fails when it is about to be created, which - is during the preInstantiateSingletons() - phase of an ApplicationContext for a - non-lazy-init bean. - -
- -
- Example: the - <classname>PropertyOverrideConfigurer</classname> - - The PropertyOverrideConfigurer, another - bean factory post-processor, resembles the - PropertyPlaceholderConfigurer, but - unlike the latter, the original definitions can have default values or - no values at all for bean properties. If an overriding - Properties file does not have an entry for a - certain bean property, the default context definition is used. - - Note that the bean definition is not aware - of being overridden, so it is not immediately obvious from the XML - definition file that the override configurer is used. In case of - multiple PropertyOverrideConfigurer instances - that define different values for the same bean property, the last one - wins, due to the overriding mechanism. - - Properties file configuration lines take this format: - - beanName.property=value - - For example: - - dataSource.driverClassName=com.mysql.jdbc.Driver -dataSource.url=jdbc:mysql:mydb - - This example file is usable against a container definition that - contains a bean called dataSource, which has - driver and url - properties. - - Compound property names are also supported, as long as every - component of the path except the final property being overridden is - already non-null (presumably initialized by the constructors). In this - example... - - foo.fred.bob.sammy=123 - - ... the sammy property of the - bob property of the fred - property of the foo bean is set to the scalar value - 123. - - - Specified override values are always - literal values; they are not translated into - bean references. This convention also applies when the original - value in the XML bean 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: - - <context:property-override location="classpath:override.properties"/> -
-
- -
- Customizing instantiation logic with the - <interfacename>FactoryBean</interfacename> Interface <literal> - </literal> - - You implement the - org.springframework.beans.factory.FactoryBean - interface for objects that are themselves - factories. - - The FactoryBean interface is a - point of pluggability into the Spring IoC container's instantiation - logic. If you have complex initialization code that is better expressed - in Java as opposed to a (potentially) verbose amount of XML, you can - create your own FactoryBean, write the - complex initialization inside that class, and then plug your custom - FactoryBean into the container. - - The FactoryBean interface provides - three methods: - - - - Object getObject(): returns an - instance of the object this factory creates. The instance can - possibly be shared, depending on whether this factory returns - singletons or prototypes. - - - - boolean isSingleton(): returns - true if this - FactoryBean returns singletons, - false otherwise. - - - - Class getObjectType(): returns the - object type returned by the getObject() - method or null if the type is not known in - advance - - - - The FactoryBean concept and - interface is used in a number of places within the Spring Framework; - more than 50 implementations of the - FactoryBean interface ship with Spring - itself. - - When you need to ask a container for an actual - FactoryBean instance itself, not the bean - it produces, you preface the bean id with the ampersand symbol - & (without quotes) when calling the - getBean() method of the - ApplicationContext. So for a given - FactoryBean with an id of - myBean, invoking getBean("myBean") - on the container returns the product of the - FactoryBean, and invoking - getBean("&myBean") returns the - FactoryBean instance itself. -
-
- -
- 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 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 while others - argue that annotated classes are no longer POJOs and, furthermore, that - the configuration becomes decentralized and harder to control. - - No matter the choice, Spring can accommodate both styles and even - mix them together. It's worth pointing out that through its JavaConfig option, Spring allows 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 SpringSource Tool - Suite. - - - An alternative to XML setups is provided by annotation-based - configuration which rely on the bytecode metadata for wiring up components - instead of angle-bracket declarations. Instead of using XML to describe a - bean wiring, the developer moves the configuration into the component - class itself by using annotations on the relevant class, method, or field - declaration. As mentioned in , using a - BeanPostProcessor in conjunction with - annotations is a common means of extending the Spring IoC container. For - example, Spring 2.0 introduced the possibility of enforcing required - properties with the @Required annotation. As of - Spring 2.5, it is now possible to follow that same general approach to - drive Spring's dependency injection. Essentially, the - @Autowired annotation provides the same - capabilities as described in but - with more fine-grained control and wider applicability. Spring 2.5 also - adds support for JSR-250 annotations such as - @Resource, - @PostConstruct, and - @PreDestroy. Spring 3.0 adds support for - JSR-330 (Dependency Injection for Java) annotations contained in the - javax.inject package such as @Inject, - @Qualifier, @Named, and @Provider if the JSR330 jar is - present on the classpath. Use of these annotations also requires that - certain BeanPostProcessors be registered - within the Spring container. - Annotation injection is performed - - before - - XML injection, thus the latter configuration will override the former for properties wired through both approaches. - As always, you can register them as individual bean definitions, - but they can also be implicitly registered by including the following tag - in an XML-based Spring configuration (notice the inclusion of the - context namespace): - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - <context:annotation-config/> - -</beans> - - (The implicitly registered post-processors include AutowiredAnnotationBeanPostProcessor, - CommonAnnotationBeanPostProcessor, - PersistenceAnnotationBeanPostProcessor, - as well as the aforementioned RequiredAnnotationBeanPostProcessor.) - - - <context:annotation-config/> only looks - for annotations on beans in the same application context in which it is - defined. This means that, if you put - <context:annotation-config/> in a - WebApplicationContext for a - DispatcherServlet, it only checks for - @Autowired beans in your controllers, and - not your services. See for more - information. - - -
- <interfacename>@Required</interfacename> - - The @Required annotation applies to - bean property setter methods, as in the following example: - - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Required - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... -} - - This annotation simply indicates that the affected bean property - must be populated at configuration time, through an explicit property - value in a bean definition or through autowiring. The container throws - an exception if the affected bean property has not been populated; this - allows for eager and explicit failure, avoiding - NullPointerExceptions or the like later on. It is - still recommended that you put assertions into the bean class itself, - for example, into an init method. Doing so enforces those required - references and values even when you use the class outside of a - container. -
- -
- <interfacename>@Autowired and @Inject</interfacename> - - As expected, you can apply the - @Autowired annotation to "traditional" - setter methods: - - - JSR 330's @Inject annotation can be used in place of Spring's - @Autowired in the examples below. - @Inject does not have a required - property unlike Spring's @Autowired - annotation which has a required property to - indicate if the value being injected is optional. This behavior is - enabled automatically if you have the JSR 330 JAR on the - classpath. - - - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Autowired - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... -} - - You can also apply the annotation to methods with arbitrary names - and/or multiple arguments: - - public class MovieRecommender { - - private MovieCatalog movieCatalog; - - private CustomerPreferenceDao customerPreferenceDao; - - @Autowired - public void prepare(MovieCatalog movieCatalog, - CustomerPreferenceDao customerPreferenceDao) { - this.movieCatalog = movieCatalog; - this.customerPreferenceDao = customerPreferenceDao; - } - - // ... -} - - You can apply @Autowired to - constructors and fields: - - public class MovieRecommender { - - @Autowired - private MovieCatalog movieCatalog; - - private 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: - - public class MovieRecommender { - - @Autowired - private MovieCatalog[] movieCatalogs; - - // ... -} - - The same applies for typed collections: - - public class MovieRecommender { - - private Set<MovieCatalog> movieCatalogs; - - @Autowired - public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) { - this.movieCatalogs = movieCatalogs; - } - - // ... -} - - 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: - - public class MovieRecommender { - - private Map<String, MovieCatalog> movieCatalogs; - - @Autowired - public void setMovieCatalogs(Map<String, MovieCatalog> 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. - - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Autowired(required=false) - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... -} - - - Only one annotated constructor per-class - can be marked as required, but multiple - non-required constructors can be annotated. In that case, each is - considered among the candidates and Spring uses the - greediest constructor whose dependencies can be - satisfied, that is the constructor that has the largest number of - arguments. - - @Autowired's - required attribute is recommended over the - @Required annotation. The - required attribute indicates that the property is - not required for autowiring purposes, the property is ignored if it - cannot be autowired. @Required, on the - other hand, is stronger in that it enforces the property that was set - by any means supported by the container. If no value is injected, a - corresponding exception is raised. - - - You can also use @Autowired for - interfaces that are well-known resolvable dependencies: - BeanFactory, - ApplicationContext, - ResourceLoader, - ApplicationEventPublisher, and - MessageSource. These interfaces and their - extended interfaces, such as - ConfigurableApplicationContext or - ResourcePatternResolver, are - automatically resolved, with no special setup necessary. - - public class MovieRecommender { - - @Autowired - private ApplicationContext context; - - public MovieRecommender() { - } - - // ... -} -
- -
- Fine-tuning annotation-based autowiring with qualifiers - - Because autowiring by type may lead to multiple candidates, it is - often necessary to have more control over the selection process. One way - to accomplish this is with Spring's - @Qualifier annotation. You can associate - qualifier values with specific 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: - - - JSR 330's @Qualifier annotation - can only be applied as a meta-annotation unlike Spring's @Qualifier - which takes a string property to discriminate among multiple injection - candidates and can be placed on annotations as well as types, fields, - methods, constructors, and parameters. - - - public class MovieRecommender { - - @Autowired - @Qualifier("main") - private MovieCatalog movieCatalog; - - // ... -} - - The @Qualifier annotation can also - be specified on individual constructor arguments or method - parameters: - - public class MovieRecommender { - - private MovieCatalog movieCatalog; - - private 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. - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - <context:annotation-config/> - - <bean class="example.SimpleMovieCatalog"> - <qualifier value="main"/> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean class="example.SimpleMovieCatalog"> - <qualifier value="action"/> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean id="movieRecommender" class="example.MovieRecommender"/> - -</beans> - - - For a fallback match, the bean name is considered a default - qualifier value. Thus you can define the bean with an id "main" instead - of the nested qualifier element, leading to the same matching result. - However, although you can use this convention to refer to specific beans - by name, @Autowired is fundamentally - about type-driven injection with optional semantic qualifiers. This - means that qualifier values, even with the bean name fallback, always - have narrowing semantics within the set of type matches; they do not - semantically express a reference to a unique bean id. Good qualifier - values are "main" or "EMEA" or "persistent", expressing characteristics - of a specific component that are independent from the bean id, which may - be auto-generated in case of an anonymous bean definition like the one - in the preceding example. - - Qualifiers also apply to typed collections, as discussed above, - for example, to Set<MovieCatalog>. In this - case, all matching beans according to the declared qualifiers are - injected as a collection. This implies that qualifiers do not have to be - unique; they rather simply constitute filtering criteria. For example, - you can define multiple MovieCatalog beans with - the same qualifier value "action"; all of which would be injected into a - Set<MovieCatalog> annotated with - @Qualifier("action"). - - - If you intend to express annotation-driven injection by name, do - not primarily use @Autowired, even if - is technically capable of referring to a bean name through - @Qualifier values. Instead, use the - JSR-250 @Resource annotation, which is - semantically defined to identify a specific target component by its - unique name, with the declared type being irrelevant for the matching - process. - - As a specific consequence of this semantic difference, beans - that are themselves defined as a collection or map type cannot be - injected through @Autowired, because - type matching is not properly applicable to them. Use - @Resource for such beans, referring to - the specific collection or map bean by unique name. - - @Autowired applies to fields, - constructors, and multi-argument methods, allowing for narrowing - through qualifier annotations at the parameter level. By contrast, - @Resource is supported only for fields - and bean property setter methods with a single argument. As a - consequence, stick with qualifiers if your injection target is a - constructor or a multi-argument method. - - - You can create your own custom qualifier annotations. Simply - define an annotation and provide the - @Qualifier annotation within your - definition: - - - You can use JSR 330's @Qualifier - annotation in the manner described below in place of - Spring's @Qualifier annotation. This - behavior is enabled automatically if you have the JSR 330 jar on the - classpath. - - - @Target({ElementType.FIELD, ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -@Qualifier -public @interface Genre { - - String value(); -} - - Then you can provide the custom qualifier on autowired fields and - parameters: - - public class MovieRecommender { - - @Autowired - @Genre("Action") - private MovieCatalog actionCatalog; - - private MovieCatalog comedyCatalog; - - @Autowired - public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) { - this.comedyCatalog = comedyCatalog; - } - - // ... -} - - Next, provide the information for the candidate bean definitions. - You can add <qualifier/> tags as sub-elements - of the <bean/> tag and then specify the - type and value to match your - custom qualifier annotations. The type is matched against the - 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. - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - <context:annotation-config/> - - <bean class="example.SimpleMovieCatalog"> - <qualifier type="Genre" value="Action"/> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean class="example.SimpleMovieCatalog"> - <qualifier type="example.Genre" value="Comedy"/> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean id="movieRecommender" class="example.MovieRecommender"/> - -</beans> - - - In , you will see an - annotation-based alternative to providing the qualifier metadata in XML. - Specifically, see . - - In some cases, it may be sufficient to use an annotation without a - value. This may be useful when the annotation serves a more generic - purpose and can be applied across several different types of - dependencies. For example, you may provide an - offline catalog that would be searched when no - Internet connection is available. First define the simple - annotation: - - @Target({ElementType.FIELD, ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -@Qualifier -public @interface Offline { - -} - - Then add the annotation to the field or property to be - autowired: - - public class MovieRecommender { - - @Autowired - @Offline - private MovieCatalog offlineCatalog; - - // ... -} - - Now the bean definition only needs a qualifier - type: - - <bean class="example.SimpleMovieCatalog"> - <qualifier type="Offline"/> - <!-- inject any dependencies required by this bean --> -</bean> - - You can also define custom qualifier annotations that accept named - attributes in addition to or instead of the simple - value attribute. If multiple attribute values are - then specified on a field or parameter to be autowired, a bean - definition must match all such attribute values to - be considered an autowire candidate. As an example, consider the - following annotation definition: - - @Target({ElementType.FIELD, ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -@Qualifier -public @interface MovieQualifier { - - String genre(); - - Format format(); -} - - In this case Format is an enum: - - 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. - - public class MovieRecommender { - - @Autowired - @MovieQualifier(format=Format.VHS, genre="Action") - private MovieCatalog actionVhsCatalog; - - @Autowired - @MovieQualifier(format=Format.VHS, genre="Comedy") - private MovieCatalog comedyVhsCatalog; - - @Autowired - @MovieQualifier(format=Format.DVD, genre="Action") - private MovieCatalog actionDvdCatalog; - - @Autowired - @MovieQualifier(format=Format.BLURAY, genre="Comedy") - private MovieCatalog comedyBluRayCatalog; - - // ... -} - - Finally, the bean definitions should contain matching qualifier - values. This example also demonstrates that bean - meta attributes may be used instead of the - <qualifier/> sub-elements. If available, the - <qualifier/> and its attributes take - precedence, but the autowiring mechanism falls back on the values - provided within the <meta/> tags if no such - qualifier is present, as in the last two bean definitions in the - following example. - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - <context:annotation-config/> - - <bean class="example.SimpleMovieCatalog"> - <qualifier type="MovieQualifier"> - <attribute key="format" value="VHS"/> - <attribute key="genre" value="Action"/> - </qualifier> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean class="example.SimpleMovieCatalog"> - <qualifier type="MovieQualifier"> - <attribute key="format" value="VHS"/> - <attribute key="genre" value="Comedy"/> - </qualifier> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean class="example.SimpleMovieCatalog"> - <meta key="format" value="DVD"/> - <meta key="genre" value="Action"/> - <!-- inject any dependencies required by this bean --> - </bean> - - <bean class="example.SimpleMovieCatalog"> - <meta key="format" value="BLURAY"/> - <meta key="genre" value="Comedy"/> - <!-- inject any dependencies required by this bean --> - </bean> - -</beans> -
- -
- <classname>CustomAutowireConfigurer</classname> - - The 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. - - <bean id="customAutowireConfigurer" - class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"> - <property name="customQualifierTypes"> - <set> - <value>example.CustomQualifier</value> - </set> - </property> -</bean> - - 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 <beans/> element. - In Java 5 or later, the presence of - @Qualifier annotations and any custom - annotations registered with the - CustomAutowireConfigurer will also play a - role. - - 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. -
- -
- <interfacename>@Resource</interfacename> - - 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 in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring - supports this pattern for Spring-managed objects as well. - - @Resource takes a name attribute, - and by default Spring interprets that value as the bean name to be - injected. In other words, it follows by-name - semantics, as demonstrated in this example: - - public class SimpleMovieLister { - - private 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 setter method. In case of a field, it takes the - field name; in case of a setter method, it takes the bean property name. - So the following example is going to have the bean with name - "movieFinder" injected into its setter method: - - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Resource - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } -} - - - 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 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. - - - In the exclusive case of @Resource - usage with no explicit name specified, and similar to - @Autowired, - @Resource finds a primary type match - instead of a specific named bean and resolves well-known resolvable - dependencies: the - BeanFactory, - ApplicationContext, ResourceLoader, - ApplicationEventPublisher, and - MessageSource interfaces. - - Thus in the following example, the - customerPreferenceDao field first looks for a bean - named customerPreferenceDao, then falls back to a primary type match for - the type CustomerPreferenceDao. The "context" - field is injected based on the known resolvable dependency type - ApplicationContext. - - public class MovieRecommender { - - @Resource - private CustomerPreferenceDao customerPreferenceDao; - - @Resource - private ApplicationContext context; - - public MovieRecommender() { - } - - // ... -} -
- -
- <interfacename>@PostConstruct</interfacename> and - <interfacename>@PreDestroy</interfacename> - - The CommonAnnotationBeanPostProcessor not - only recognizes the @Resource annotation - but also the JSR-250 lifecycle annotations. - Introduced in Spring 2.5, the support for these annotations offers yet - another alternative to those described in initialization - callbacks and destruction - callbacks. Provided that the - CommonAnnotationBeanPostProcessor is registered - within the Spring ApplicationContext, a - method carrying one of these annotations is invoked at the same 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. - - public class CachingMovieLister { - - @PostConstruct - public void populateMovieCache() { - // populates the movie cache upon initialization... - } - - @PreDestroy - public void clearMovieCache() { - // clears the movie cache upon destruction... - } -} - - - For details about the effects of combining various lifecycle - mechanisms, see . - -
-
- -
- Classpath scanning and managed components - - - - Most examples in this chapter use XML to specify the configuration - metadata that produces each BeanDefinition - within the Spring container. The previous section () demonstrates how to provide a lot of - the configuration metadata through source-level annotations. Even in those - examples, however, the "base" bean definitions are explicitly defined in - the XML file, while the annotations only drive the dependency injection. - This section describes an option for implicitly detecting the - candidate components by scanning the classpath. - Candidate components are classes that match against a filter criteria and - have a corresponding bean definition registered with the container. This - removes the need to use XML to perform bean registration, instead you can - use annotations (for example @Component), AspectJ type expressions, or - your own custom filter criteria to select which classes will have bean - definitions registered with the container. - - - Starting with Spring 3.0, many features provided by the Spring JavaConfig - project are part of the core Spring Framework. This allows you - to define beans using Java rather than using the traditional XML files. - Take a look at the @Configuration, - @Bean, - @Import, and - @DependsOn annotations for examples of - how to use these new features. - - -
- <interfacename>@Component</interfacename> 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 . - - Spring 2.5 introduces 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 layers, - respectively. Therefore, you can annotate your component classes with - @Component, but by annotating them with - @Repository, - @Service, or - @Controller instead, your classes are - more properly suited for processing by tools or associating with - aspects. For example, these stereotype annotations make ideal targets - for pointcuts. It is also possible that - @Repository, - @Service, and - @Controller may carry additional - semantics in future releases of the Spring Framework. Thus, if you are - choosing between using @Component or - @Service for your service layer, - @Service is clearly the better choice. - Similarly, as stated above, @Repository - is already supported as a marker for automatic exception translation in - your persistence layer. -
- -
- Automatically detecting classes and registering bean - definitions - - Spring can automatically detect stereotyped classes and register - corresponding BeanDefinitions with the - ApplicationContext. For example, the - following two classes are eligible for such autodetection: - - @Service -public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Autowired - public SimpleMovieLister(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } -} - - @Repository -public class JpaMovieFinder implements MovieFinder { - // implementation elided for clarity -} - - To autodetect these classes and register the corresponding beans, - you need to include the following element in XML, where the base-package - element is a common parent package for the two classes. (Alternatively, - you can specify a comma-separated list that includes the parent package - of each class.) - - <?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - <context:component-scan base-package="org.example"/> - -</beans> - - - The scanning of classpath packages requires the presence of - corresponding directory entries in the classpath. When you build JARs - with Ant, make sure that you do not activate the - files-only switch of the JAR task. - - - Furthermore, the - AutowiredAnnotationBeanPostProcessor and - CommonAnnotationBeanPostProcessor are - both included implicitly when you use the component-scan element. That - means that the two components are autodetected and - wired together - all without any bean configuration metadata provided in - XML. - - - You can disable the registration of - AutowiredAnnotationBeanPostProcessor - and CommonAnnotationBeanPostProcessor - by including the annotation-config attribute with - a value of false. - - - -
- -
- Using filters to customize scanning - - By default, classes annotated with - @Component, - @Repository, - @Service, - @Controller, or a custom annotation that - itself is annotated with @Component are - the only detected candidate components. However, you can modify and - extend this behavior simply by applying custom filters. Add them as - include-filter or - exclude-filter sub-elements of the - component-scan element. Each filter element requires - the type and expression - attributes. The following table describes the filtering options. - - - Filter Types - - - - - - - - - - - Filter Type - - Example Expression - - Description - - - - - - annotation - - org.example.SomeAnnotation - - An annotation to be present at the type level in target - components. - - - - assignable - - org.example.SomeClass - - A class (or interface) that the target components are - assignable to (extend/implement). - - - - aspectj - - org.example..*Service+ - - An AspectJ type expression to be matched by the target - components. - - - - regex - - org\.example\.Default.* - - A regex expression to be matched by the target components - class names. - - - - custom - - org.example.MyTypeFilter - - A custom implementation of the - org.springframework.core.type - .TypeFilter interface. - - - -
- - The following example shows the XML configuration ignoring all - @Repository annotations and using "stub" - repositories instead. - - <beans> - - <context:component-scan base-package="org.example"> - <context:include-filter type="regex" expression=".*Stub.*Repository"/> - <context:exclude-filter type="annotation" - expression="org.springframework.stereotype.Repository"/> - </context:component-scan> - -</beans> - - - You can also disable the default filters by providing - use-default-filters="false" as an attribute of - the <component-scan/> element. This will in effect disable - automatic detection of classes annotated with - @Component, - @Repository, - @Service, or - @Controller. - -
- -
- Defining bean metadata within components - - Spring components can also contribute bean definition metadata to - the container. You do this with the same @Bean - annotation used to define bean metadata within - @Configuration annotated classes. Here is a simple - example: - - @Component -public class FactoryMethodComponent { - - @Bean @Qualifier("public") - public TestBean publicInstance() { - return new TestBean("publicInstance"); - } - - public void doWork() { - // Component method implementation omitted - } -} - - This class is a Spring component that has application-specific - code contained in its doWork() method. However, - it also contributes a bean definition that has a factory 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: - - @Component -public class FactoryMethodComponent { - - private static int i; - - @Bean @Qualifier("public") - public TestBean publicInstance() { - return new TestBean("publicInstance"); - } - - // use of a custom qualifier and autowiring of method parameters - - @Bean @BeanAge(1) - 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(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 property on another bean named - privateInstance. A Spring Expression Language element - defines the value of the property through the notation #{ - <expression> }. For @Value - annotations, an expression resolver is preconfigured to look for bean - names when resolving expression text. - - The @Bean methods in a Spring component are - processed differently than their counterparts inside a Spring - @Configuration class. The difference is that - @Component 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 field within a - @Component classes @Bean method - has standard Java semantics. -
- -
- Naming autodetected components - - When a component is autodetected as part of the scanning process, - its bean name is generated by the - BeanNameGenerator strategy known to that - scanner. By default, any Spring stereotype annotation - (@Component, - @Repository, - @Service, and - @Controller) that contains a - name value will thereby provide that name to the - corresponding bean definition. - - - JSR 330's @Named annotation can be used as a means to both - detect components and to provide them with a name. This behavior is - enabled automatically if you have the JSR 330 JAR on the - classpath. - - - If such an annotation contains no name value or - for any other detected component (such as those discovered by custom - filters), the default bean name generator returns the uncapitalized - non-qualified class name. For example, if the following two components - were detected, the names would be myMovieLister and - movieFinderImpl: - - @Service("myMovieLister") -public class SimpleMovieLister { - // ... -} - - @Repository -public class MovieFinderImpl implements MovieFinder { - // ... -} - - - If you do not want to rely on the default bean-naming strategy, - you can provide a custom bean-naming strategy. First, implement the - BeanNameGenerator - interface, and be sure to include a default no-arg constructor. Then, - provide the fully-qualified class name when configuring the - scanner: - - - <beans> - - <context:component-scan base-package="org.example" - name-generator="org.example.MyNameGenerator" /> - -</beans> - - As a general rule, consider specifying the name with the - annotation whenever other components may be making explicit references - to it. On the other hand, the auto-generated names are adequate whenever - the container is responsible for wiring. -
- -
- Providing a scope for autodetected components - - As with Spring-managed components in general, the default and most - common scope for autodetected components is singleton. However, - sometimes you need other scopes, which Spring 2.5 provides with a new - @Scope annotation. Simply provide the - name of the scope within the annotation: - - @Scope("prototype") -@Repository -public class MovieFinderImpl implements MovieFinder { - // ... -} - - - To provide a custom strategy for scope resolution rather than - relying on the annotation-based approach, implement the ScopeMetadataResolver - interface, and be sure to include a default no-arg constructor. Then, - provide the fully-qualified class name when configuring the - scanner: - - - <beans> - - <context:component-scan base-package="org.example" - scope-resolver="org.example.MyScopeResolver" /> - -</beans> - - When using certain non-singleton scopes, it may be necessary to - generate proxies for the 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: - - <beans> - - <context:component-scan base-package="org.example" - scoped-proxy="interfaces" /> - -</beans> -
- -
- Providing qualifier metadata with annotations - - The @Qualifier annotation is - discussed in . - The examples in that section demonstrate the use of the - @Qualifier annotation and custom - qualifier annotations to provide fine-grained control when you resolve - autowire candidates. Because those examples were based on XML bean - definitions, the qualifier metadata was provided on the candidate bean - definitions using the qualifier or - meta sub-elements of the bean - element in the XML. When relying upon classpath scanning for - autodetection of components, you provide the qualifier metadata with - type-level annotations on the candidate class. The following three - examples demonstrate this technique: - - @Component -@Qualifier("Action") -public class ActionMovieCatalog implements MovieCatalog { - // ... -} - - @Component -@Genre("Action") -public class ActionMovieCatalog implements MovieCatalog { - // ... -} - - @Component -@Offline -public class CachingMovieCatalog implements MovieCatalog { - // ... -} - - - As with most annotation-based alternatives, keep in mind that - the annotation metadata is bound to the class definition itself, while - the use of XML allows for multiple beans of the same - type to provide variations in their qualifier metadata, - because that metadata is provided per-instance rather than - per-class. - -
-
- -
- Java-based container configuration - -
- Basic concepts: <literal>@Configuration</literal> and - <literal>@Bean</literal> - - The central artifact in Spring's new Java-configuration support is - the @Configuration-annotated class. These - classes consist principally of - @Bean-annotated methods that define - instantiation, configuration, and initialization logic for objects to be - managed by the Spring IoC container. - - Annotating a class with the - @Configuration indicates that the class - can be used by the Spring IoC container as a source of bean definitions. - The simplest possible @Configuration - class would read as follows: @Configuration -public class AppConfig { - @Bean - public MyService myService() { - return new MyServiceImpl(); - } -} - - For those more familiar with Spring - <beans/> XML, the AppConfig - class above would be equivalent to: <beans> - <bean id="myService" class="com.acme.services.MyServiceImpl"/> -</beans> As you can see, the @Bean - annotation plays the same role as the <bean/> - element. The @Bean annotation 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. -
- -
- Instantiating the Spring container using - <literal>AnnotationConfigApplicationContext</literal> - - The sections below document Spring's - AnnotationConfigApplicationContext, new in Spring - 3.0. This versatile ApplicationContext implementation - is capable of accepting not only @Configuration - classes as input, but also plain @Component classes - and classes annotated with JSR-330 metadata. - - When @Configuration classes are provided as - input, the @Configuration class itself is registered - as a bean definition, and all declared @Bean methods - within the class are also registered as bean definitions. - - When @Component and JSR-330 classes are - provided, they are registered as bean definitions, and it is assumed - that DI metadata such as @Autowired or - @Inject are used within those classes where - necessary. - -
- Simple construction - - In much the same way that Spring XML files are used as input - when instantiating a - ClassPathXmlApplicationContext, - @Configuration classes may be used as input when - instantiating an - AnnotationConfigApplicationContext. This allows for - completely XML-free usage of the Spring container: 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: 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 dependency injection annotations such as - @Autowired. -
- -
- Building the container programmatically using - <literal>register(Class<?>...)</literal> - - An AnnotationConfigApplicationContext may be - instantiated using a no-arg constructor and then configured using the - register() method. This approach is particularly - useful when programmatically building an - AnnotationConfigApplicationContext. 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(); -} -
- -
- Enabling component scanning with - <literal>scan(String...)</literal> - - Experienced Spring users will be familiar with the following - commonly-used XML declaration from Spring's - context: namespace <beans> - <context:component-scan base-package="com.acme"/> -</beans> In the example above, the - com.acme package will be scanned, looking for any - @Component-annotated classes, and those classes - will be registered as Spring bean definitions within the container. - AnnotationConfigApplicationContext exposes the - scan(String...) method to allow for the same - component-scanning functionality:public static void main(String[] args) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.scan("com.acme"); - ctx.refresh(); - MyService myService = ctx.getBean(MyService.class); -} - - - 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. - -
- -
- Support for web applications with - <literal>AnnotationConfigWebApplicationContext</literal> - - A WebApplicationContext variant of - AnnotationConfigApplicationContext is available - with AnnotationConfigWebApplicationContext. This - implementation may be used when configuring the Spring - ContextLoaderListener servlet listener, Spring MVC - DispatcherServlet, etc. What follows is a - web.xml snippet that configures a typical Spring - MVC web application. Note the use of the - contextClass context-param and init-param: - -<web-app> - <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext - instead of the default XmlWebApplicationContext --> - <context-param> - <param-name>contextClass</param-name> - <param-value> - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - </param-value> - </context-param> - - <!-- Configuration locations must consist of one or more comma- or space-delimited - fully-qualified @Configuration classes. Fully-qualified packages may also be - specified for component-scanning --> - <context-param> - <param-name>contextConfigLocation</param-name> - <param-value>com.acme.AppConfig</param-value> - </context-param> - - <!-- Bootstrap the root application context as usual using ContextLoaderListener --> - <listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> - </listener> - - <!-- Declare a Spring MVC DispatcherServlet as usual --> - <servlet> - <servlet-name>dispatcher</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext - instead of the default XmlWebApplicationContext --> - <init-param> - <param-name>contextClass</param-name> - <param-value> - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - </param-value> - </init-param> - <!-- Again, config locations must consist of one or more comma- or space-delimited - and fully-qualified @Configuration classes --> - <init-param> - <param-name>contextConfigLocation</param-name> - <param-value>com.acme.web.MvcConfig</param-value> - </init-param> - </servlet> - - <!-- map all requests for /main/* to the dispatcher servlet --> - <servlet-mapping> - <servlet-name>dispatcher</servlet-name> - <url-pattern>/main/*</url-pattern> - </servlet-mapping> -</web-app> -
-
- -
- Composing Java-based configurations - -
- Using the <literal>@Import</literal> annotation - - Much as the <import/> element is used - within Spring XML files to aid in modularizing configurations, the - @Import annotation allows for loading - @Bean definitions from another configuration - class:@Configuration -public class ConfigA { - public @Bean A a() { return new A(); } -} - -@Configuration -@Import(ConfigA.class) -public class ConfigB { - public @Bean 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: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); -} 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. - -
- Injecting dependencies on imported <literal>@Bean</literal> - definitions - - The example above works, but is simplistic. In most practical - scenarios, beans will have dependencies on one another across - configuration classes. When using XML, this is not an issue, per se, - because there is no compiler involved, and one can simply declare - ref="someBean" and trust that Spring will work it - out during container initialization. Of course, when using - @Configuration classes, the Java compiler places - constraints on the configuration model, in that references to other - beans must be valid Java syntax. - - Fortunately, solving this problem is simple. Remember that - @Configuration classes are ultimately just - another bean in the container - this means that they can take - advantage 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:@Configuration -public class ServiceConfig { - private @Autowired AccountRepository accountRepository; - - public @Bean TransferService transferService() { - return new TransferServiceImpl(accountRepository); - } -} - -@Configuration -public class RepositoryConfig { - private @Autowired DataSource dataSource; - - public @Bean AccountRepository accountRepository() { - return new JdbcAccountRepository(dataSource); - } -} - -@Configuration -@Import({ServiceConfig.class, RepositoryConfig.class}) -public class SystemTestConfig { - public @Bean 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"); -} - -
- Fully-qualifying imported beans for ease of - navigation - - In the scenario above, using @Autowired - works well and provides the desired modularity, but determining - exactly where the autowired bean definitions are declared is still - somewhat ambiguous. For example, as a developer looking at - ServiceConfig, how do you know exactly where - the @Autowired AccountRepository bean is - declared? It's not explicit in the code, and this may be just - fine. Remember that the SpringSource Tool - Suite provides tooling that can render graphs showing how - everything is wired up - that may be all you need. Also, your Java - IDE can easily find all declarations and uses of the - AccountRepository type, and will quickly show - you the location of @Bean methods that return - that type. - - In cases where this ambiguity is not acceptable and you wish - to have direct navigation from within your IDE from one - @Configuration class to another, consider - autowiring the configuration classes themselves: @Configuration -public class ServiceConfig { - private @Autowired RepositoryConfig repositoryConfig; - - public @Bean 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: @Configuration -public class ServiceConfig { - private @Autowired RepositoryConfig repositoryConfig; - - public @Bean TransferService transferService() { - return new TransferServiceImpl(repositoryConfig.accountRepository()); - } -} - -@Configuration -public interface RepositoryConfig { - @Bean AccountRepository accountRepository(); -} - -@Configuration -public class DefaultRepositoryConfig implements RepositoryConfig { - public @Bean AccountRepository accountRepository() { - return new JdbcAccountRepository(...); - } -} - -@Configuration -@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config! -public class SystemTestConfig { - public @Bean 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 - DefaultRepositoryConfig, and built-in IDE - tooling is still useful: it will be easy for the developer to get - a type hierarchy of RepositoryConfig - implementations. In this way, navigating - @Configuration classes and their dependencies - becomes no different than the usual process of navigating - interface-based code. -
-
-
- -
- Combining Java and XML configuration - - Spring's @Configuration class support does - not aim to be a 100% complete replacement for Spring XML. Some - facilities such as Spring XML namespaces remain an ideal way to - configure the container. In cases where XML is convenient or - necessary, you have a choice: either instantiate the container in an - "XML-centric" way using, for example, - ClassPathXmlApplicationContext, or in a - "Java-centric" fashion using - AnnotationConfigApplicationContext and the - @ImportResource annotation to import XML as - needed. - -
- XML-centric use of <literal>@Configuration</literal> - classes - - It may be preferable to bootstrap the Spring container from - XML and include @Configuration classes in an - ad-hoc fashion. For example, in a large existing codebase that uses - Spring XML, it will be easier to create - @Configuration classes on an as-needed basis and - include them from the existing XML files. Below you'll find the - options for using @Configuration classes in this - kind of "XML-centric" situation. - -
- Declaring <literal>@Configuration</literal> classes as - plain Spring <literal><bean/></literal> elements - - Remember that @Configuration classes are - ultimately just bean definitions in the container. In this - example, we create a @Configuration class named - AppConfig and include it within - system-test-config.xml as a - <bean/>definition. Because - <context:annotation-config/> is switched - on, the container will recognize the - @Configuration annotation, and process the - @Bean methods declared in - AppConfig properly.@Configuration -public class AppConfig { - private @Autowired DataSource dataSource; - - public @Bean AccountRepository accountRepository() { - return new JdbcAccountRepository(dataSource); - } - - public @Bean TransferService transferService() { - return new TransferService(accountRepository()); - } -} system-test-config.xml -<beans> - <!-- enable processing of annotations such as @Autowired and @Configuration --> - <context:annotation-config/> - <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> - - <bean class="com.acme.AppConfig"/> - - <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> - <property name="url" value="${jdbc.url}"/> - <property name="username" value="${jdbc.username}"/> - <property name="password" value="${jdbc.password}"/> - </bean> -</beans> jdbc.properties -jdbc.url=jdbc:hsqldb:hsql://localhost/xdb -jdbc.username=sa -jdbc.password= public static void main(String[] args) { - ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); - TransferService transferService = ctx.getBean(TransferService.class); - // ... -} - - - In system-test-config.xml above, the - AppConfig<bean/> does not declare an - id element. While it would be acceptable to - do so, it is unnecessary given that no other bean will ever - refer to it, and it is unlikely that it will be explicitly - fetched from the container by name. Likewise with the - DataSource bean - it is only ever autowired - by type, so an explicit bean id is not strictly required. - -
- -
- Using <literal><context:component-scan/></literal> to - pick up <literal>@Configuration</literal> classes - - Because @Configuration is meta-annotated - with @Component, - @Configuration-annotated classes are - automatically candidates for component scanning. Using the same - scenario as above, we can redefine - system-test-config.xml to take advantage of - component-scanning. Note that in this case, we don't need to - explicitly declare - <context:annotation-config/>, because - <context:component-scan/> enables all the - same functionality.system-test-config.xml -<beans> - <!-- picks up and registers AppConfig as a bean definition --> - <context:component-scan base-package="com.acme"/> - <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> - - <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> - <property name="url" value="${jdbc.url}"/> - <property name="username" value="${jdbc.username}"/> - <property name="password" value="${jdbc.password}"/> - </bean> -</beans> -
-
- -
- <literal>@Configuration</literal> class-centric use of XML - with <literal>@ImportResource</literal> - - 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 - scenarios, simply use @ImportResource and define - only as much XML as is needed. Doing so achieves a "Java-centric" - approach to configuring the container and keeps XML to a bare - minimum. @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; - - public @Bean DataSource dataSource() { - return new DriverManagerDataSource(url, username, password); - } -} properties-config.xml -<beans> - <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> -</beans> jdbc.properties -jdbc.url=jdbc:hsqldb:hsql://localhost/xdb -jdbc.username=sa -jdbc.password= public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); - TransferService transferService = ctx.getBean(TransferService.class); - // ... -} -
-
-
- -
- Using the <interfacename>@Bean</interfacename> annotation - - @Bean is a method-level annotation - and a direct analog of the XML <bean/> element. The - annotation supports some of the attributes offered by - <bean/>, such as: init-method, - destroy-method, - autowiring - and name. - - You can use the @Bean annotation in - a @Configuration-annotated or in a - @Component-annotated class. - -
- Declaring a bean - - To declare a bean, simply annotate a method with the - @Bean annotation. You use this 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: - @Configuration -public class AppConfig { - - @Bean - public TransferService transferService() { - return new TransferServiceImpl(); - } - -} - - The preceding configuration is exactly equivalent to the - following Spring XML: <beans> - <bean id="transferService" class="com.acme.TransferServiceImpl"/> -</beans> - - Both declarations make a bean named transferService - available in the ApplicationContext, bound to an object - instance of type TransferServiceImpl: -transferService -> com.acme.TransferServiceImpl - -
- -
- Injecting dependencies - - When @Beans have dependencies on - one another, expressing that dependency is as simple as having one - bean method call another: @Configuration -public class AppConfig { - - @Bean - public Foo foo() { - return new Foo(bar()); - } - - @Bean - public Bar bar() { - return new Bar(); - } - -} - - In the example above, the foo bean receives a - reference to bar via constructor injection. -
- -
- Receiving lifecycle callbacks - - Beans declared in a - @Configuration-annotated class support - the regular lifecycle callbacks. Any classes defined with the - @Bean annotation can use the - @PostConstruct and @PreDestroy - annotations from JSR-250, see JSR-250 - annotations for further details. - - The regular Spring lifecycle callbacks are fully - supported as well. If a bean implements InitializingBean, - DisposableBean, or Lifecycle, their - respective methods are called by the container. - - The standard set of *Aware interfaces such as - BeanFactoryAware, - BeanNameAware, - MessageSourceAware, - ApplicationContextAware, - and so on are also fully supported. - - The @Bean annotation supports - specifying arbitrary initialization and destruction callback methods, - much like Spring XML's init-method and - destroy-method attributes on the bean - element: public class Foo { - public void init() { - // initialization 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(); - } -} - - - Of course, in the case of Foo above, it would be - equally as valid to call the init() method directly - during construction: @Configuration -public class AppConfig { - @Bean - public Foo foo() { - Foo foo = new Foo(); - foo.init(); - return foo; - } - - // ... -} - - - When you work directly in Java, you can do anything you like - with your objects and do not always need to rely on the container - lifecycle! - -
- -
- Specifying bean scope - -
- Using the <interfacename>@Scope</interfacename> - annotation - - - - You can specify that your beans defined with the - @Bean annotation should have a - specific scope. You can use any of the standard scopes specified in - the Bean Scopes - section. - - The default scope is singleton, but you can - override this with the @Scope - annotation: @Configuration -public class MyConfiguration { - @Bean - @Scope("prototype") - public Encryptor encryptor() { - // ... - } -} -
- -
- <code>@Scope and scoped-proxy</code> - - Spring offers a convenient way of working with scoped - dependencies through scoped - proxies. The easiest way to create such a proxy when using - the XML configuration is the <aop:scoped-proxy/> - element. Configuring your beans in Java with a @Scope annotation - offers equivalent support with the proxyMode attribute. The default - is no proxy (ScopedProxyMode.NO), but you can - 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: // 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; -} -
- -
- Lookup method injection - - As noted earlier, lookup method - injection is an 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. 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(); - } - - // 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: @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(); - } - } -} -
-
- -
- Customizing bean naming - - 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. @Configuration -public class AppConfig { - - @Bean(name = "myFoo") - public Foo foo() { - return new Foo(); - } - -} -
- - - - -
- Bean aliasing - - As discussed in , it is - sometimes desirable to give a single bean multiple names, otherwise - known as bean aliasing. The - name attribute of the @Bean - annotation accepts a String array for this purpose. @Configuration -public class AppConfig { - - @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" }) - public DataSource dataSource() { - // instantiate, configure and return DataSource bean... - } - -} -
-
- -
- Further information about how Java-based configuration works internally - - The following example shows a @Bean annotated method being called twice: - - -@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 ClientDao clientDao() { - return new ClientDaoImpl(); - } -} - - - clientDao() has been called once in clientService1() and once in - clientService2(). - Since this method creates a new instance of ClientDaoImpl and returns it, you would normally expect having 2 instances - (one for each service). - That definitely would be problematic: in Spring, instantiated beans have a singleton scope by default. - This is where the magic comes in: - All @Configuration classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any - cached (scoped) beans before it calls the parent method and creates a new instance. - - - - The behavior could be different according to the scope - of your bean. We are talking about singletons here. - - - - - Beware that, in order for JavaConfig to work, you must include the CGLIB jar in your list of dependencies. - - - - - There are a few restrictions due to the fact that CGLIB dynamically adds features at startup-time: - - - Configuration classes should not be final - - - They should have a constructor with no arguments - - - - - -
-
+
Registering a <interfacename>LoadTimeWeaver</interfacename> The context namespace introduced in Spring 2.5 - provides a load-time-weaver element. + provides a load-time-weaver + element. <beans> @@ -6664,758 +959,88 @@ public class AppConfig { </beans> Adding this element to an XML-based Spring configuration file - activates a Spring LoadTimeWeaver for the - ApplicationContext. Any bean within that - ApplicationContext may implement - LoadTimeWeaverAware, thereby receiving a - reference to the load-time weaver instance. This is particularly useful in - combination with Spring's JPA support where - load-time weaving may be necessary for JPA class transformation. Consult - the LocalContainerEntityManagerFactoryBean Javadoc - for more detail. For more on AspectJ load-time weaving, see . + activates a Spring LoadTimeWeaver for the + ApplicationContext. Any bean within that + ApplicationContext may implement + LoadTimeWeaverAware, thereby receiving a + reference to the load-time weaver instance. This is particularly useful in + combination with Spring's JPA support where + load-time weaving may be necessary for JPA class transformation. Consult + the LocalContainerEntityManagerFactoryBean Javadoc + for more detail. For more on AspectJ load-time weaving, see .
-
- Additional Capabilities of the - <interfacename>ApplicationContext</interfacename> - - - - 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 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 - declarative fashion, not even creating it programmatically, but instead - relying on support classes such as ContextLoader to - automatically instantiate an - ApplicationContext as part of the normal - startup process of a J2EE web application. - - To enhance BeanFactory functionality - in a more framework-oriented style the context package also provides the - following functionality: - - - - Access to messages in i18n-style, through - the MessageSource interface. - - - - Access to resources, such as URLs and - files, through the ResourceLoader - interface. - - - - Event publication to beans implementing the - ApplicationListener interface, through - the use of the - ApplicationEventPublisher - interface. - - - - Loading of multiple (hierarchical) - contexts, allowing each to be focused on one particular - layer, such as the web layer of an application, through the - HierarchicalBeanFactory - interface. - - - -
- Internationalization using - <interfacename>MessageSource</interfacename> - - - - The ApplicationContext interface - extends an interface called - MessageSource, and therefore provides - internationalization (i18n) functionality. Spring also provides the - interface HierarchicalMessageSource, which can - resolve messages hierarchically. Together these interfaces provide the - foundation upon which Spring effects message resolution. The methods - defined on these interfaces include: - - - - String getMessage(String code, Object[] args, - String default, Locale loc): The basic method used to - retrieve a message from the - MessageSource. When no message is - found for the specified locale, the default message is used. Any - arguments passed in become replacement values, using the - MessageFormat functionality provided - by the standard library. - - - - String getMessage(String code, Object[] args, - Locale loc): Essentially the same as the previous - method, but with one difference: no default message can be - specified; if the message cannot be found, a - NoSuchMessageException is thrown. - - - - String getMessage(MessageSourceResolvable - resolvable, Locale locale): All properties used in the - preceding methods are also wrapped in a class named - MessageSourceResolvable, which you - can use with this method. - - - - When an ApplicationContext is - loaded, it automatically searches for a - MessageSource bean defined in the - context. The bean must have the name messageSource. - If such a bean is found, all calls to the preceding methods are - delegated to the message source. If no message source is found, the - ApplicationContext attempts to find a - parent containing a bean with the same name. If it does, it uses that - bean as the MessageSource. If the - ApplicationContext cannot find any source - for messages, an empty DelegatingMessageSource is - instantiated in order to be able to accept calls to the methods defined - above. - - Spring provides two MessageSource - implementations, ResourceBundleMessageSource and - StaticMessageSource. Both implement - HierarchicalMessageSource in order to do - nested messaging. The StaticMessageSource is - rarely used but provides programmatic ways to add messages to the - source. The ResourceBundleMessageSource is shown - in the following example: - - <beans> - <bean id="messageSource" - class="org.springframework.context.support.ResourceBundleMessageSource"> - <property name="basenames"> - <list> - <value>format</value> - <value>exceptions</value> - <value>windows</value> - </list> - </property> - </bean> -</beans> - - In the example it is assumed you have three resource bundles - defined in your classpath called format, - exceptions and windows. Any - request to resolve a message will be handled in the JDK standard way of - resolving messages through ResourceBundles. For the purposes of the - example, assume the contents of two of the above resource bundle files - are... - - # in format.properties -message=Alligators rock! - - # 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. - - 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... - - Alligators rock! - - So to summarize, the MessageSource is - defined in a file called beans.xml, which exists at - the root of your classpath. The messageSource bean - definition refers to a number of resource bundles through its - basenames property. The three files that are passed - in the list to the basenames property exist as files - at the root of your classpath and are called - format.properties, - exceptions.properties, and - windows.properties respectively. - - 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. - - <beans> - - <!-- this MessageSource is being used in a web application --> - <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> - <property name="basename" value="test-messages"/> - </bean> - - <!-- lets inject the above MessageSource into this POJO --> - <bean id="example" class="com.foo.Example"> - <property name="messages" ref="messageSource"/> - </bean> - -</beans> - - public class Example { - - private MessageSource 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); - } - -} - - The resulting output from the invocation of the - execute() method will be... - - 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 would create - files called format_en_GB.properties, - exceptions_en_GB.properties, and - windows_en_GB.properties respectively. - - 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. - - # in exceptions_en_GB.properties -argument.required=Ebagum lad, the '{0}' argument is required, I say, required. - - 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... - - Ebagum lad, the 'userDao' argument is required, I say, required. - - You can also use the MessageSourceAware - interface to acquire a reference to any - MessageSource that has been defined. Any bean - that is defined in an ApplicationContext that - implements the MessageSourceAware interface is - injected with the application context's - MessageSource when the bean is created and - configured. - - - As an alternative to - ResourceBundleMessageSource, Spring provides a - ReloadableResourceBundleMessageSource class. - This variant supports the same bundle file format but is more flexible - than the standard JDK based - ResourceBundleMessageSource - implementation. In particular, it allows for reading files - from any Spring resource location (not just from the classpath) and - supports hot reloading of bundle property files (while efficiently - caching them in between). Check out the - ReloadableResourceBundleMessageSource javadoc - for details. - -
- -
- Standard and Custom Events - - Event handling in the - ApplicationContext is provided through - the ApplicationEvent class and - ApplicationListener interface. If a bean - that implements the ApplicationListener - interface is deployed into the context, every time an - ApplicationEvent gets published to the - ApplicationContext, that bean is - notified. Essentially, this is the standard - Observer design pattern. Spring provides the - following standard events: - - - Built-in Events - - - - - - - - - Event - - Explanation - - - - - - ContextRefreshedEvent - - Published when the - ApplicationContext is initialized - or refreshed, for example, using the - refresh() method on the - ConfigurableApplicationContext - interface. "Initialized" here means that all beans are loaded, - post-processor beans are detected and activated, singletons are - pre-instantiated, and the - ApplicationContext object is - ready for use. As long as the context has not been closed, a - refresh can be triggered multiple times, provided that the - chosen ApplicationContext - actually supports such "hot" refreshes. For example, - XmlWebApplicationContext supports hot - refreshes, but GenericApplicationContext - does not. - - - - ContextStartedEvent - - Published when the - ApplicationContext is started, - using the start() method on the - ConfigurableApplicationContext - interface. "Started" here means that all - Lifecycle beans receive an - explicit start signal. Typically this signal is used to restart - beans after an explicit stop, but it may also be used to start - components that have not been configured for autostart , for - example, components that have not already started on - initialization. - - - - ContextStoppedEvent - - Published when the - ApplicationContext is stopped, - using the stop() method on the - ConfigurableApplicationContext - interface. "Stopped" here means that all - Lifecycle beans receive an - explicit stop signal. A stopped context may be restarted through - a start() call. - - - - ContextClosedEvent - - Published when the - ApplicationContext is closed, - using the close() method on the - ConfigurableApplicationContext - interface. "Closed" here means that all singleton beans are - destroyed. A closed context reaches its end of life; it cannot - be refreshed or restarted. - - - - 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 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: - - public class BlackListEvent extends ApplicationEvent { - private final String address; - private final String test; - - 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 - ApplicationEventPublisher. Typically this - is done by creating a class that implements - ApplicationEventPublisherAware and - registering it as a Spring bean. The following example demonstrates such a - class: - - blackList; - private ApplicationEventPublisher publisher; - - public void setBlackList(List blackList) { - this.blackList = blackList; - } - - 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... - - At configuration time, the Spring container will detect that - EmailService implements - ApplicationEventPublisherAware and will - automatically call - setApplicationEventPublisher(). In reality, the - parameter passed in will be the Spring container itself; you're simply - interacting with the application context via its - ApplicationEventPublisher - interface. - - 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: - - { - - private String notificationAddress; - - public void setNotificationAddress(String notificationAddress) { - this.notificationAddress = notificationAddress; - } - - public void onApplicationEvent(BlackListEvent event) { -]]> // notify appropriate parties via notificationAddress... - - Notice that ApplicationListener is - generically parameterized with the type of your custom event, - BlackListEvent. This means that the - onApplicationEvent() method can remain - type-safe, avoiding any need for downcasting. You may register as many - event listeners as you wish, but note that by default event listeners - receive events synchronously. This means the - publishEvent() method blocks until all - listeners have finished processing the event. One advantage of this - synchronous and single-threaded approach is that when a listener - receives an event, it operates inside the transaction context of the - publisher if a transaction context is available. If another strategy for - event publication becomes necessary, refer to the JavaDoc for Spring's - ApplicationEventMulticaster - interface. - - The following example demonstrates the bean definitions used to - register and configure each of the classes above: - - - - black@list.org - white@list.org - john@doe.org - - - - - - -]]> - - Putting it all together, when the sendEmail() - method of the emailService bean is called, if there - are any emails that should be blacklisted, a custom event of type - BlackListEvent is published. The - blackListNotifier bean is registered as an - ApplicationListener and thus receives the - BlackListEvent, at which point it can notify - appropriate parties. - - - Spring's eventing mechanism is designed for simple communication - between Spring beans within the same application context. However, for - more sophisticated enterprise integration needs, the separately-maintained - Spring Integration - project provides complete support for building lightweight, pattern-oriented, - event-driven architectures that build upon the well-known Spring - programming model. - -
- -
- Convenient access to low-level resources - - For optimal usage and understanding of application contexts, users - should generally familiarize themselves with Spring's - Resource abstraction, as described in the - chapter . - - An application context is a - ResourceLoader, which can be used to load - Resources. A - Resource is essentially a more feature - rich version of the JDK class java.net.URL, in fact, - the implementations of the Resource wrap - an instance of java.net.URL where appropriate. A - Resource can obtain low-level resources - from almost any location in a transparent fashion, including from the - classpath, a filesystem location, anywhere describable with a standard - URL, and some other variations. If the resource location string is a - simple path without any special prefixes, where those resources come - from is specific and appropriate to the actual application context - type. - - You can configure a bean deployed into the application context to - implement the special callback interface, - ResourceLoaderAware, to be automatically - called back at initialization time with the application context itself - passed in as the ResourceLoader. You can - also expose properties of type Resource, - to be used to access static resources; they will be injected into it - like any other properties. You can specify those - Resource properties as simple String - paths, and rely on a special JavaBean - PropertyEditor that is automatically - registered by the context, to convert those text strings to actual - Resource objects when the bean is - deployed. - - The location path or paths supplied to an - ApplicationContext constructor are - actually resource strings, and in simple form are treated appropriately - to the specific context implementation. - ClassPathXmlApplicationContext treats a simple - location path as a classpath location. You can also use location paths - (resource strings) with special prefixes to force loading of definitions - from the classpath or a URL, regardless of the actual context - type. -
- -
- Convenient <interfacename>ApplicationContext</interfacename> - instantiation for web applications - - You can create ApplicationContext - instances declaratively by using, for example, a - ContextLoader. Of course you can also create - ApplicationContext instances - programmatically by using one of the - ApplicationContext - implementations. - - The ContextLoader mechanism comes in two - flavors: the ContextLoaderListener and the - ContextLoaderServlet. They have the same - functionality but differ in that the listener version is not reliable in - Servlet 2.3 containers. In the Servlet 2.4 specification, Servlet - context listeners must execute immediately after the Servlet context for - the web application is created and is available to service the first - request (and also when the Servlet context is about to be shut down). As - such a Servlet context listener is an ideal place to initialize the - Spring ApplicationContext. All things - being equal, you should probably prefer - ContextLoaderListener; for more information on - compatibility, have a look at the Javadoc for the - ContextLoaderServlet. - - You can register an - ApplicationContext using the - ContextLoaderListener as follows: - - <context-param> - <param-name>contextConfigLocation</param-name> - <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value> -</context-param> - -<listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -</listener> - -<!-- or use the ContextLoaderServlet instead of the above listener -<servlet> - <servlet-name>context</servlet-name> - <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> - <load-on-startup>1</load-on-startup> -</servlet> ---> - - The listener inspects the contextConfigLocation - parameter. If the parameter does not exist, the listener uses - /WEB-INF/applicationContext.xml as a default. When - the parameter does exist, the listener separates - the String by using predefined delimiters (comma, semicolon and - whitespace) and uses the values as locations where application contexts - will be searched. Ant-style path patterns are supported as well. - Examples are /WEB-INF/*Context.xml for all files with - names ending with "Context.xml", residing in the "WEB-INF" directory, - and /WEB-INF/**/*Context.xml, for all such files in - any subdirectory of "WEB-INF". - - You can use ContextLoaderServlet instead of - ContextLoaderListener. The Servlet uses the - contextConfigLocation parameter just as the listener - does. -
- -
- 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. - - 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 use application server - resources such as the JTA transaction manager and JNDI-bound JDBC - DataSources and JMS ConnectionFactory instances, and may also register - with the platform's JMX server - all through Spring's standard - transaction management and JNDI 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 SpringContextResourceAdapter - class for the configuration details involved in RAR deployment. - - For a simple deployment of a Spring ApplicationContext - as a J2EE RAR file: package all application classes into a - RAR file, which is a standard JAR file with a different file extension. - Add all required library JARs into the root of the RAR archive. Add a - "META-INF/ra.xml" deployment descriptor (as shown in - SpringContextResourceAdapters JavaDoc) and the - corresponding Spring XML bean definition file(s) (typically - "META-INF/applicationContext.xml"), and drop the resulting RAR file into - your application server's deployment directory. - - - Such RAR deployment units are usually self-contained; they do - not expose components to the outside world, not even to other modules - of the same application. Interaction with a RAR-based - ApplicationContext usually occurs through JMS destinations that it - shares with other modules. A RAR-based ApplicationContext may also, - for example, schedule some jobs, reacting to new files in the file - system (or the like). If it needs to allow synchronous access from the - outside, it could for example export RMI endpoints, which of course - may be used by other application modules on the same machine. - -
-
+
The BeanFactory The BeanFactory provides the underlying basis - for Spring's IoC functionality but it is only used directly in integration - with other third-party frameworks and is now largely historical in nature - for most users of Spring. The BeanFactory and - related interfaces, such as BeanFactoryAware, - InitializingBean, - DisposableBean, are still present in Spring for the - purposes of backward compatibility with the large number of third-party - frameworks that integrate with Spring. Often third-party components that - can not use more modern equivalents such as @PostConstruct or - @PreDestroy in order to remain compatible with JDK 1.4 or to - avoid a dependency on JSR-250. + for Spring's IoC functionality but it is only used directly in integration + with other third-party frameworks and is now largely historical in nature + for most users of Spring. The BeanFactory and + related interfaces, such as BeanFactoryAware, + InitializingBean, + DisposableBean, are still present in Spring for the + purposes of backward compatibility with the large number of third-party + frameworks that integrate with Spring. Often third-party components that + can not use more modern equivalents such as @PostConstruct or + @PreDestroy in order to remain compatible with JDK 1.4 or to + avoid a dependency on JSR-250. This section provides additional background into the differences - between the BeanFactory and - ApplicationContext and how one might access - the IoC container directly through a classic singleton lookup. + between the BeanFactory and + ApplicationContext and how one might access + the IoC container directly through a classic singleton lookup.
<interfacename>BeanFactory</interfacename> or - <interfacename>ApplicationContext</interfacename>? + ApplicationContext? - Use an ApplicationContext unless - you have a good reason for not doing so. + Use an ApplicationContext unless you + have a good reason for not doing so. Because the ApplicationContext - includes all functionality of the - BeanFactory, it is 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 use of the BeanPostProcessor - extension point (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 extra steps on your part. This situation could be confusing - because nothing is actually wrong with the configuration. + includes all functionality of the + BeanFactory, it is 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 use of the BeanPostProcessor extension point + (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 extra steps on your part. This situation could be confusing because + nothing is actually wrong with the configuration. The following table lists features provided by the - BeanFactory and - ApplicationContext interfaces and - implementations. + BeanFactory and + ApplicationContext interfaces and + implementations. + pgwide="1"> Feature Matrix - + Feature - BeanFactory + BeanFactory - ApplicationContext + ApplicationContext @@ -7430,8 +1055,8 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.Automatic - BeanPostProcessor - registration + BeanPostProcessor + registrationNo @@ -7440,8 +1065,8 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.Automatic - BeanFactoryPostProcessor - registration + BeanFactoryPostProcessor + registrationNo @@ -7450,8 +1075,8 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.Convenient - MessageSource access (for - i18n) + MessageSource access (for + i18n)No @@ -7460,7 +1085,7 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.ApplicationEvent - publication + publicationNo @@ -7471,11 +1096,11 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.To explicitly register a bean post-processor with a - BeanFactory implementation, you must - write code like this: + BeanFactory implementation, you must + write code like this:ConfigurableBeanFactory factory = new XmlBeanFactory(...); - + // now register any needed BeanPostProcessor instances MyBeanPostProcessor postProcessor = new MyBeanPostProcessor(); factory.addBeanPostProcessor(postProcessor); @@ -7483,9 +1108,9 @@ factory.addBeanPostProcessor(postProcessor); // now start using the factoryTo explicitly register a - BeanFactoryPostProcessor when using a - BeanFactory implementation, you must - write code like this: + BeanFactoryPostProcessor when using a + BeanFactory implementation, you must + write code like this:XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml")); @@ -7496,54 +1121,55 @@ cfg.setLocation(new FileSystemResource("jdbc.properties")); // now actually do the replacement cfg.postProcessBeanFactory(factory); - In both cases, the explicit registration step is inconvenient, - which is one reason why the various - ApplicationContext implementations are - preferred above plain BeanFactory - implementations in the vast majority of Spring-backed applications, - especially when using BeanFactoryPostProcessors and - BeanPostProcessors. These mechanisms implement - important functionality such as property placeholder replacement and - AOP. + In both cases, the explicit registration step is inconvenient, which + is one reason why the various + ApplicationContext implementations are + preferred above plain BeanFactory + implementations in the vast majority of Spring-backed applications, + especially when using BeanFactoryPostProcessors and + BeanPostProcessors. These mechanisms implement + important functionality such as property placeholder replacement and + AOP.
Glue code and the evil singleton - It is best to write most application code in a - dependency-injection (DI) style, where that code is served out of a - Spring IoC container, has its own dependencies supplied by the container - when it is created, and is completely unaware of the container. However, - for the small glue layers of code that are sometimes needed to tie other - code together, you sometimes need a singleton (or quasi-singleton) style - access to a Spring IoC container. For example, third-party code may try - to construct new objects directly (Class.forName() - style), without the ability to get these objects out of a Spring IoC - container. If - the object constructed by the third-party code is a small stub or proxy, - which then uses a singleton style access to a Spring IoC container to - get a real object to delegate to, then inversion of control has still - been achieved for the majority of the code (the object coming out of the - container). Thus most code is still unaware of the container or how it - is accessed, and remains decoupled from other code, with all ensuing - benefits. EJBs may also use this stub/proxy approach to delegate to a - plain Java implementation object, retrieved from a Spring IoC container. - While the Spring IoC container itself ideally does not have to be a - singleton, it may be unrealistic in terms of memory usage or - initialization times (when using beans in the Spring IoC container such - as a Hibernate SessionFactory) for each - bean to use its own, non-singleton Spring IoC container. + It is best to write most application code in a dependency-injection + (DI) style, where that code is served out of a Spring IoC container, has + its own dependencies supplied by the container when it is created, and + is completely unaware of the container. However, for the small glue + layers of code that are sometimes needed to tie other code together, you + sometimes need a singleton (or quasi-singleton) style access to a Spring + IoC container. For example, third-party code may try to construct new + objects directly (Class.forName() style), without the + ability to get these objects out of a Spring IoC container. + If + the object constructed by the third-party code is a small stub or proxy, + which then uses a singleton style access to a Spring IoC container to + get a real object to delegate to, then inversion of control has still + been achieved for the majority of the code (the object coming out of the + container). Thus most code is still unaware of the container or how it + is accessed, and remains decoupled from other code, with all ensuing + benefits. EJBs may also use this stub/proxy approach to delegate to a + plain Java implementation object, retrieved from a Spring IoC container. + While the Spring IoC container itself ideally does not have to be a + singleton, it may be unrealistic in terms of memory usage or + initialization times (when using beans in the Spring IoC container such + as a Hibernate SessionFactory) for each + bean to use its own, non-singleton Spring IoC container. Looking up the application context in a service locator style is - sometimes the only 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 - ContextSingletonBeanFactoryLocator - locator that is described in this SpringSource - team blog entry. + sometimes the only 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 + ContextSingletonBeanFactoryLocator + locator that is described in this SpringSource team blog entry.