750 likes | 1.06k Views
Spring. Bipin Jethwani. http://www.springsource.org /. What is Spring?. Spring simplifies Java development. Spring is an open source application framework and inversion of control container for the Java platform. Background. Originally created by Rod Johnson.
E N D
Spring Bipin Jethwani
Spring simplifies Java development Spring is an open source application framework and inversion of control container for the Java platform
Background Originally created by Rod Johnson. Described in his book Expert One-on-One: J2EE Design and Development. The framework was first released under the Apache 2.0 license in June 2003. Spring was created to address the complexity of enterprise application development, and makes it possible to use plain-vanilla JavaBeans to achieve things that were previously only possible with EJBs. Spring’s usefulness isn’t limited to server-side development. Any Java application can benefit from Spring in terms of simplicity, testability, and loose coupling.
Spring’s primary features • Dependency Injection (DI) • Aspect-oriented programming (AOP)
Lightweight and minimally invasive development with plain old Java objects (POJOs). Loose coupling through dependency injection and interface orientation. Declarative programming through aspects and common conventions. Boilerplate reduction through aspects and templates
package com.bjethwan.ejbs.session; • import javax.ejb.SessionBean; • import javax.ejb.SessionContext; • public class HelloWorldBean implements SessionBean{ • public void ejbCreate(){ … } • public void ejbActivate(){ … } • public void ejbPassivate(){ … } • public void ejbRemove(){ … } • public void setSessionContext(SessionContextctx){ … } • public StringsayHello(){ return"HelloWorld"; • } • }
The SessionBean interface would let you hook into the EJB’s lifecycle by implement- ing several lifecycle callback methods (those methods that start with ejb). Or I should rephrase that to say that the SessionBean interface would force you to hook into the EJB’s lifecycle, even if you didn’t need to. The bulk of the code in HelloWorldBean is there solely for the sake of the framework. This raises the question: who’s working for whom?
EJB 2 wasn’t alone when it came to being invasive. Other popular frameworks such as the earlier versions of Struts, WebWork, and Tapestry imposed themselves upon otherwise simple Java classes. These heavyweight frameworks forced developers to write classes that were littered with unnecessary code, locked into their framework, and were often difficult to write tests against.
The core features of the Spring Framework can be used by any Java application, but there are extensions for building web applications on top of the Java EE platform. Although the Spring Framework does not impose any specific programming model, it has become popular in the Java community as an alternative to, replacement for, or even addition to the Enterprise JavaBean (EJB) model.
Spring avoids (as much as possible) littering your application code with its API. Spring almost never forces you to implement a Spring-specific interface or extend a Spring-specific class. Instead, the classes in a Spring-based application often have no indication that they’re being used by Spring. At worst, a class may be annotated with one of Spring’s annotations, but is otherwise a POJO.
package com.bjethwan.spring; • public class HelloWorldBean { • public String sayHello() { • return "Hello World"; • } • }
Injecting Dependencies The phrase dependency injection may sound intimidating, conjuring up notions of a complex programming technique or design pattern. But as it turns out, DI isn’t nearly as complex as it sounds. Traditionally, each object is responsible for obtaining its own references to the objects it collaborates with (its dependencies). This can lead to highly coupled and hard-to-test code.
Tightly coupled to RescueDamselQuest package com.springinaction.knights; public class DamselRescuingKnight implements Knight { private RescueDamselQuest quest; public DamselRescuingKnight() { quest = new RescueDamselQuest(); } public void embarkOnQuest() throws QuestException { quest.embark(); } }
With DI, on the other hand, objects are given their dependencies at creation time by some third party that coordinates each object in the system. Objects aren’t expected to create or obtain their dependencies—dependencies are injected into the objects that need them.
constructor injection Quest is injected package com.springinaction.knights; public class BraveKnight implements Knight { private Quest quest; public BraveKnight(Quest quest) { this.quest= quest; } public void embarkOnQuest() throws QuestException { quest.embark(); } } What’s more, the quest he’s given is typed as Quest, an interface that all quests implement. So BraveKnight could embark on a RescueDamselQuest, a SlayDragon- Quest, a MakeRoundTableRounderQuest, or any other Quest implementation he’s given.
The point here is that BraveKnight isn’t coupled to any specific implementation of Quest. It doesn’t matter to him what kind of quest he’s asked to embark upon, so long as it implements the Quest interface. That’s the key benefit of DI—loose coupling. If an object only knows about its dependencies by their interface (not by their implementation or how they’re instantiated), then the dependency can be swapped out with a different implementation without the depending object knowing the difference.
package com.springinaction.knights; import static org.mockito.Mockito.*; import org.junit.Test; public class BraveKnightTest { @Test public void knightShouldEmbarkOnQuest() throws QuestException { Quest mockQuest = mock(Quest.class); BraveKnightknight = new BraveKnight(mockQuest); knight.embarkOnQuest(); verify(mockQuest, times(1)).embark(); } }
wiring INJECTING A QUEST INTO A KNIGHT Now that your BraveKnight class is written in such a way that you can give him any quest you want, how can you specify which Quest to give him? The act of creating associations between application components is commonly referred to as wiring.
In Spring, there are many ways to wire components together, but a common approach has always been via XML. The following listing shows a simple Spring configuration file, knights.xml, that gives a BraveKnight a SlayDragonQuest.
<?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 id="knight" class="com.springinaction.knights.BraveKnight"> <constructor-arg ref="quest" /> </bean> <bean id="quest" class="com.springinaction.knights.SlayDragonQuest" /> </beans>
application context SEEING IT WORK In a Spring application, an application context loads bean definitions and wires them together. The Spring application context is fully responsible for the creation of and wiring of the objects that make up the application. Spring comes with several imple- mentations of its application context, each primarily differing only in how they load their configuration.
Because the beans in knights.xml are declared in an XML file, an appropriate choice for application context might be ClassPathXmlApplicationContext. This Spring context implementation loads the Spring context from one or more XML files located in the application’s classpath. The main() method in the following listing uses ClassPathXmlApplicationContext to load knights.xml and to get a reference to the Knight object.
Injecting through constructors INJECTING OBJECT REFERENCES WITH CONSTRUCTORS
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.
package com.springinaction.knights; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class KnightMain { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("knights.xml"); Knight knight = (Knight) context.getBean("knight"); knight.embarkOnQuest(); } }
By default, all Spring beans are singletons. When the container dispenses a bean (either through wiring or as the result of a call to the container’s getBean() method) it’ll always hand out the exact same instance of the bean. But there may be times when you need a unique instance of a bean each time it’s asked for. How can you override Spring’s default singleton nature?
When declaring a <bean> in Spring, you have the option of declaring a scope for that bean. To force Spring to produce a new bean instance each time one is needed, you should declare the bean’s scope attribute to be prototype. For example, suppose that tickets for a performance are declared as a bean in Spring: <bean id="ticket" class="com.bjethwan.Ticket“ scope="prototype“ />
Spring’s singleton beans only guarantee a single instance of the bean definition per the application context—nothing is stopping you from instantiating that same class in a more conventional way or even defining several <bean> declarations that instantiate the same class.
When a bean is instantiated, it may be necessary to perform some initialization to get it into a usable state. Likewise, when the bean is no longer needed and is removed from the container, some cleanup may be in order. To accommodate setup and tear- down of beans, Spring provides hooks into the bean lifecycle.
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.
DEFAULTING INIT-METHOD AND DESTROY-METHOD If many of the beans in a context definition file will have initialization or destroy methods with the same name, you don’t have to declare init-method or destroy- method on each individual bean. Instead you can take advantage of the default- init-method and default-destroy-method attributes on the <beans> element: <?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" default-init-method="turnOnLights" default-destroy-method="turnOffLights">... </beans> (if those methods exist—otherwise nothing happens).
INJECTING INNER BEANS We’ve seen that Kenny can play saxophone, piano, or any instrument that implements the Instrument interface. But it’s also true that the saxophone and piano beans could also be shared with any other bean by injecting them into an instrument property. So, not only can Kenny play any Instrument, any Instrumentalist can play the saxophone bean. In fact, it’s common for beans to be shared among other beans in an application. The problem is that Kenny’s concerned with the hygienic implications of sharing his saxophone with others.
The p namespace has a schema URI of http://www.springframework.org/ schema/p. To use it, simply add a declaration for it in the Spring XML configuration: <?xml version="1.0"encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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">
With it declared, you can now use p:-prefixed attributes of the <bean> element to wire properties. An an example, look at the following declaration of the kenny bean: <bean id="kenny" class="com.springinaction.springidol.Instrumentalist" p:song = "Jingle Bells" p:instrument-ref = "saxophone" />
Up to now, you’ve seen how to use Spring to configure both simple property values (using the value attribute) and properties with references to other beans (using the ref attribute). But value and ref are only useful when your bean’s properties are sin- gular. How can Spring help you when your bean has properties that are plural—what if a property is a collection of values?
Spring offers four types of collection configuration elements that come in handy when configuring collections of values.
Spring 3 Spring Expression Language (SpEL)
<property name="count" value="#{5}"/> The #{} markers are a clue to Spring that the content that they contain is a SpEL expression. They could be mixed with non-SpEL values as well: <property name="message" value="The value is #{5}"/> Floating-point numbers can also be expressed in SpEL. For example: <property name="frequency" value="#{89.7}"/>