From c2f4f97fa5b6f2a5d4b9214151151f52ed163afe Mon Sep 17 00:00:00 2001 From: Mark Pollack Date: Mon, 27 Apr 2009 05:37:45 +0000 Subject: [PATCH] Update docs to use of @Bean inside a @Component --- spring-framework-reference/src/beans.xml | 734 ++++++++++---------- spring-framework-reference/src/new-in-3.xml | 59 +- spring-framework-reference/src/rest.xml | 6 +- 3 files changed, 420 insertions(+), 379 deletions(-) diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml index 349588080f8..7b5bddb6eab 100644 --- a/spring-framework-reference/src/beans.xml +++ b/spring-framework-reference/src/beans.xml @@ -1,7 +1,6 @@ - +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> The IoC container @@ -206,23 +205,23 @@ Find below an example of the basic structure of XML-based configuration metadata. - -<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - - - + <bean id="..." class="..."> + <!-- collaborators and configuration for this bean go here --> + </bean> - - - + <bean id="..." class="..."> + <!-- collaborators and configuration for this bean go here --> + </bean> - + <!-- more bean definitions go here --> -]]> +</beans> @@ -255,16 +254,16 @@ BeanFactory factory = context; load bean definitions from another file (or files). Let's look at a sample: - + <beans> - - - + <import resource="services.xml"/> + <import resource="resources/messageSource.xml"/> + <import resource="/resources/themeSource.xml"/> - - + <bean id="bean1" class="..."/> + <bean id="bean2" class="..."/> -]]> +</beans> In this example, external bean definitions are being loaded from 3 files, services.xml, @@ -519,7 +518,7 @@ BeanFactory factory = context; XML-based configuration metadata this may be accomplished via the use of the <alias/> element. - ]]> + <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 @@ -535,8 +534,8 @@ BeanFactory factory = context; easily handled by adding to the MyApp XML fragment the following standalone aliases: - -]]> + <alias name="componentA-dataSource" alias="componentB-dataSource"/> +<alias name="componentA-dataSource" alias="myApp-dataSource" /> Now each component and the main application can refer to the dataSource via a name that is unique and guaranteed not to clash @@ -623,9 +622,9 @@ BeanFactory factory = context; When using XML-based configuration metadata you can specify your bean class like so: - + <bean id="exampleBean" class="examples.ExampleBean"/> -]]> +<bean name="anotherExample" class="examples.ExampleBeanTwo"/> The mechanism for supplying arguments to the constructor (if required), or setting properties of the object instance after it has @@ -655,9 +654,9 @@ BeanFactory factory = context; this example, the createInstance() method must be a static method. - <bean id="exampleBean" class="examples.ExampleBean2" - factory-method="createInstance"/>]]> + factory-method="createInstance"/> The mechanism for supplying (optional) arguments to the factory method, or setting properties of the object instance after @@ -725,8 +724,8 @@ BeanFactory factory = context; BeanFactory you would create one and read in some bean definitions in the XML format as follows: - + Resource res = new FileSystemResource("beans.xml"); +BeanFactory factory = new XmlBeanFactory(res); Basically that is all there is to it. Using getBean(String) you can retrieve instances of @@ -831,16 +830,16 @@ public class Foo { specify the constructor argument indexes and / or types explicitly. - - - - - - - - - -]]> + <beans> + <bean name="foo" class="x.y.Foo"> + <constructor-arg> + <bean class="x.y.Bar"/> + </constructor-arg> + <constructor-arg> + <bean class="x.y.Baz"/> + </constructor-arg> + </bean> +</beans> When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). @@ -873,10 +872,10 @@ public class ExampleBean { 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>
@@ -886,10 +885,10 @@ public class ExampleBean { explicitly by use of the index attribute. For example: - - - -]]> + <bean id="exampleBean" class="examples.ExampleBean"> + <constructor-arg index="0" value="7500000"/> + <constructor-arg index="1" value="42"/> +</bean> As well as solving the ambiguity problem of multiple simple values, specifying an index also solves the problem of ambiguity @@ -1100,7 +1099,7 @@ public class ExampleBean { <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/> - public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; @@ -1117,7 +1116,7 @@ public class ExampleBean { public void setIntegerProperty(int i) { this.i = i; } -}]]> +} As you can see, setters have been declared to match against the properties specified in the XML file. Find below an example of using @@ -1139,7 +1138,7 @@ public class ExampleBean { <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/> - public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; @@ -1151,7 +1150,7 @@ public class ExampleBean { this.beanTwo = yetAnotherBean; this.i = i; } -}]]> +} As you can see, the constructor arguments specified in the bean definition will be used to pass in as arguments to the constructor of @@ -1161,15 +1160,15 @@ public class ExampleBean { 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 { @@ -1296,23 +1295,23 @@ public class ExampleBean { 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 main reason the first form is preferable to the second is that using the idref tag allows the container to @@ -1375,7 +1374,7 @@ public class ExampleBean { bean, or one of the values in the 'name' attribute of the target bean. - ]]> + <ref bean="someBean"/> Specifying the target bean by using the local attribute leverages the ability of the XML parser to validate XML id @@ -1387,7 +1386,7 @@ public class ExampleBean { about errors as early as possible) if the target bean is in the same XML file. - ]]> + <ref local="someBean"/> Specifying the target bean by using the 'parent' attribute allows a reference to be created @@ -1515,7 +1514,7 @@ public class ExampleBean { value, can also again be any of the following elements: - + bean | ref | idref | list | set | map | props | value | null
Collection merging @@ -1575,9 +1574,9 @@ public class ExampleBean { adminEmails collection with the parent's adminEmails collection. - administrator=administrator@example.com sales=sales@example.com -support=support@example.co.uk]]> +support=support@example.co.uk Notice how the child Properties collection's value set will have inherited all the property elements @@ -1632,26 +1631,26 @@ support=support@example.co.uk]]> instances will be converted to the appropriate type prior to being added to the Collection. - public class Foo { - private Map accounts; + private Map<String, Float> accounts; - public void setAccounts(Map 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 being prepared for injection, the @@ -1676,18 +1675,18 @@ support=support@example.co.uk]]> email property being set to the empty String value ("") - - -]]> + <bean class="ExampleBean"> + <property name="email"><value/></property> +</bean> This is equivalent to the following Java code: exampleBean.setEmail(""). The special <null> element may be used to indicate a null value. For example: - - -]]> + <bean class="ExampleBean"> + <property name="email"><null/></property> +</bean> The above configuration is equivalent to the following Java code: exampleBean.setEmail(null). @@ -1714,25 +1713,25 @@ support=support@example.co.uk]]> embedding a full <value/> element. Therefore, the following: - - hello -]]> + <property name="myProperty"> + <value>hello</value> +</property> - - hello -]]> + <constructor-arg> + <value>hello</value> +</constructor-arg> - - hello -]]> + <entry key="myKey"> + <value>hello</value> +</entry> are equivalent to: - ]]> + <property name="myProperty" value="hello"/> - ]]> + <constructor-arg value="hello"/> - ]]> + <entry key="myKey" value="hello"/> The <property/> and <constructor-arg/> elements support a @@ -1740,19 +1739,19 @@ support=support@example.co.uk]]> used instead of a full nested <ref/> element. Therefore, the following: - - -]]> + <property name="myProperty"> + <ref bean="myBean"> +</property> - - -]]> + <constructor-arg> + <ref bean="myBean"> +</constructor-arg> ... are equivalent to: - ]]> + <property name="myProperty" ref="myBean"/> - ]]> + <constructor-arg ref="myBean"/> Note however that the shortcut form is equivalent to a <ref bean="xxx"> element; there is no @@ -1765,16 +1764,16 @@ support=support@example.co.uk]]> 'value' / 'value-ref' attributes. Therefore, the following: - - - - - -]]> + <entry> + <key> + <ref bean="myKeyBean" /> + </key> + <ref bean="myValueBean" /> +</entry> is equivalent to: - ]]> + <entry key-ref="myKeyBean" value-ref="myValueBean"/> Again, the shortcut form is equivalent to a <ref bean="xxx"> element; there is no shortcut for @@ -1808,19 +1807,19 @@ support=support@example.co.uk]]> the end: the first is using the standard XML format whereas the second example is using 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"> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> - - -]]> + <bean name="p-namespace" class="com.example.ExampleBean" + p:email="foo@bar.com"/> +</beans> As you can see, we are including an attribute in the p-namespace called email in the bean definition - this is telling @@ -1832,26 +1831,26 @@ support=support@example.co.uk]]> 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"> + 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> - + 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 doesn't only include a property value using the p-namespace, but also uses a special format to @@ -1889,9 +1888,9 @@ support=support@example.co.uk]]> 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 @@ -1933,12 +1932,12 @@ support=support@example.co.uk]]> 'depends-on' attribute, with commas, whitespace and semicolons all valid delimiters, like so: - - - + <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 at the bean @@ -2545,9 +2544,9 @@ public class ReplacementComputeValue implements MethodReplacer { fully qualified type name. For example, all the following would match java.lang.String. - java.lang.String String - Str]]> + Str Since the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, @@ -2874,13 +2873,13 @@ public class ReplacementComputeValue implements MethodReplacer { the declarations in your web application's 'web.xml' file. - + <web-app> ... - - org.springframework.web.context.request.RequestContextListener - + <listener> + <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> + </listener> ... -]]> +</web-app> If you are using an older web container (Servlet 2.3), you will need to use the provided @@ -2892,18 +2891,18 @@ public class ReplacementComputeValue implements MethodReplacer { mapping depends on the surrounding web application configuration and so you will have to change it as appropriate.) - + <web-app> .. - - requestContextFilter - org.springframework.web.filter.RequestContextFilter - - - requestContextFilter - /* - + <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> That's it. DispatcherServlet, RequestContextListener and @@ -2919,7 +2918,7 @@ public class ReplacementComputeValue implements MethodReplacer { Consider the following bean definition: - ]]> + <bean id="loginAction" class="com.foo.LoginAction" scope="request"/> With the above bean definition in place, the Spring container will create a brand new instance of the @@ -2941,7 +2940,7 @@ public class ReplacementComputeValue implements MethodReplacer { Consider the following bean definition: - ]]> + <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> With the above bean definition in place, the Spring container will create a brand new instance of the @@ -2968,7 +2967,7 @@ public class ReplacementComputeValue implements MethodReplacer { 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 (incomplete): - + <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> - - -]]> +<bean id="userManager" class="com.foo.UserManager"> + <property name="userPreferences" ref="userPreferences"/> +</bean> From the above configuration it is evident that the singleton bean 'userManager' is being injected with a @@ -3205,7 +3204,7 @@ public class ReplacementComputeValue implements MethodReplacer { of the bean, after having bound it to the session for future reference). - + Object get(String name, ObjectFactory objectFactory) The second method should remove the object from the underlying scope. The session scope implementation for example, removes the @@ -3213,20 +3212,20 @@ public class ReplacementComputeValue implements MethodReplacer { returned (you are allowed to return null if the object with the specified name wasn't found) - + Object remove(String name) The third method is used to register callbacks the scope should execute when it is destroyed or when the specified object in the scope is destroyed. Please refer to the Javadoc or a Spring scope implementation for more information on destruction callbacks. - + void registerDestructionCallback(String name, Runnable destructionCallback) The last method deals with obtaining the conversation identifier for the underlying scope. This identifier is different for each scope. For a session for example, this can be the session identifier. - + String getConversationId()
@@ -3242,7 +3241,7 @@ public class ReplacementComputeValue implements MethodReplacer { BeanFactory implementations that ship with Spring); this central method is displayed below: - + void registerScope(String scopeName, Scope scope); The first argument to the registerScope(..) method is the unique name @@ -3359,7 +3358,7 @@ beanFactory.registerScope("thread", customScope InitializingBean interface specifies exactly one method: - + void afterPropertiesSet() throws Exception; Generally, the use of the InitializingBean interface can be @@ -3370,7 +3369,7 @@ beanFactory.registerScope("thread", customScope 'init-method' attribute. For example, the following definition: - ]]> + <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> public class ExampleBean { @@ -3381,7 +3380,7 @@ beanFactory.registerScope("thread", customScope ...is exactly the same as... - ]]> + <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> public class AnotherExampleBean implements InitializingBean { @@ -3403,7 +3402,7 @@ beanFactory.registerScope("thread", customScope DisposableBean interface specifies a single method: - + void destroy() throws Exception; Generally, the use of the DisposableBean callback interface can @@ -3415,7 +3414,7 @@ beanFactory.registerScope("thread", customScope <bean/>. For example, the following definition: - ]]> + <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/> public class ExampleBean { @@ -3426,7 +3425,7 @@ beanFactory.registerScope("thread", customScope ...is exactly the same as... - ]]> + <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> public class AnotherExampleBean implements DisposableBean { @@ -3667,10 +3666,10 @@ public final class Boot { BeanFactory that created it, when it is created by that BeanFactory. - public interface BeanFactoryAware { void setBeanFactory(BeanFactory beanFactory) throws BeansException; -}]]> +} This allows beans to manipulate the BeanFactory that created them @@ -3713,7 +3712,7 @@ public final class Boot { ObjectFactoryCreatingFactoryBean with the name of the bean that is to be looked up. Let's look at an example: - package x.y; public class NewsFeed { @@ -3726,9 +3725,9 @@ public class NewsFeed { public String getNews() { return this.toString() + ": '" + news + "'"; } -}]]> +} - package x.y; import org.springframework.beans.factory.ObjectFactory; @@ -3746,28 +3745,28 @@ public class NewsFeedManager { NewsFeed news = (NewsFeed) factory.getObject(); System.out.println(news.getNews()); } -}]]> +} Find below the XML configuration to wire together the above classes using the ObjectFactoryCreatingFactoryBean approach. - - - - - - - - - - - - - -]]> + <beans> + <bean id="newsFeedManager" class="x.y.NewsFeedManager"> + <property name="factory"> + <bean +class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> + <property name="targetBeanName"> + <idref local="newsFeed" /> + </property> + </bean> + </property> + </bean> + <bean id="newsFeed" class="x.y.NewsFeed" scope="prototype"> + <property name="news" value="... that's fit to print!" /> + </bean> +</beans> And here is a small driver program to test the fact that new (prototype) instances of the newsFeed bean are @@ -3776,7 +3775,7 @@ class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean NewsFeedManager's printNews() method. - import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import x.y.NewsFeedManager; @@ -3789,13 +3788,13 @@ public class Main { manager.printNews(); manager.printNews(); } -}]]> +} The output from running the above program will look like so (results will of course vary on your machine). - + x.y.NewsFeed@1292d26: '... that's fit to print!' +x.y.NewsFeed@5329c5: '... that's fit to print!' As of Spring 2.5, you can rely upon autowiring of the BeanFactory as yet another alternative @@ -4138,7 +4137,7 @@ public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor Find below a small driver script to exercise the above code and configuration; - import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.scripting.Messenger; @@ -4149,13 +4148,13 @@ public final class Boot { Messenger messenger = (Messenger) ctx.getBean("messenger"); System.out.println(messenger); } -}]]> +} The output of executing the above program will be (something like) this: - + Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 +org.springframework.scripting.groovy.GroovyMessenger@272961
@@ -4316,10 +4315,10 @@ cfg.postProcessBeanFactory(factory); 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]]> +jdbc.password=root With the context namespace introduced in Spring 2.5, it is possible to configure property placeholders with a @@ -4327,7 +4326,7 @@ jdbc.password=root]]> a comma-separated list for the location attribute. - ]]> + <context:property-placeholder location="classpath:com/foo/jdbc.properties"/> The PropertyPlaceholderConfigurer doesn't only look for properties in the Properties file @@ -4350,16 +4349,16 @@ jdbc.password=root]]> you have to pick a particular implementation class at runtime. For example: - - - classpath:com/foo/strategy.properties - - - custom.strategy.class=com.foo.DefaultStrategy - - + <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 is unable to be resolved at runtime to a valid class, resolution of the bean will fail once it is about to be @@ -4393,12 +4392,12 @@ jdbc.password=root]]> Properties file configuration lines are expected to be in the format: - + beanName.property=value An example properties file might look like this: - + dataSource.driverClassName=com.mysql.jdbc.Driver +dataSource.url=jdbc:mysql:mydb This example file would be usable against a container definition which contains a bean called dataSource, which @@ -4410,7 +4409,7 @@ dataSource.url=jdbc:mysql:mydb]]> 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 @@ -4426,7 +4425,7 @@ dataSource.url=jdbc:mysql:mydb]]> Spring 2.5, it is possible to configure property overriding with a dedicated configuration element: - ]]> + <context:property-override location="classpath:override.properties"/>
@@ -4719,18 +4718,18 @@ dataSource.url=jdbc:mysql:mydb]]> source. The ResourceBundleMessageSource is more interesting and is the one we will provide an example for:
- - - - - format - exceptions - windows - - - -]]> + <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> This assumes you have three resource bundles defined on your classpath called format, @@ -4753,15 +4752,15 @@ argument.required=The '{0}' argument is required. 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' (this file @@ -4793,7 +4792,7 @@ argument.required=The '{0}' argument is required. </beans> - public class Example { private MessageSource messages; @@ -4807,12 +4806,12 @@ argument.required=The '{0}' argument is required. 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 @@ -4832,17 +4831,17 @@ argument.required=The '{0}' argument is required. # 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. The MessageSourceAware interface can also be used to acquire a reference to any @@ -4989,19 +4988,19 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.Let's look at an example. First, the ApplicationContext: - - - - black@list.org - white@list.org - john@doe.org - - - + <bean id="emailer" class="example.EmailBean"> + <property name="blackList"> + <list> + <value>black@list.org</value> + <value>white@list.org</value> + <value>john@doe.org</value> + </list> + </property> +</bean> - - -]]> +<bean id="blackListListener" class="example.BlackListNotifier"> + <property name="notificationAddress" value="spam@list.org"/> +</bean> Now, let's look at the actual classes: @@ -5732,12 +5731,12 @@ public @interface Genre { 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: @@ -5767,7 +5766,7 @@ public @interface Offline { 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 { @@ -5775,14 +5774,14 @@ 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 @@ -5871,13 +5870,13 @@ public @interface MovieQualifier { even if they are not themselves annotated with Spring's @Qualifier annotation. - - - - example.CustomQualifier - - -]]> + <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"> + <property name="customQualifierTypes"> + <set> + <value>example.CustomQualifier</value> + </set> + </property> +</bean> Note that the particular implementation of AutowireCandidateResolver that will be @@ -6097,7 +6096,7 @@ public @interface MovieQualifier { ApplicationContext. For example, the following two classes are eligible for such autodetection: - @Service public class SimpleMovieLister { private MovieFinder movieFinder; @@ -6106,7 +6105,7 @@ public class SimpleMovieLister { public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } -}]]> +} @Repository public class JpaMovieFinder implements MovieFinder { @@ -6119,18 +6118,18 @@ public class JpaMovieFinder implements MovieFinder { alternatively a comma-separated list could be specified that included 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"> + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + <context:component-scan base-package="org.example"/> -]]> +</beans> Note that the scanning of classpath packages requires the @@ -6247,14 +6246,14 @@ public class JpaMovieFinder implements MovieFinder { @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> It is also possible to disable the default filters by providing @@ -6307,12 +6306,12 @@ public class MovieFinderImpl implements MovieFinder { 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 @@ -6345,12 +6344,12 @@ public class MovieFinderImpl implements MovieFinder { 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 @@ -6361,12 +6360,12 @@ public class MovieFinderImpl implements MovieFinder { '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>
@@ -6414,57 +6413,96 @@ public class CachingMovieCatalog implements MovieCatalog { per-class.
-
- Defining FactoryBeans with annotations - FactoryBeans can be defined in code using the - @FactoryMethod method level annotation. Factory bean - definiton supports using standard as well as custom qualifiers using - annotations. The scope of the object produces and if it should be a scoped - AOP proxy are determined by the presence of @Scope - and @ScopedProxy annotations. The default scope for - methods with @FactoryMethod can also be inherited - from the class level. The following example shows a variety of usages of the - @FactoryMethod annotation. +
+ Defining bean metadata within components - @Component + Spring components can also contribute bean definition metadata to + the container. This is done with the same @Bean + annotation used to define bean metadata within + @Configuration annotated classes. Here is a simple + example + + @Component public class FactoryMethodComponent { - private static TestBean staticTestBean = new TestBean("staticInstance",1); - - @Autowired @Qualifier("public") - public TestBean autowiredTestBean; - - private static int i; + @Bean @Qualifier("public") + public TestBean publicInstance() { + return new TestBean("publicInstance"); + } - @FactoryMethod @Qualifier("static") - public static TestBean staticInstance() - { - return staticTestBean; - } - - @FactoryMethod @Qualifier("public") - public TestBean getPublicInstance() { - return new TestBean("publicInstance"); - } + public void DoWork() + { + // Component method implementation omitted + } +} - @FactoryMethod @BeanAge(1) - protected TestBean getProtectedInstance() { - return new TestBean("protectedInstance", 1); - } - - @FactoryMethod @Scope("prototype") - private TestBean getPrivateInstance() { - return new TestBean("privateInstance", i++); - } + This class is a Spring component and has appliation specific code + contained in its DoWork method. However, it + also contributes a bean definition that has a factory method refering to + the method publicInstance. The + @Bean annotation identifies the factory method and + also other bean definition properties, such as a qualifier value via 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 before with the additional support + for autowiring of @Bean methods, as shown in the example below - @FactoryMethod @Scope("request") @ScopedProxy - private TestBean getPrivateInstance() { - return new TestBean("privateInstance", i++); - } + @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("prototype") + private TestBean privateInstance() { + return new TestBean("privateInstance", i++); + } + + @Bean @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) + public TestBean requestScopedInstance() { + return new TestBean("requestScopedInstance", 3); + } } -
+ + Note the use of autowiring of the String + method parameter country to the value of the + Age property on another bean named + privateInstance. A Spring Expression Language element + is used to define the value of the property via 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 and do + not invoke the method with normal Java semantics. + In contrast, calling a method or field within a + @Component classes' @Bean method + has standard Java semantics. +
@@ -6473,11 +6511,11 @@ public class FactoryMethodComponent { The context namespace introduced in Spring 2.5 provides a load-time-weaver element. - + <beans ...> - + <context:load-time-weaver/> -]]> +</beans> Adding this element to an XML-based Spring configuration file activates a Spring LoadTimeWeaver for the @@ -6491,4 +6529,4 @@ public class FactoryMethodComponent { for more detail. For more on AspectJ load-time weaving, see .
-
\ No newline at end of file + diff --git a/spring-framework-reference/src/new-in-3.xml b/spring-framework-reference/src/new-in-3.xml index 9784f1a9bda..d96f5618252 100644 --- a/spring-framework-reference/src/new-in-3.xml +++ b/spring-framework-reference/src/new-in-3.xml @@ -1,7 +1,6 @@ - +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> What's new in Spring 3.0? @@ -178,8 +177,9 @@ - Object to XML mapping functionality (OXM) moved from Spring Web Services project - + Object to XML mapping functionality (OXM) moved from Spring Web + Services project + Comprehensive REST support @@ -348,32 +348,33 @@ public class AppConfig{
- Factory Bean definitions using annotations + Defining bean metadata within components - FactoryBeans can be defined within a Spring component definition - and registered using standard component-scanning techniques. See Factory Bean Definitions - using annotations for more information + @Bean annotated methods are also supported + inside Spring components. They contribute a factory bean definition to + the container. See Defining bean metadata within + components for more information
- + -
- The Data Tier +
+ The Data Tier - Object to XML mapping functionality (OXM) from the Spring Web Services project have - been moved to the core Spring Framework now. The functionality is found in the - org.springframework.oxm package. More information on - the use of the OXM can be found - in the Marshalling XML using O/X Mappers chapter. - -
+ Object to XML mapping functionality (OXM) from the Spring Web + Services project have been moved to the core Spring Framework now. The + functionality is found in the org.springframework.oxm + package. More information on the use of the OXM can + be found in the Marshalling XML using O/X + Mappers chapter. +
The Web Tier - The most exciting new feature for the Web Tier is the support for building - RESTful web services and web applications. There are also some new annotations that - can be used in any web application. + The most exciting new feature for the Web Tier is the support for + building RESTful web services and web applications. There are also some + new annotations that can be used in any web application.
Comprehensive REST support @@ -387,14 +388,14 @@ public class AppConfig{ functionality make use of HttpConverters to facilitate the conversion between objects and their representation in HTTP request - and replies. + and replies. The MarhsallingHttpMessageConverter uses - the Object to XML mapping functionality mentioned earlier. + the Object to XML mapping functionality mentioned + earlier. Refer to the section on REST support for more information. -
@@ -407,7 +408,6 @@ public class AppConfig{ @CookieValue annotation and Mapping request header attributes with the @RequestHeader annotation for more information. -
@@ -422,10 +422,11 @@ public class AppConfig{
Early support for Java EE 6 - We provide support for asynchronous method invocations through the use of - the new @Async annotation (or EJB 3.1's @Asynchronous annotation). + We provide support for asynchronous method invocations through the + use of the new @Async annotation (or EJB 3.1's @Asynchronous + annotation). - JSF 2.0, JPA 2.0, etc + JSF 2.0, JPA 2.0, etc Work in progress... not part of the Spring 3.0 M3 release.
diff --git a/spring-framework-reference/src/rest.xml b/spring-framework-reference/src/rest.xml index c8e882a5edd..36265d6e623 100644 --- a/spring-framework-reference/src/rest.xml +++ b/spring-framework-reference/src/rest.xml @@ -853,8 +853,10 @@ URI location = template.postForLocation(uri, booking, String.class, "1");
HTTP Message Conversion - Objects passed to and returned from the methods getForObject(), - postForLocation(), and put() and are converted to HTTP requests and from + Objects passed to and returned from the methods + getForObject, + postForLocation, and + put are converted to HTTP requests and from HTTP responses by HttpMessageConverters. The HttpMessageConverter interface is show below to give you a better feel for its functionality