Spring Framework
Feature Summary
Inversion of Control (IoC)
http://martinfowler.com/articles/injection.html
The Spring IoC container is implemented through the
BeanFactory interface or through it’s superset interface,
ApplicationContext.
Dependency Injection
Dependencies are also known as collaborators.
The Spring team advocates using setter injection in preference to constructor injection, however it is by no means mandated.
Constructor Injection
<bean id="example1" class="examples.Example1">
<constructor-arg index="0"><ref bean="otherBeanRef"/></constructor-arg>
<constructor-arg index="1" ref="anotherBeanRef"/>
</bean>
public class Example1 {
private OtherBean otherBean;
private AnotherBean anotherBean;
public Example1(OtherBean ob, AnotherBean ab) {
this.otherBean = ob;
this.anotherBean = ab;
}
}
The ‘index’ attribute is only needed where the arguments cannot be clearly distinguished based on their type. They are actually unnecessary in the above example.
Static factory method
<bean id="example1" class="examples.ExampleFactory"
factory-method="createInstance">
<constructor-arg><ref bean="otherBeanRef"/></constructor-arg>
<constructor-arg ref="anotherBeanRef"/>
</bean>
public class Example1 {
private OtherBean otherBean;
private AnotherBean anotherBean;
private Example1(OtherBean ob, AnotherBean ab) {
this.otherBean = ob;
this.anotherBean = ab;
}
public static Example1 createInstance(OtherBean ob, AnotherBean ab) {
return new Example1(ob, ab);
}
}
Setter Injection
<bean id="example2" class="examples.Example2">
<property name="otherBean" ref="otherBeanRef"/>
<property name="anotherBean"><ref bean="anotherBeanRef"/></property>
</bean>
public class Example2 {
private OtherBean otherBean;
private AnotherBean anotherBean;
public void setOtherBean(OtherBean ob) {
this.otherBean = ob;
}
public void setAnotherBean(AnotherBean ab) {
this.anotherBean = ab;
}
}
Using idref
If you use the ref attribute or element to reference another bean, the reference can be by either the other bean’s id or name elements. If you use the idref element instead, the id is used and Spring validates that it exists.
Additionally, be using the idref element’s local attribute, the validation occurs when the XML document is first parsed. The target id must exist within the same file.
<bean id="example2" class="examples.Example2">
<property name="otherBean"><idref bean="otherBeanRef"/></property>
<property name="anotherBean"><idref local="anotherBeanRef"/></property>
</bean>
Injecting Values
<bean id="example3" class="examples.Example3">
<property name="stringValue1" value="abc"/>
<property name="stringValue2"><value>def</value></property>
<property name="intValue" value="123"/>
</bean>
Collections
<bean id="example4" class="examples.Example4">
<property name="properties">
<props>
<prop key="com.fdsd.co.uk.value1">abc</prop>
<prop key="com.fdsd.co.uk.value2">123</prop>
</props>
</property>
<property name="myProperties">
<value>
com.mydomain.value1=abc
com.mydomain.value2=123
</value>
</property>
<property>
<list>
<value>a value</value>
<ref bean="example3"/>
</list>
</property>
<property>
<map>
<entry>
<key><value>com.fdsd.co.uk.value1</value></key>
<value>abc</value>
</entry>
<entry key="com.fdsd.co.uk.value2" value="123"/>
<entry key-ref="example3" value-ref="a value"/>
</map>
</property>
<property>
<set>
<value>a value</value>
<ref bean="example3"/>
</set>
</property>
</bean>
Specifying a null Value
<bean class="examples.Example5">
<property name="example"><null/></property>
</bean>
Using p-namespace to Specify Properties
<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/>
<bean name="example6"
class="examples.Example6"
p:givenName="John"
p:surname="Smith"
p:example-ref="example5"
/>
</beans>
Compound Property Names
Where Example7 has a foo property which in turn has a bar property:
<bean class="examples.Example7">
<property name="foo.bar" value="abc"/>
</bean>
Autowiring
Mode Explanation
no No autowiring. The default. Must use ref element
byName Autowire by property name. The property must have exactly the same name as the bean to be wired
byType Autowire by type where there is only one bean of that type in the container
constructor Same as byType for constructor arguments
autodetect Chooses constructor or byType
through introspection. If a default constructor is found, the
byType mode is used ###
Table: Autowiring Modes
Dependency Checking
<bean class="examples.Example8" dependency-check="none"/>
Mode Explanation
none No dependency checking
simple Check primitive types and collections, not collaborators
object Check collaborators only
all Check both primitive types, collections and collaborators ###
Table: Dependency Checking Modes
Method Injection
Method injection is needed in situations where a singleton scoped bean requires a new prototype bean to be instantiated on each call to a particular methodon the singleton bean. There are a number of solutions described in the Spring Reference Documentation.
Scopes
- singleton
- prototype
- request - scoped to lifecyle of single HTTP request
- session - scoped to lifecycle of single HTTP session
- global session - scoped to lifecycle of a global HTTP session, typically, a portlet context
Prototype Scoped Bean
Clean up is the responsibility of the client code.
Initial Web Configuration
Configuration to enable request, session and global session scoping is only required if you are not using Spring MVC.
Servlet 2.4
Add a listener to web.xml
<web-app>
...
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
...
</web-app>
Servlet 2.3
Add a filter to web.xml
<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>
Scoped Beans as Dependencies
The scoped bean must be wrapped by a proxy that will obtain the correct instance of the scoped (request, session or global session) 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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
<aop:scoped-proxy/>
</bean>
<bean id="options" class="com.foo.Options" scope="session">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<bean id="userService" class="com.foo.SimpleUserService">
<property name="userPreferences" ref="userPreferences"/>
</bean>
</beans>
The first form of
Beans
TODO:: Insert table “The bean definition” from spring-reference page 31, section 3.2.3 “The beans” ### ### Element xxx class
name
scope
constructor arguments
properties
autowiring mode
dependency checking mode
lazy-initialization mode
initialization method
destruction method ###
Table: The bean definition
Instantiating Beans
Beans can be instantiated by one of the following methods;
Using a constructor
Using a static factory method
Using an instance factory method
Bean Factory
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Lifecycle Callbacks
Initialization Callbacks
Implementing the
org.springframework.beans.factory.InitializingBean
interface provides:
void afterPropertiesSet() throws Exception;
Alternatively:
<bean id="example" class="SomeBean" init-method="init"/>
public class SomeBean {
public void init() {
}
}
Destruction Callbacks
Implementing the
org.springframework.beans.factory.DisposableBean interface
provides:
void destroy() throws Exception;
Alternatively:
<bean id="example" class="SomeBean" destory-method="destroy" />
Default Callback Naming
Applies to all beans in container. The named methods will be called if they exist.
<beans default-init-method="init" default-destroy-method="destroy">
Bean Definition Inheritance
A child bean defininition can inherit the properties of it’s parent,
by specifying the parent id using the parent attribute of
the <bean> element.
The parent bean definition can be declared abstract by setting the
abstract attribute of the <bean> element
to “true”. In this case, no class attribute is
required.
If a child bean definition has no class specified, it takes that of the specified parent.
The depends on, autowire mode,
dependency check, singleton,
scope and lazy init attributes settings are
always taken from the child definition.
Internationalisation using MessageSource
The Application Context will search for a
MessageSource bean definition named
messageSource.
To use a ResourceBundleMessageSource, define a bean
similar to the following:
<beans>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="baseNames">
<list
<value>resource1</value>
<value>resource2</value>
</list>
</property>
</bean>
</beans>
This will search the classpath for two resource bundles named
resource1 and resource2. Alternative language
versions are named for example resource1_en_GB.properties.
Resources are then retrieved using MessageSource.getMessage(…) calls.
The MessageSourceAware interface can be used to inject
any implementing bean with the application’s
MessageSource.
Spring also provides a
ReloadableResourceBundleMessageSource that is more flexible
than the JDK based ResouceBundleMessageSource.
Events
Beans can implement the ApplicationListener interface to
handle various events within the ApplicationContext.
Low-level Resources
An ApplicationContext is also a
ResourceLoader which can load Resources from
any location, e.g. the file system, classpath or URL.
Web Application Context
<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>
-->
/WEB-INF/applicationContext.xml is used as the default
if no value is specified for the contextConfigLocation. Ant
style path patterns can also be used to specify application
contexts.
TODO:: continue from 3.9 Glue code and the evil singleton
HTML Escaping
Set a “defaultHtmlEscape” web.xml context-param specifying the default behaviour.
Use org.springframework.web.servlet.tags.HtmlEscapeTag on a per page basis to override the default behaviour.
Note: The HTML escaping is only done when the page is rendered. Input values submitted in a POST or GET or submittted AS-IS.
Submitting Indexed Properties
This requires much the same solution as described in StrutsHints with indexed properties being rendered in the HTML in the following JSTL fashion:
<table>
<c:set value="0" var="i" />
<c:forEach varStatus="loop" var="item" items="${model.myList}">
<tr>
<td><c:out value="${item.myValue}" /> </td>
<td><input type="hidden" name="<c:out value="submitValue[${loop.index}].id" />" value="<c:out value="${item.id}" />" />
<input type="radio" name="<c:out value="submitValue[${loop.index}].choice" />" value="Selected" checked="checked"/></td>
</tr>
</c:forEach>
</table>
The indexed properties will be written to a list property named ‘submitValue’
Error Handling
org.springframework.web.servlet.tags.form.ErrorsTag.MESSAGES_ATTRIBUTE is used to define where error messages are stored within the page context. Whilst this could change, it is currently, “messages”
Sharing Session Data Between Portlets
See http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=3131
References
Related Topics:: StrutsHints
– Frank Dean - 16 Aug 2007