Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Spring: Creating Objects So You Don't Have To : Page 3

As a dependency injection framework (not to mention one of the more popular open source Java projects today), Spring links objects together using XML definitions. Find out about Spring and the ways you can invert control in your object programming.


WEBINAR: On-Demand

Unleash Your DevOps Strategy by Synchronizing Application and Database Changes REGISTER >

Setter vs. Constructor-based Injection
The example on page 2 demonstrates how Spring can be used to do constructor-based injection. Spring also allows for setter-based injection.

Here is an example of setter-based injection:

<bean name="person" class="examples.spring.Person"> <property name="email"> <value>my@email.address</value> </property> </bean>

This code creates a Person object and calls the setEmail() method, passing in the string defined as a value.

It is good practice to default your classes to being immutable until you have a reason to make them mutable. Constructor-based injection will allow you to take advantage of dependency-injection while still permitting immutability. If your classes are meant to be immutable, then it is probably best to stick with constructor-based injection.

Spring provides a mechanism for "autowiring" beans together. If there is one and only one bean of the type needed for reference by another bean, then Spring can auto-magically link them together for you.

Here is an example:

<bean name="fileDataProcessor" class="examples.spring.DataProcessor" singleton="true" autowire="constructor"> </bean> <bean name="fileDataReader" class="examples.spring.FileDataReader" singleton="true"> <constructor-arg><ref bean="dataFile"/></constructor-arg> </bean>

I specified the autowire attribute on the fileDataProcessor bean to look for bean types that the object takes as a constructor. Because the constructor takes a FileDataReader, and I've only specified one, Spring will automatically link that one into our bean. If there is not exactly one bean defined of the type that I need (i.e. no bean or more than one bean), then Spring will throw an error.

This feature is meant to save you from having to explicitly type out the names of the beans that you reference. I personally favor explicitness in order to make the bean definitions more readable, thus I choose not to use Spring's autowiring functionality, but you may find it useful.

Spring provides a richer mechanism for accessing beans called ApplicationContext. ApplicationContext, like XmlBeanFactory, implements Spring's BeanFactory interface. ApplicationContext provides a few things above and beyond XmlBeanFactory. The Spring documentation recommends always using ApplicationContext unless you have memory usage restrictions, such as in a Java Applet.

One major advantage to ApplicationContext is that it can be loaded declaratively within the context of an application server. One way of doing this is in a Web application. Spring ties in to the standard J2EE mechanism for defining context parameters and application listeners in the Web deployment descriptor file (web.xml).

Here is what you need to define in web.xml:

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> <param-value>/WEB-INF/anotherContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>

If you are using an older version of the Servlet API that doesn't support listeners, you may alternatively have to use Spring's ContextLoaderServlet in order to declaratively configure your ApplicationContext.

ApplicationContext is actually an interface in Spring. WebApplicationContext is a class that implements ApplicationContext and can be used in your Web applications. Here is how you access the ApplicationContext from within your Web application.

class ExampleServlet … WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext( this.getServletContext()); DataProcessor fileDataProcessor = (DataProcessor) ctx.getBean("fileDataProcessor");

Loading Multiple XML Files
You can load multiple XML files into a BeanFactory using the ClassPathXmlApplicationContext class. This class takes a String[], of which each element points to an XML file.

String[] configFiles = new String[] { "examples/spring/spring.xml", "examples/spring/spring-database.xml" }; BeanFactory factory = new ClassPathXmlApplicationContext(configFiles);

Wouldn't it be nice if you could use dependency injection to define your BeanFactory itself? Actually, you can. Using an XML bean definition, you can create a ClassPathXmlApplicationContext and pass the XML file names into the constructor:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="examples.spring" class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg> <list> <value>examples/spring/spring.xml</value> <value>examples/spring/spring-database.xml</value> </list> </constructor-arg> </bean> </beans>

This file can define one or more ApplicationContext beans and can even define a hierarchy of ApplicationContext beans. In order to obtain a reference to our ApplicationContext, Spring provides a Singleton called SingletonBeanFactoryLocator. The no-argument getInstance() method on this class will look for a file called beanRefFactory.xml in the root of the classpath. There is another getInstance() method that takes a String, which you can use to point to a different file. After obtaining a BeanFactoryLocator, you must obtain a BeanFactoryReference, which you use to obtain the BeanFactory calling the useBeanFactory() method and passing in the name designated to the bean in the XML file.

client code… BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance(); BeanFactoryReference bfReference = bfLocator.useBeanFactory("examples.spring"); BeanFactory factory = bfReference.getFactory(); DataSource dataSource = (DataSource) factory.getBean("dataSource");

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date