Inversion of Control (IoC) principle – Also known as dependency injection (DI). IoC is a process whereby objects define their dependencies, only through constructor arguments.
The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern.
Ways to Access Spring:
- PREFERRED: XML File
- Use Java Annotations
- Replace Large Number of Tags in the XML File with Code
- Tries to Minimize the XML File
- Java Based Configuration
- Write Java classes to do the configuration and annotations
If you modify the configuration in the XML file, you only have to edit it. If you use annotations, you have to recompile and retest. You can easily work out the dependencies and what the program is doing, by looking at the XML file. However, you can’t do that through annotations. Config file is not for data. It is for your program dependencies.
The traditional approach to creating associations between application objects (via construction or lookup) leads to complicated code that’s difficult to reuse and unit test. At best, these objects do more work than they should. At worst, they’re highly coupled to one another, making them hard to reuse and hard to test.
In Spring, objects aren’t responsible for finding or creating the other objects that they need to do their jobs. Instead, they’re given references to the objects that they collaborate with by the container. An order manager component, for example, may need a credit card authorizer—but it doesn’t need to create the credit card authorizer. It just needs to show up empty-handed and it’ll be given a credit card authorizer to work with.
The act of creating these associations between application objects is the essence of dependency injection (DI) and is commonly referred to as wiring.
Wiring beans.
Two ways to wire beans:
- Manually
- Auto-wiring: Where Spring does the wiring for you. * Not recommended
When declaring beans in XML, the root element of the Spring configuration file is the <beans> element from Spring’s beans schema. A typical Spring configuration XML file looks like this:
<?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-3.0.xsd”>
<!– Bean declarations go here –>
</beans>
Within the <beans> you can place all of your Spring configuration, including <bean> declarations. But the beans namespace isn’t the only Spring namespace you’ll encounter. All together, the core Spring Framework comes with ten configuration namespaces, as described below.
- aop: Provides elements for declaring aspects and for automatically proxying @AspectJ-annotated classes as Spring aspects
- beans: The core primitive Spring namespace, enabling declaration of beans and how they should be wired.
- context: Comes with elements for configuring the Spring application context, including the ability to autodetect and autowire beans and injection of objects not directly managed by Spring.
- jee: Offers integration with Java EE APIs such as JNDI and EJB.
- jms: Provides configuration elements for declaring message-driven POJOs.
- lang: Enables declaration of beans that are implemented as Groovy, JRuby, or BeanShell scripts.
- mvc: Enables Spring MVC capabilities such as annotation-oriented controllers, view controllers, and interceptors.
- oxm: Supports configuration of Spring’s object-to-XML mapping facilities.
- tx: Provides for declarative transaction configuration.
- util: A miscellaneous selection of utility elements. Includes the ability to declare collections as beans and support for property placeholder elements.
The namespaces define the tags that accessible under that namespace.
<jsp: name>
<chris: name>
Have to specify your tags using a schema. This allows you to have multiple tag libraries. All are valid as long as the schema is defined at the beginning.
<bean id = ‘myBean” class=”com.frost.MyClass”>
Inject Dependencies Here…
</bean>
ID has to be unique. Can only use once per file because beans have to be unique. To give Duke a try, you can load the Spring application context using the following code:
ApplicationContext ctx = new ClassPathXmlApplicationContext(
“com/springinaction/springidol/spring-idol.xml”);
Performer performer = (Performer) ctx.getBean(“duke”);
performer.perform();
Although this isn’t the real competition, the previous code gives Duke a chance to practice. When run, this code prints the following:
package com.springinaction.springidol;
public class Juggler implements Performer {
private int beanBags = 3;
public Juggler() {
}
public Juggler(int beanBags) {
this.beanBags = beanBags
}
public void perform() throws PerformanceException {
System.out.println(“JUGGLING ” + beanBags + ” BEANBAGS”);
}
}
JUGGLING 3 BEANBAGS
Dealing with Complicated Dependencies
First solution – Program to interfaces instead of programming to a class
– That way, the dependency is on the interface.
– Also, avoid using new
– Gives us flexibility. However, we still need a concrete class at some point
IOC – This class does not get its own dependencies. Instead, Spring gives it its own dependencies.
The Juggler class can be constructed in two different ways:
– Using the default constructor
– Using a constructor that takes an int argument which indicates the number of beanbags that the Juggler will attempt to keep in the air
Although the declaration of the duke bean in section 2.1.2 is valid, it uses the Juggler’s default constructor, which limits Duke to juggling only three beanbags at once. To make Duke a world-record juggler, we’ll need to use the other constructor. The following XML re-declares Duke as a 15-beanbag juggler:
<bean id=”duke”
class=”com.springinaction.springidol.Juggler”>
<constructor-arg value=”15″ />
</bean>
The <constructor-arg> element is used to give Spring additional information to use when constructing a bean. If no <constructor-arg>s are given, as in section 2.1.2, the default constructor is used. But here you’ve given a <constructor-arg> with a value attribute set to 15, so the Juggler’s other constructor will be used instead.
Now when Duke performs, the following is printed:
JUGGLING 15 BEANBAGS
Because Duke is more than just an average juggler—he’s a poetic juggler—we need to define a new type of juggler for him to be. PoeticJuggler is a class more descriptive of Duke’s talent. This new type of juggler does everything a regular juggler does, but it also has a reference to a poem to be recited. Speaking of the poem, here’s an interface that generically defines what a poem looks like:
package com.springinaction.springidol;
public interface Poem {
void recite();
}
One of Duke’s favorite Shakespearean sonnets is “When in disgrace with fortune and men’s eyes.” Sonnet29 is an implementation of the Poem interface that defines this sonnet.
package com.springinaction.springidol;
public class Sonnet29 implements Poem {
private static String[] LINES = {
“When, in disgrace with fortune and men’s eyes,”,
“I all alone beweep my outcast state”,
“And trouble deaf heaven with my bootless cries”,
“And look upon myself and curse my fate,”,
“Wishing me like to one more rich in hope,”,
“Featured like him, like him with friends possess’d,”,
“Desiring this man’s art and that man’s scope,”,
“With what I most enjoy contented least;”,
“Yet in these thoughts myself almost despising,”,
“Haply I think on thee, and then my state,”,
“Like to the lark at break of day arising”,
“From sullen earth, sings hymns at heaven’s gate;”,
“For thy sweet love remember’d such wealth brings”,
“That then I scorn to change my state with kings.” };
public Sonnet29() {
}
public void recite() {
for (int i = 0; i < LINES.length; i++) {
System.out.println(LINES[i]);
}
}
}
Sonnet29 can be declared as a Spring <bean> with the following XML:
<bean id=”sonnet29″
class=”com.springinaction.springidol.Sonnet29″ />
With the poem chosen, all you need to do is give it to Duke. Now that Duke is a PoeticJuggler, his <bean> declaration will need to change slightly:
<bean id=”poeticDuke”
class=”com.springinaction.springidol.PoeticJuggler”>
<constructor-arg value=”15″ />
<constructor-arg ref=”sonnet29″ />
</bean>
As you can see from listing 2.2, there’s no default constructor. The only way to construct a PoeticJuggler is to use a constructor that takes arguments. In this listing, you’re using the constructor that takes an int and a Poem as arguments. The duke bean declaration configures the number of beanbags as 15 through the int argument using <constructor-arg>’s value attribute.
But you can’t use value to set the second constructor argument because a Poem isn’t a simple type. Instead, the ref attribute is used to indicate that the value passed to the constructor should be a reference to the bean whose ID is sonnet29. Although the Spring container does much more than just construct beans, you may imagine that when Spring encounters the sonnet29 and duke <bean>s, it performs some logic that’s essentially the same as the following lines of Java:
Poem sonnet29 = new Sonnet29();
Performer duke = new PoeticJuggler(15, sonnet29);
Now when Duke performs, he not only juggles but will also recite Shakespeare, resulting in the following being printed to the standard output stream:
JUGGLING 15 BEANBAGS WHILE RECITING… When, in disgrace with fortune and men’s eyes, I all alone beweep my outcast state And trouble deaf heaven with my bootless cries And look upon myself and curse my fate, Wishing me like to one more rich in hope, Featured like him, like him with friends possess’d, Desiring this man’s art and that man’s scope, With what I most enjoy contented least; Yet in these thoughts myself almost despising, Haply I think on thee, and then my state, Like to the lark at break of day arising From sullen earth, sings hymns at heaven’s gate; For thy sweet love remember’d such wealth brings That then I scorn to change my state with kings.
<bean id = ‘myBean”
class=”com.frost.MyClass” attributes>
Tags – More Attributes
</bean>
<bean id=”poeticDuke”
class=”com.springinaction.springidol.PoeticJuggler”>
<constructor-arg value=”15″ />
<constructor-arg ref=”sonnet29″ />
</bean>
Sometimes the only way to instantiate an object is through a static factory method. Spring is ready-made to wire factory-created beans through the <bean> element’s factory-method attribute.
To illustrate, consider the case of configuring a singleton3 class as a bean in Spring. Singleton classes generally ensure that only one instance is created by only allowing creation through a static factory method. The Stage class in the following listing is a basic example of a singleton class.
Three common ways to get the bean factory:
//Using the BeanFactory – simpliest, but hardly ever used
BeanFactory factory = new XmlBeanFactory(new ClassPathResource(“context.xml”));
HelloWorld helloWorld = (HelloWorld) factory.getBean(“helloWorld”);
//Using ApplicationContext and a single configuration file
ApplicationContext context = new ClassPathXmlApplicationContext(“context.xml”);
HelloWorld helloWorld = (HelloWorld)context.getBean(“helloWorld”);
//Using ApplicationContext and multiple configuration files
String[] files = {“context.xml”,”secondContext.xml”};
ApplicationContext context = new ClassPathXmlApplicationContext(files);
HelloWorld helloWorld = (HelloWorld)context.getBean(“helloWorld”);
ApplicationContext is a subclass of BeanFactory.
DI – Two ways to pass something into your class
- Constructor
- Need to have a zero-argument constructor for this to work
- Call the Set Method
Spring can handle both ways, so you have to be ready to handle both. Spring’s preferences are to use setters. Google is passionate about using constructors with their equivalent, Juice.
Typically, a JavaBean’s properties are private and will have a pair of accessor methods in the form of setXXX() and getXXX(). Spring can take advantage of a property’s setter method to configure the property’s value through setter injection.
Beans.xml
<bean id=”user” class=”com.springclass.User” >
<property name=”name” value”Chris” />
<property name=”age” value=”42” />
<property name=”location” value=”Plano” />
</bean>
//This will look for a constructor taking three arguments.
Each line allows you to inject one property.
In the SpellCheck example:
<bean id = “textEditor” class=”com.springclass.TextEditor” >
<constructor-arg ref=””>
</bean>
<bean id=”user” class=””>
<constructor-arg value=”Chris” />
<constructor-arg value=”42” />
<constructor-arg value=”Plano” />
</bean>
//This works with constructors by supplying them with the arguments in order. If the order is switched, then data type issues might occur. For example, a String being cast as an Int.
<bean id=”user” class=”com.springclass.User”>
<constructor-arg type=”java.lang.String” value=”Chris” />
<constructor-arg type=“java.lang.String” value=”Plano” />
</bean>
Can also define the order by using index..
<bean id=”user” class=”com.springclass.User”>
<constructor-arg index=”1” type=”java.lang.String” value=”Chris” />
<constructor-arg index=”0” type=“java.lang.String” value=”Plano” />
</bean>
Notice that we used java.lang.String instead of just String. Here, we have to put the full package name of the class.
Using the p-Namespace
p-namespace enables you to use the bean element’s attributes, instead of nested <property/> elements, to describe your property values and/or collaborating beans.
The following example shows two XML snippets that resolve to the same result: The first uses standard XML format and the second uses 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”>
<bean name=”classic”>
<property name=”email” value=”foo@bar.com”/>
</bean>
<bean name=”p-namespace”
p:email=”foo@bar.com”/>
</beans>
The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name.
<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“>
<bean name=”john-classic”>
<property name=”name” value=”John Doe”/>
<property name=”spouse” ref=”jane”/>
</bean>
<bean name=”john-modern”
class=”com.example.Person”
p:name=”John Doe”
p:spouse-ref=”jane”/>
<bean name=”jane”>
<property name=”name” value=”Jane Doe”/>
</bean>
</beans>
<bean id=”john” class=”com.springclass.Person”>
P:name=”John Doe”
P:spouse-ref=”jane”>
</bean>
<bean id=”jane” class=>
P:name=”Jane Doe”>
</bean>
<bean id = “john” class=”com.springclass.Person”>
<property name=”Name” value=”John Doe”/>
<property name=”spouse” ref=”jane”/>
</bean>
<bean id = “jane” class=”com.springclass.Person”>
<property name=”Name” value=”Jane Doe”/>
</bean>
Singletons
Have a constructor that you mark as private. Then, you can only instantiate that class one time. It’s useful in creating a database connection. However, it causes issues with Spring.
If you can’t create the object, you cannot do DI. There are Design Patterns called Factory methods. Provide a public method.
className.getInstance()
<factory-method = “getInstance”>
Provide the name of the method to instantiate the object. Calls the factory method, instead of using new
Static Factory Method
When defining a bean that you create with a static factory method, you use the class attribute to specify the class containing the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code.
The following bean definition specifies that the bean will be created by calling a factory-method. The definition does not specify the type (class) of the returned object, only the class containing the factory method. In this example, the createInstance() method must be a static method.
<bean id=”clientService”
class=”examples.ClientService”
factory-method=”createInstance”/>
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
Securing Our Beans
By default, all beans can call all other beans. One way around this is to create InnerBeans. InnerBeans do not need (or have) IDs. Instead, they are included in the OuterBean.
<bean id=”textEditor” class=”com.springsource.TextEditor”>
<property name=”spellChecker”>
<bean class=”com.springsource.SpellChecker”>
</property>
</bean>
//Here SpellChecker’s class is the inner bean.
Collections
In the <list/>, <set/>, <map/>, and <props/> elements, you set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. Spring offers four types of collection configuration elements that come in handy when configuring collections of values.
Collection element Useful for…
<list> Wiring a list of values, allowing duplicates
<set> Wiring a set of values, ensuring no duplicates
<map> Wiring a collection of name-value pairs where name and value can be of any type
<props> Wiring a collection of name-value pairs where the name and
value are both Strings
The <list> and <set> elements are useful when configuring properties that are either arrays or some implementation of java.util.Collection. As you’ll soon see, the actual implementation of the collection used to define the property has little correlation to the choice of <list> or <set>. Both elements can be used almost interchangeably with properties of any type of java.util.Collection.
As for <map> and <props>, these two elements correspond to collections that are java.util.Map and java.util.Properties, respectively. These types of collections value-setting Spring elements as the members of a <list>, including <value>,<bean>, and<null/>. In fact, a <list> may contain another <list> as a member for multidimensional lists.
<property name=”addressList”<list>
<value>England</value>
</list>
</property>
<property name=”addressSet”
<set>
<value>England</value>
</set>
</property>
<property name=”addressMap”
<map>
<entry key=”1” value=”England”</>
</map>
</property>
<property name=”addressMap”
<props>
<prop key=”one”> England</prop>
</props>
</property>
MainApp
package com.springclass;
import org.springframework.context.ApplicationContext;
public class AddressApp{
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(“beans.xml”);
JavaCollection jc = (javaCollection) context.getBean(“javaCollection”);
Jc.getAddressList();
Jc.getAddressSet();
Jc.getAddressMap();
Jc.getAddressProp() ;
}
}
Scope
There are five scopes for a bean:
singleton | Scopes the bean definition to a single instance per Spring container(default). No state, just a bunch of methods |
prototype | Allows a bean to be instantiated any number of times (once per use). Does not maintain state. |
request | Scopes a bean definition to an HTTP request. Only valid when used with aweb-capable Spring context (such as with Spring MVC) |
session | Scopes a bean definition to an HTTP session. Only valid when used with aweb-capable Spring context (such as with Spring MVC) |
global-session | Scopes a bean definition to a global HTTP session. Only valid when used in a portlet context. |
Only one shared instance of a singleton bean is managed, and all requests for beans with an id or ids matching that bean definition result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object.
Prototype beans will be instantiated on demand (lazy), while singleton beans will be created on startup.
Prototype scope may be useful in situations where you want to use Spring as a factory for new instances of domain objects. If domain objects are configured as prototype beans, you can easily configure them.
IOC, 67
If you have three classes doing the same thing, you elevate those common elements up into a super class. With beans, if you have shared properties across multiple beans, we use the same concept.
<bean id=”inheritance1” class=”com.springclass.Inheritance1”>
<property name=”message1” value=”Hello World”/>
<property name=”message2” value=”Hello Second World”/>
</bean>
<bean id=”inheritance3” class=”com.springclass.Inheritance3” parent=”inheritance1”>
<property name=”message1” value=”Hello England”/>
<property name=”message3” value=”ello mate!”/>
</bean>
Abstract Beans
<bean id=”beanTemplate” abstract=”true”>
<property name=”message1” value=”Hello England”/>
<property name=”message2” value=”Hello Second World”/>
<property name=”message3” value=”Hello World!”/>
</bean>
//Won’t instantiate because it has no class and abstract is set to true. Holds a set of properties that can be inherited by other beans.
IOC, pg86
Lifecycle of a Bean
In a traditional Java application, the lifecycle of a bean is simple. Java’s new keyword is used to instantiate the bean (or perhaps it’s deserialized) and it’s ready to use. Once the bean is no longer in use, it’s eligible for garbage collection and eventually goes to the big bit bucket in the sky.
In contrast, the lifecycle of a bean within a Spring container is more elaborate. It’s important to understand the lifecycle of a Spring bean, because you may want to take advantage of some of the opportunities that Spring offers to customize how a bean is created. Figure 1.5 shows the startup lifecycle of a typical bean as it’s loaded into a Spring application context.
As you can see, a bean factory performs several setup steps before a bean is ready to use. Breaking down figure 1.5 in more detail:
1) Spring instantiates the bean.
2) Spring injects values and bean references into the bean’s properties.
3) If the bean implements BeanNameAware, Spring passes the bean’s ID to the setBeanName() method.
4) If the bean implements BeanFactoryAware, Spring calls the setBeanFactory() method, passing in the bean factory itself.
5) If the bean implements ApplicationContextAware, Spring will call the setApplicationContext() method, passing in a reference to the enclosing application context.
6) If any of the beans implement the BeanPostProcessor interface, Spring calls theirpostProcessBeforeInitialization() method.
7) If any beans implement the InitializingBean interface, Spring calls their afterPropertiesSet() method. Similarly, if the bean was declared with an init-method, then the specified initialization method will be called.
8) If there are any beans that implement BeanPostProcessor, Spring will call their
9) postProcessAfterInitialization() method.
10) At this point, the bean is ready to be used by the application and will remain in the application context until the application context is destroyed.
11) If any beans implement the DisposableBean interface, then Spring will call their destroy() methods. Likewise, if any bean was declared with a destroy-method, then the specified method will be called.
Basic Lifecycle
1) Load Bean
2) Load Properties
3) Custom init Method
4) Custom destroy Method
5) Die
To define setup and teardown for a bean, simply declare the <bean> with init-method and/or destroy-method parameters. The init-method attribute specifies a method that is to be called on the bean immediately upon instantiation. Similarly, destroy-method specifies a method that is called just before a bean is removed from the container.
<beanid=”auditorium”
class=”com.springinaction.springidol.Auditorium”
init-method=”turnOnLights” destroy-method=”turnOffLights”/>
When declared this way, the turnOnLights() method will be called soon after the auditorium bean is instantiated, allowing it the opportunity to light up the performance venue. And, just before the bean is removed from the container and discarded, turnOffLights() will be called to turn the lights off.
Auto Wiring
The Spring container can autowire relationships between collaborating beans. You can allow Spring to resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext.
4 Ways to Autowire:
- byName: Match by name
- byType: Match by type
- constructor: Match by the arguments in your constructors
- autodetect: Dangerous, best guess
IOC, pg.61
Dependency resolution process
1) The container performs bean dependency resolution as follows:
2) The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified via XML, Java code or annotations.
3) For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method if you are using that instead of a normal constructor. These dependencies are provided to the bean, when the bean is actually created.
4) Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container.
5) Each property or constructor argument which is a value is converted from its specified format to the actual type of that property or constructor argument. By default Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, etc.
6) The Spring container validates the configuration of each bean as the container is created, including the validation of whether bean reference properties refer to valid beans. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies’ dependencies (and so on) are created and assigned.