- Spring Framework
- Feature Summary
- Inversion of Control (IoC)
- Dependency Injection
- Constructor Injection
- Setter Injection
- Using idref
- Injecting Values
- Collections
- Specifying a null Value
- Using p-namespace to Specify Properties
- Compound Property Names
- Autowiring
- Mode Explanation
- Dependency Checking
- Mode Explanation
- Method Injection
- Scopes
- Beans
- Element xxx
- Lifecycle Callbacks
- Bean Definition Inheritance
- Internationalisation using MessageSource
- Events
- Low-level Resources
- Web Application Context
- HTML Escaping
- Submitting Indexed Properties
- Error Handling
- Sharing Session Data Between Portlets
- References
- Feature Summary
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 resource1enGB.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