Spring Framework : A Framework from SpringSource :: Spring IoC ( Inversion Of Control)
- What is IoC?
- What is Coupling?
- Container and Beans
- First Sample Application
- Convenient access to low-level resources
- Resources
- Download Examples
What is IoC? |
- A way of sorting out dependencies between objects and automatically “injecting” references to collaborating objects on demand usually by XML configuration files
- The basic concept of the Inversion of Control pattern (also known as dependency injection) is that you do not create your objects, but describe how they should be created. You do not directly connect your components and services together in code, but describe which services are needed by which components in a configuration file. A container (in the case of the Spring framework, the IOC container) is then responsible for hooking it all up.
-
In a typical IOC scenario, the container creates all the objects, wires them together by setting the necessary properties, and determines when methods will be invoked. The three implementation pattern types for IOC are listed in as follows:
- Type 1 Services need to implement a dedicated interface through which they are provided with an object from which they can look up dependencies (for example, additional needed services).
- Type 2 Dependencies are assigned through JavaBeans properties (for example, setter methods).
- Type 3 Dependencies are provided as constructor parameters and are not exposed as JavaBeans properties.
- The Spring framework uses the Type 2 and Type 3 implementations for its IOC container.
Benefits of IoC are as follows:
- Reduces coupling between implementation objects and encourages
- interface based design
- Removes the responsibility of finding or creating dependent objects and moves it into configuration
- Allows an application to be reconfigured outside of code
- Encourage writing testable components
Coupling? |
- The big win in using dependency injection is that it allows you to make your applications loosely coupled. That is to say, any one class of your implementation will tend not to have any dependencies on any other class’s specific implementation.
- You will still have dependencies on the type system that you’re establishing in your application, of course, but loose coupling encourages the use of programming to interfaces rather than to abstract or concrete implementations.
Tight Coupling
Rather than talking in abstract terms, Here, an example of some tightly coupled code to illustrate these concerns
package com.javaskool.coupling;
public class TightlyCoupled {
private Transport transport = new SmtpImpl();
public void sendMessage() {
transport.send();
}
}
Loose Coupling
Loosely coupled code allows the major dependencies to be supplied from external code. Here, simple example of a class that has a loose coupling with its dependency
package com.javaskool.coupling;
public class LooselyCoupled {
private Transport transport;
public LooselyCoupled(final Transport transport) {
this.transport = transport;
}
public void sendMessage() {
transport.send();
}
}
Basics: Container and Beans |
Beans
- In Spring, those objects that form the backbone of your application and that are managed by the Spring IoC container are referred to as beans.
- A bean is simply an object that is instantiated, assembled and otherwise managed by a Spring IoC container; other than that, there is nothing special about a bean (it is in all other respects one of probably many objects in your application).
- These beans, and the dependencies between them, are reflected in the configuration metadata used by a container.
Container
- org.springframework.beans.factory.BeanFactory is the actual representation of the Spring IoC container that is responsible for containing and otherwise managing the aforementioned beans.
- The BeanFactory interface is the central IoC container interface in Spring. Its responsibilities include instantiating or sourcing application objects, configuring such objects, and assembling the dependencies between these objects.
- There are a number of implementations of the BeanFactory interface that are supplied straight out-of-the-box with Spring. The most commonly used BeanFactory implementation is the XmlBeanFactory class. This implementation allows you to express the objects that compose your application, and the doubtless rich interdependencies between such objects, in terms of XML. The XmlBeanFactory takes this XML configuration metadata and uses it to create a fully configured system or application.
First Sample Application |
Department.Java
package com.javaskool;
public class Department {
String departmentCode;
String name;
public String getDepartmentCode() {
return this.departmentCode;
}
public void setDepartmentCode(String departmentCode) {
this.departmentCode = departmentCode;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
applicationContext.xml
<bean class="com.javaskool.Department" id="ddd">
<property name="departmentCode" value="1"/>
<property name="name" value="New Tech"/>
</bean>
TestDrive.java
Resource res = new ClassPathResource("applicationContext.xml");
BeanFactory beans=new XmlBeanFactory(res);
Department department=(Department)ctx.getBean("ddd"); //getting Object from BeanFactory
System.out.println(department.getName());
Convenient access to low-level resources |
Convenient ApplicationContext instantiation for Web applications
- As opposed to the BeanFactory, which will often be created programmatically, ApplicationContext instances can be created declaratively using for example a ContextLoader. Of course you can also create ApplicationContext instances programmatically using one of the ApplicationContext implementations. First, let’s examine the ContextLoader mechanism and its implementations.
- The ContextLoader mechanism comes in two flavors: the ContextLoaderListener and the ContextLoaderServlet.
- They both have the same functionality but differ in that the listener version cannot be reliably used in Servlet 2.3 containers. As the Servlet 2.4 specification, servlet context listeners are required to execute immediately after the servlet context for the Web application has been 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.
- It is up to you as to which one you use, but 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 will use /WEB-INF/applicationContext.xml as a default. When it does exist, it will separate the String using predefined delimiters (comma, semi-colon and whitespace) and use the values as locations where application contexts will be searched for. Ant-style path patterns are supported as well: e.g. /WEB-INF/*Context.xml (for all files whose name ends with “Context.xml”, residing in the “WEB-INF” directory) or /WEB-INF/**/*Context.xml (for all such files in any subdirectory of “WEB-INF”).
- The ContextLoaderServlet can be used instead of the ContextLoaderListener. The servlet will use the ‘contextConfigLocation’ parameter just as the listener does.
Resources |
Java’s standard java.net.URL class and standard handlers for various URL prefixes unfortunately are not quite adequate enough for all access to low-level resources. For example, there is no standardized URL implementation that may be used to access a resource that needs to be obtained from the classpath, or relative to a ServletContext. While it is possible to register new handlers for specialized URL prefixes (similar to existing handlers for prefixes such as http:), this is generally quite complicated, and the URL interface still lacks some desirable functionality, such as a method to check for the existence of the resource being pointed to.
The Resource interface
Spring’s Resource interface is meant to be a more capable interface for abstracting access to low-level resources.
public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
URL getURL() throws IOException;
File getFile() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
Some of the most important methods from the Resource interface are:
- getInputStream(): Locates and opens the resource, returning an InputStream for reading from the resource.It is expected that each invocation returns a fresh InputStream. It is the responsibility of the caller to close the stream.
- exists(): Returns a boolean indicating whether this resource actually exists in physical form.
- isOpen(): Returns a boolean indicating whether this resource represents a handle with an open stream. If true, the InputStream cannot be read multiple times, and must be read once only and then closed to avoid resource leaks. Will be false for all usual resource implementations, with the exception of InputStreamResource.
- getDescription(): Returns a description for this resource, to be used for error output when working with the resource. This is often the fully qualified file name or the actual URL of the resource.
- Other methods allow you to obtain an actual URL or File object representing the resource (if the underlying implementation is compatible, and supports that functionality).
- The Resource abstraction is used extensively in Spring itself, as an argument type in many method signatures when a resource is needed. Other methods in some Spring APIs (such as the constructors to various ApplicationContext implementations), take a String which in unadorned or simple form is used to create a Resource appropriate to that context implementation, or via special prefixes on the String path, allow the caller to specify that a specific Resource implementation must be created and used.
- While the Resource interface is used a lot with Spring and by Spring, it’s actually very useful to use as a general utility class by itself in your own code, for access to resources, even when your code does not know or care about any other parts of Spring.
- While this couples your code to Spring, it really only couples it to this small set of utility classes, which are serving as a more capable replacement for URL, and can be considered equivalent to any other library you would use for this purpose.
- It is important to note that the Resource abstraction does not replace functionality: it wraps it where possible.
- For example, an UrlResource wraps a URL, and uses the wrapped URL to do its work.
Built-in Resource implementations
There are number of resource implementations that come supplied straight out of the box in Spring:
UrlResource:
The UrlResource wraps a java.net.URL, and may be used to access any object that is normally accessible via a URL, such as files, an HTTP target, an FTP target, and so on. All URLs have a standardized String representation, such that appropriate standardized prefixes are used to indicate one URL type from another. This includes file: for accessing filesystem paths, http: for accessing resources via the HTTP protocol, ftp: for accessing resources via FTP, and so on. An UrlResource is created by Java code explicitly using the UrlResource constructor, but will often be created implicitly when you call an API method which takes a String argument which is meant to represent a path. For the latter case, a JavaBeans PropertyEditor will ultimately decide which type of Resource to create. If the path string contains a few well-known (to it, that is) prefixes such as classpath, it will create an appropriate specialized Resource for that prefix. However, if it doesn’t recognize the prefix, it will assume this is just a standard URL string, and will create an UrlResource.
ClassPathResource:
This class represents a resource which should be obtained from the classpath. This uses either the thread context class loader, a given class loader, or a given class for loading resources.This Resource implementation supports resolution as java.io.File if the class path resource resides in the filesystem, but not for classpath resources which reside in a jar and have not been expanded (by the servlet engine, or whatever the environment is) to the filesystem. To address this various resource implementations always support resolution as a java.net.URL.
A ClassPathResource is created by Java code explicitly using the ClassPathResource constructor, but will often be created implicitly when you call an API method which takes a String argument which is meant to represent a path. For the latter case, a JavaBeans PropertyEditor will recognize the special prefix classpath: on the string path and create a ClassPathResource in that case.
FileSystemResource:
This is a resource implementation for java.io.File handles. It obviously supports resolution as a File, and as a URL.
ServletContextResource:
This is a resource implementation for ServletContext resources, interpreting relative paths within the relevant Web application’s root directory. This always supports stream access and URL access, but only allows java.io.File access when the Web application archive is expanded and the resource is physically on the filesystem. Whether or not it’s expanded and on the filesystem like this, or accessed directly from the JAR or somewhere else like a DB (it’s conceivable) is actually dependent on the Servlet container.
InputStreamResource:
A resource implementation for a given InputStream. This should only be used if no specific Resource implementation is applicable. In particular, prefer ByteArrayResource or any of the file-based resource implementations where possible. In contrast to other resource implementations, this is a descriptor for an already opened resource – therefore returning true from isOpen(). Do not use it if you need to keep the resource descriptor somewhere, or if you need to read a stream multiple times.
ByteArrayResource:
This is a resource implementation for a given byte array. It creates a ByteArrayInputStream for the given byte array. It is useful for loading content from any given byte array, without having to resort to a single-useInputStreamResource.
The ResourceLoader
The ResourceLoader interface is meant to be implemented by objects that can return (that is, load) Resource instances.
public interface ResourceLoader {
Resource getResource(String location);
}
All application contexts implement the ResourceLoader interface, and therefore all application contexts may be used to obtain Resource instances. When you call getResource() on a specific application context, and the location path specified doesn’t have a specific prefix, you will get back a resource type that is appropriate to that particular application context. For example, assume the following snippet of code was executed against a ClassPathXmlApplicationContext instance:
Resource template = ctx.getResource(“some/resource/path/myTemplate.txt);
- What would be returned would be a ClassPathResource; if the same method was executed against a FileSystemXmlApplicationContext instance, you had get back a FileSystemResource. For a WebApplicationContext, you’d get back a ServletContextResource, and so on.
- As such, you can load resources in a fashion appropriate to the particular application context.
- On the other hand, you may also force ClassPathResource to be used, regardless of the application context type, by specifying the special classpath: prefix:
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt);
Similarly, one can force a UrlResource to be used by specifying any of the standard java.net.URL prefixes:
Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt);
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt);
Click Below to download the Examples
Recent Comments