Book Image

Spring Essentials

Book Image

Spring Essentials

Overview of this book

Spring is an open source Java application development framework to build and deploy systems and applications that run on the JVM. It is the industry standard and the most popular framework among Java developers with over two-thirds of developers using it. Spring Essentials makes learning Spring so much quicker and easier with the help of illustrations and practical examples. Starting from the core concepts of features such as inversion of Control Container and BeanFactory, we move on to a detailed look at aspect-oriented programming. We cover the breadth and depth of Spring MVC, the WebSocket technology, Spring Data, and Spring Security with various authentication and authorization mechanisms. Packed with real-world examples, you’ll get an insight into utilizing the power of Spring Expression Language in your applications for higher maintainability. You’ll also develop full-duplex real-time communication channels using WebSocket and integrate Spring with web technologies such as JSF, Struts 2, and Tapestry. At the tail end, you will build a modern SPA using EmberJS at the front end and a Spring MVC-based API at the back end.By the end of the book, you will be able to develop your own dull-fledged applications with Spring.
Table of Contents (14 chapters)
Spring Essentials
Credits
About the Authors
About the Reviewer
www.PacktPub.com
Preface
Index

Dependency Injection


Dependency Injection is a specific form of Inversion of Control. It is a more formalized design pattern, whereby dependencies of an object are injected by an assembler. DI is generally performed in three major styles: constructor injection, property (setter) injection, or, sometimes, interface injection. IoC and DI are often used interchangeably.

DI offers several benefits, including effective decoupling of dependencies, cleaner code, and increased testability.

The Spring IoC container

The core Spring modules, spring-core, spring-beans, spring-context, spring-context-support, and spring-expression, together make up the core container. The Spring IoC container is designed as an implementation of the following interfaces:

  • org.springframework.beans.factory.BeanFactory

  • org.springframework.context.ApplicationContext

The BeanFactory interface provides the configuration framework and basic functionality, while ApplicationContext, an extension of BeanFactory, adds more enterprise-specific functionality, such as easier integration with Spring's AOP features, message resource handling (for internationalization), and event publication.

Spring provides several concrete implementations of ApplicationContext out of the box for various contexts. The following table lists the most popular ones among them:

Application context

Typical application type

ClassPathXmlApplicationContext

Standalone

AnnotationConfigApplicationContext

Standalone

FileSystemXmlApplicationContext

Standalone

GenericWebApplicationContext

Web

XmlWebApplicationContext

Web

XmlPortletApplicationContext

Web portlet

In Spring, objects managed by the IoC container are called beans. The IoC container handles the assembly and lifecycles of Spring beans. Beans are defined in the configuration metadata consumed by the container, which instantiates and assembles them in order to compose your application.

Configuration metadata

Spring supports three forms of configuration metadata to configure your beans:

  • XML-based configuration metadata

  • Annotation-based configuration metadata

  • Java-based configuration metadata

The example code listing you saw earlier used XML-based configuration metadata. You can always mix and match different forms of metadata in a single application. For example, you may define the primary metadata to be a root XML file that combines a set of annotation-based metadata that in turn defines beans from different layers.

XML-based configuration metadata

The application-context.xml file we saw in the previous Spring application sample is a very minimal example for XML-based configuration metadata. Beans are configured as <bean/> elements inside a top-level <beans> element.

Classes representing the service layer (core business logic, also known as Service classes), Data Access Objects (DAOs), managed web backing beans (such as Struts action instances and JSF managed beans), infrastructure objects (such as Hibernate session factories and JMS queues), and so forth, are excellent candidates for Spring beans. Fine-grained domain objects are not generally configured as Spring beans, because it is usually the responsibility of DAOs and the business logic to create and load domain objects—Hibernate entities are typical examples.

You can create a consolidated (root) ApplicationContext XML file that imports other XML files representing various layers of the application:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

   <import resource="/xml-data-access-objects.xml"/>
   <import resource="/xml-services.xml"/>
   <import resource="/web-beans.xml"/>
   <import resource="/rest-endpoints.xml"/>
...
   <bean id="systemSettings" class="com...SystemSettings">
</beans>

Annotation-based configuration metadata

This method relies on bytecode metadata to wire up components instead of XML-based angle bracket declarations. Configuration of a bean is defined at the source level of the bean itself, in the form of annotations at class, field, or method levels.

Let's take a look at the simplest Spring bean configured by source-level annotation:

@Component("Greeter")
public class GreetingServiceImpl implements GreetingService {

   Logger logger = LoggerFactory.getLogger(GreetingService.class);

   public void greet(String message) {
      logger.info("Greetings! " + message);
   }
}

This is just an annotated version of the same GreetingServiceImpl shown in the Your first Spring application section, where it was configured in the application-context.xml file purely in XML form. In this preceding listing, the annotation @Component makes it a Spring bean. Now, it doesn't require to be defined in XML, but you should instruct your ApplicationContext to consider annotations, as given in the following code:

<context:component-scan base-package="com.springessentialsbook"/>

This code snippet in your application-context.xml file forces ApplicationContext to scan the entire application, including all its dependencies—even inside JAR files—for components annotated as Spring beans of various stereotypes, such as @Component, @Service, @Repository, and @Controller. In addition to component scanning, the ApplicationContext looks for all the annotations in that bean at the class, property, constructor, and method levels (including setter methods) in order to inject dependencies and other behaviors into your beans at startup.

Beware, component scanning can be time consuming if you provide a broader package name to the base-package attribute; it is advised to provide more specific package names to scan (for example, a set of comma-separated package names) so that you have more control. You can narrow down your component scanning even further using <context:include-filter/> and <context:exclude-filter/>.

Another simple instruction to enable annotation configuration is <context:annotation-config/>. It simply looks for annotations on beans registered in the application context and will not detect the components, whereas if you use <context:component-scan/>, it handles both component scanning and other annotations, which will be covered later in this chapter, so you do not need to explicitly declare <context:annotation-config/>. So, the best method for annotation-based configuration is to use <context:annotation-config/>.

XML-based versus annotation-based configuration

XML-based configuration has some advantages over its annotation-based counterpart. The biggest one is that all your bean definitions are in one place and not scattered in many classes or even JAR dependencies. XML allows you to split your metadata files and then combine them using <import/>. Using XML, you can configure any class, including third-party ones such as Spring beans, and inject dependencies and other services into it, which is impossible in the case of annotation. Also, you can define the same class as multiple different beans, each with a different name, dependencies, configuration, and so on.

Annotation-based metadata too has some advantages over XML configuration. It is more concise and much easier to develop and maintain, as your annotation and DI are right inside your source code. All information about a class is in one place.

For bigger applications, the best option would be a mixed approach where the more reusable beans (libraries shared between multiple projects) and third-party components are configured in XML and those with a smaller scope are annotated.

Component stereotype annotations

Spring provides further component stereotypes for beans that represent various roles. The primary stereotype is @Component, and all the others are its specializations for more specific use cases:

Stereotype

Description

@Component

A generic type for all Spring-managed components (beans).

@Service

Marker meta-annotation for service layer components. Currently, Spring treats this the same as @Component, with no special function.

@Repository

Used as DAOs in your persistence layer. Spring Data libraries provide additional functionality.

@Controller

Handles Web MVC endpoints in order to process HTTP requests mapped to specific URLs.

@RestController

A specialized controller for RESTful web services, part of Web MVC. It is a meta-annotation that combines @Controller and @ResponseBody.

Custom stereotypes can be created by defining meta-annotations from scratch or combining existing annotations.

Java-based configuration metadata

Starting with Spring 3.0, you can configure Spring metadata purely inside Java classes, completely avoiding any XML configuration while enhancing annotation-based metadata. You annotate any Java class with @Configuration annotation at the class level and have methods annotated as @Configuration annotation on a factory method that instantiates an @Component annotation, or any other specialized bean, to define your application context. Let's see a simple example:

@Configuration
@ComponentScan(basePackages = "com.springessentialsbook")
public class SpringJavaConfigurator {

    @Autowired
    private GreetingService greeter;

    @Autowired
    private BannerService banner;

    @Bean
    public BannerService createBanner() {
        return new BannerService();
    }

    public BannerService getBanner() {
        return this.banner;
    }

    public void run() {
        this.banner.displayBanner();
        this.greeter.greet("I am the Greeter Spring bean, configured with Java Configuration.");
    }
}

In SpringJavaConfigurator.java, the Java configuration class configures the Spring beans, replacing the application-context.xml file. Your Spring application can directly depend on this Configuration class for loading ApplicationContext.

Typically, you use an AnnotationConfigApplication instance for instantiating your application context:

ApplicationContext ctx = new AnnotationConfigApplicationContext(
  SpringJavaConfigurator.class);
SpringJavaConfigurator app = ctx.getBean(SpringJavaConfigurator.class);
app.run();
BannerService banner = ctx.getBean(BannerService.class);
banner.displayBanner();

When @Configuration classes are provided as the constructor argument, the @Configuration class itself is registered as a bean definition and so are all declared @Bean methods within the class. Spring will scan for the entire project and its dependencies for @Component or its specializations (the other stereotypes listed previously), matching the argument values provided in @ComponentScan(basePackages = "…") with all other relevant annotations and building the application context.

The advantage of JavaConfig metadata is that you have programmatic control over Spring configuration while separating out the entire DI and bean configuration into a separate Java class. Using JavaConfig, you eliminate the complexity of managing many XML files. You detect any configuration issues during development at the earliest, as JavaConfig fails during compilation itself, while in the case of XML, you will know about the configuration issues only on application startup.

JSR 330 standard annotations

Besides Spring-specific annotations, Spring supports JSR 330 standard annotations for DI, starting from Spring 3.0. You just need to include javax.inject artifacts in your Maven or Gradle configuration.

JSR 330 standard annotations have the following equivalents in Spring:

Spring

JSR-330 (javax.inject.*)

Target level / Usage

@Component

@Named

Type (class)

@Autowired

@Inject

Property and setter methods

@Qualifier

@Named

Type, property and setter methods

@Scope("singleton")

@Singleton

Meta-annotation for bean declarations

While the default scope of Spring beans is singleton, the JSR 330 default scope is like Spring's prototype. However, for consistency, Spring treats JSR 330 annotated beans inside Spring as singleton, unless declared prototype explicitly using @Scope("..").

JSR 330 has no equivalents for some Spring-based DI annotations, such as @Value, @Required, and @Lazy. We will discuss more about bean scopes later in this chapter.