Spring Essentials

By Shameer Kunjumohamed , Hamidreza Sattari
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started with Spring Core

About 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.

Publication date:
February 2016
Publisher
Packt
Pages
260
ISBN
9781783982349

 

Chapter 1. Getting Started with Spring Core

Spring Framework is the most trusted and widely used application development framework in Enterprise Java. Originally introduced as a simple and lightweight alternative for the complex J2EE, Spring has now grown to become a truly modern application development platform. Spring and its subprojects provide an excellent foundation for end-to-end application development, with features beyond even those provided by the latest Java EE, such as mobile development, social networking, and big data, besides traditional Java web, server-side, or even standalone applications. After more than a decade since its inception, Spring continues to inspire technologies and technologists across the globe.

Although Spring simplifies Java development drastically, software developers and architects are still required to gain a thorough understanding of its core concepts and features in order to deduce the best use of the Spring family. The simplicity Spring offers to otherwise complex Java development is the result of smart abstractions that it provides in the form of excellent APIs and modules. Spring components relieve the developer of all the technical complexity and heavy lifting of common technical and infrastructure plumbing tasks. As the official Spring documentation says, Spring provides comprehensive infrastructure support so that you can focus on your application.

This book is an attempt to make your Spring learning even easier and a more enjoyable experience.

This chapter gives you a solid foundation of the core Spring Framework, guiding you through its core concepts, components, and modules accompanied by relevant sample code snippets that illustrate the best and most practical usage of each feature in order to solve your everyday programming problems.

In this chapter, we will cover the following topics:

  • The Spring landscape

  • Setting up the development environment

  • Your first Spring application

  • Core concepts

  • The IoC (Inversion of Control) container

  • Beans in detail

  • Working with bean definition profiles

  • Handling resources

  • SpEL (Spring Expression Language)

  • Aspect Oriented Programming

 

The Spring landscape


Spring covers a wide variety of technological aspects handled by applications of different types, ranging from a simple standalone Java application up to the most complex, mission critical distributed enterprise systems you can imagine. Unlike most other open source or proprietary frameworks that focus on a specific technology concern such as Web, Messaging, or Remoting, Spring successfully covers almost all the technical aspects of business applications. In most cases, instead of reinventing solutions, Spring utilizes and integrates proven existing frameworks to achieve this end-to-end coverage. Spring is highly modular; hence, it noninvasively allows you to cherry-pick just the modules or features you require in order to become a one-stop shop for all your development needs on JVM.

The whole Spring Framework portfolio is organized into three major elements:

  • Spring Framework

  • Spring Tool Suite

  • Spring subprojects

Spring is constantly improving and becoming more and more modular with every new version so that you can use just the required modules.

Note

This book is based on Spring version 4.

The Spring Framework modules

The core Spring Framework provides basic infrastructure for Java development on top of its core Inversion of Control (IoC) container. The IoC container is an infrastructure that provides Dependency Injection (DI) for applications. Both the concepts of Dependency Injection and IoC containers are explained in detail later in this chapter. The core Spring Framework is divided into the following modules, providing a range of services:

Module

Summary

Core container

Provides the IoC and Dependency Injection features.

AOP and instrumentation

Provides AOP Alliance compliant features for weaving cross-cutting concerns in Spring applications.

Messaging

Provides messaging abstraction over the Spring Integration project for messaging-based applications.

Data access/integration

The data-access/integration layer consists of JDBC, ORM, OXM, JMS, and transaction modules.

Web

Web technology abstraction over Spring MVC, web socket, and portlet APIs.

Test

Unit testing and integration testing support with JUnit and TestNG frameworks.

Spring Tool Suite (STS)

STS is an Eclipse-based IDE (short for Integrated Development Environment) for Spring development. You can download the pre-bundled STS from http://spring.io/tools/sts/all or update your existing Eclipse installation from the update site found at the same location. STS provides various high-productivity features for Spring development. In fact, a Java developer can use any IDE of their choice. Almost all the Java IDEs support Spring development, and most of them have got plugins available for Spring.

Spring subprojects

Spring has many subprojects that solve various application infrastructure needs. From configuration to security, web apps to big data, productivity to enterprise application integration (EAI), whatever your technical pain point be, you will find a Spring project to help you in your application development. Spring projects are located at http://spring.io/projects.

Some notable projects you may find useful right away are Spring Data (JPA, Mongo, Redis, and so on), Spring Security, Spring Web Services, Spring Integration, Spring for Android, and Spring Boot.

 

Design concepts behind Spring Framework


The design of Spring Framework is motivated by a set of design patterns and best practices that have evolved in the industry to address the complexity of Object Oriented Programming, including:

  • Simple, noninvasive, and lightweight POJO (Plain Old Java Objects) programming, without having a need for complex application servers

  • Loosely-coupled dependencies, achieved by applying the concepts of program to interfaces and composition over inheritance, which are the underlying design principles of design patterns and frameworks

  • Highly configurable systems composed of objects with externalized Dependency Injection

  • Templated abstractions to eliminate repetitive, boilerplate code

  • Declarative weaving of cross-cutting aspects without polluting business components

Spring implements established design principles and patterns into its elegant components and promotes their use as the default design approach in applications built using Spring. This noninvasive approach lets you engineer robust and highly maintainable systems composed of loosely coupled components and objects written in clean and modular code. Spring Framework components, templates, and libraries realize the goals and concepts explained earlier in the chapter, leaving you to focus on your core business logic.

 

Setting up the development environment


Spring projects are usually created as Java projects based in Maven, Gradle, or Ivy (which are build automation and dependency management tools). You can easily create a Maven-based Spring project using STS or Eclipse with Spring Tools support. You need to make sure your pom.xml (Maven configuration) file contains, at the minimum, a dependency to spring-context:

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring-framework.version}</version>
  </dependency>
  ...
</dependencies>

Of course, you should add further dependencies to modules such as spring-tx, spring-data-jpa, spring-webmvc, and hibernate, depending on your project type and requirements.

Unless you explicitly specify the repository location, your project works with Maven's central repository. Alternatively, you can point to Spring's official Maven repository (for example, for milestones and snapshots) by specifying it in your pom.xml file:

<repositories>
    <repository>
        <id>io.spring.repo.maven.milestone</id>
        <url>http://repo.spring.io/milestone/</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
</repositories>

You can use the Spring release, milestone, and snapshot repositories as required.

If you are using Gradle as your build system, you can declare your dependencies (typically in the build.gradle file) as follows:

dependencies {
    compile('org.springframework:spring-context')
    compile('org.springframework:spring-tx')
    compile('org.hibernate:hibernate-entitymanager')
    testCompile('junit:junit')
}

If you prefer using the Ivy dependency management tool, then your Spring dependency configuration will look like this:

<dependency org="org.springframework"
    name="spring-core" rev="4.2.0.RC3" conf="compile->runtime"/>
 

Your first Spring application


Let's start with a very simple Spring application now. This application simply greets the user with a welcome message. Technically, it demonstrates how you configure a Spring ApplicationContext (IoC container) with just a single bean in it and invoke that bean method in your application. The application has four artifacts in it (besides the project build file, of course):

  • GreetingService.java: A Java interface—just a single method

  • GreetingServiceImpl.java: A simple implementation of GreetingService

  • Application.java: Your application with a main method

  • application-context.xml: The Spring configuration file of your application

The following are the service components of your application. The service implementation just prints a greeting message to the logger:

interface GreetingService {
   void greet(String message);
}

public class GreetingServiceImpl implements GreetingService {
   Logger logger = LoggerFactory.getLogger(GreetingService.class);

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

Now let's take a look at the application-context.xml file, which is your Spring configuration file, where you register GreetingService as a Spring bean in the following listing:

<?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.xsd">
   <bean id="Greeter"
      class="com.springessentialsbook.chapter1.GreetingServiceImpl">
   </bean>
</beans>

Finally, you invoke the GreetingService.greet() method from your Spring application, as given in the following code:

public class Application {

   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"application-context.xml"});
      GreetingService greeter = (GreetingService) context.getBean("Greeter");
     greeter.greet("I am your first Spring bean instance, configured purely with XML metadata. I am resolved by name.");
   }
}

We will explore and conquer the mighty Spring Framework right from this very simple and pretty much self-explanatory application. We will discuss and elaborate the concepts behind this application, and more, in the following sections.

Inversion of Control explained

IoC is a design principle that decouples objects of an object-oriented program from their dependencies (collaborators), that is, the objects they work with. Usually, this decoupling is achieved by externalizing the responsibility of object creation and Dependency Injection to an external component, such as an IoC container.

This concept is often compared to the Hollywood principle, "Don't call us, we will call you." In the programming world, it recommends the main program (or a component) not to instantiate its dependencies by itself but let an assembler do that job.

This immediately decouples the program from the many problems caused by tightly coupled dependencies and relieves the programmer to let them quickly develop their code using abstract dependencies (program to interfaces). Later, at runtime, an external entity, such as an IoC container, resolves their concentrate implementations specified somewhere and injects them at runtime.

You can see this concept implemented in the example we just saw. Your main program (Application.java) is not instantiating the GreetingService dependency; it just asks the ApplicationContext (IoC container) to return an instance. While writing Application.java, the developer doesn't need to think about how the GreetingService interface is actually implemented. The Spring ApplicationContext takes care of object creation and injects any other functionality transparently, keeping the application code clean.

Objects managed by an IoC container do not control the creation and resolution of their dependencies by themselves; rather, that control is inverted by moving it away to the container itself; hence the term "Inversion of Control".

The IoC container assembles the components of the application as specified in the configuration. It handles the life cycles of the managed objects.

 

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.

 

Beans in detail


A Spring application is composed of a set of beans that perform functionality specific to your application layers and are managed by the IoC container. You define your beans with configuration metadata in the form of XML, annotation, or JavaConfig.

Note

The default scope of a Spring bean is singleton. This means that a single instance is shared between clients anywhere in the application. Beware of keeping state (class level data) in singleton classes, as a value set by one client will be visible to all others. The best use case for such singleton classes are stateless services.

Beans are uniquely identified by an id attribute, any of the values supplied to the (comma, semicolon, or space separated) name attribute of the bean definition, or even as an alias definition. You can refer to a bean anywhere in the application with id or any of the names or aliases specified in the bean definition.

It's not necessary that you always provide an id or name to the bean. If one isn't provided, Spring will generate a unique bean name for it; however, if you want to refer to it with a name or an id, then you must provide one.

Spring will try to autowire beans by type if id or name is not provided. This means that ApplicationContext will try to match the bean with the same type or implementation in case it is an interface.

You can refer to a bean by type if it is either the only bean registered of that type or marked as @Primary (primary="true" for XML). Generally, for nested bean definitions and autowire collaborators, you don't need to define a name unless you refer to it outside the definition.

You can alias a bean outside the bean definition using the <alias/> tag, as follows:

<alias name="fromName" alias="toName"/>

Bean definition

A bean definition object that you define to describe a bean has the following metadata:

Property

Description

class

The fully qualified class name of the bean.

id

The unique identifier of the bean.

name

One or more unique names separated by commas, semicolons, or whitespace. Typically, id and name would be the same, and you supply either of these. Other names in the list become aliases.

parent

The parent bean for inheriting configuration data from a parent bean definition.

scope

This decides the scope of the objects. The default scope of a Spring bean is singleton. This means that a single instance is shared between calls. We will discuss more about bean scopes later.

constructor args

Bean references or names for constructor-based DI.

properties

Values or references for setter-based DI.

autowire mode

Instructs the bean whether or how to autowire relationships with collaborators. Autowiring will be discussed later.

primary

This indicates that the bean should be considered as the primary autowiring candidate in case of multiple matches being found.

depends-on

This forces instantiation of dependent beans prior to this bean.

lazy-init

If true, this creates a bean instance when it is first requested.

init-method

Initialization callback method. This has no args void method and will be invoked post instance creation.

destroy-method

Destruction callback method. This has no args void method and will be invoked before destroy.

factory-method

Static instance factory method on the bean itself, unless factory-bean is provided.

factory-bean

Another bean reference that is acting as an instance factory for this bean. Usually comes along with the factory-method property.

Let's take a look at a sample bean definition in XML form:

<bean id="xmlTaskService" class="com...XmlDefinedTaskService"
init-method="init" destroy-method="cleanup">
   <constructor-arg ref="userService"/>
   <constructor-arg>
      <bean class="com...TaskInMemoryDAO"></bean>
   </constructor-arg>
</bean>

In this sample application-context file, the bean, xmlTaskService, is autowired via a constructor, that is, dependencies are injected via a constructor. The first constructor argument refers to an existing bean definition, and the second one is an inline bean definition without an id. The bean has init-method and destroy-method pointed to its own methods.

Now, let's take a look at an annotated bean with slightly different features:

@Service
public class AnnotatedTaskService implements TaskService {

...
   @Autowired
   private UserService userService;

   @Autowired
   private TaskDAO taskDAO;

   @PostConstruct
   public void init() {
      logger.debug(this.getClass().getName() + " started!");
   }

   @PreDestroy
   public void cleanup() {
      logger.debug(this.getClass().getName() + " is about to destroy!");
   }

   public Task createTask(String name, int priority, int createdByuserId, int assigneeUserId) {
      Task task = new Task(name, priority, "Open",
         userService.findById(createdByuserId), null,
         userService.findById(assigneeUserId));
      taskDAO.createTask(task);
      logger.info("Task created: " + task);
      return task;
   }
...
}

This @Service bean autowires its dependencies on its fields (properties) using an @Autowired annotation. Note the @PostConstruct and @PreDestroy annotations, the equivalents of init-method and destroy-method in the previous XML bean definition example. These are not Spring specific but are JSR 250 annotations. They work pretty well with Spring.

Instantiating beans

Bean definitions are recipes for instantiating bean instances. Depending on metadata attributes such as scope, lazy, and depends-on, Spring Framework decides when and how an instance is created. We will discuss it in detail later. Here, let's look at the "how" of instance creation.

With constructors

Any bean definition with or without constructor arguments but without a factory-method is instantiated via its own constructor, using the new operator:

<bean id="greeter" class="com...GreetingBean"></bean>

Now let's see an annotated @Component with a default constructor-based instantiation:

@Component("greeter")
public class GreetingService {
...
}

With a static factory-method

A static method within the same class, marked as factory-method, will be invoked to create an instance in this case:

<bean id="Greeter" class="...GreetingBean" factory-method="newInstance"></bean>

With Java configuration, you can use an @Bean annotation instead of factory methods:

@Configuration
@ComponentScan(basePackages = "com.springessentialsbook")
public class SpringJavaConfigurator {
...
   @Bean
   public BannerService createBanner() {
      return new BannerServiceImpl();
   }
...
}

With an instance factory-method

In this case, bean definition does not need a class attribute, but you specify the factory-bean attribute, which is another bean, with one of its non-static methods as factory-method:

<bean id="greeter"  factory-bean="serviceFactory" factory-method="createGreeter"/>
<bean id="serviceFactory"  class="...ServiceFactory">
<!— ... Dependencies ... -->
</bean>

Injecting bean dependencies

The main purpose of an IoC container is to resolve the dependencies of objects (beans) before they are returned to the clients who called for an instance (say, using the getBean method). Spring does this job transparently based on the bean configuration. When the client receives the bean, all its dependencies are resolved unless specified as not required (@Autowired(required = false)), and it is ready to use.

Spring supports two major variants of DI—constructor-based and setter-based DI—right out of the box.

Constructor-based Dependency Injection

In constructor-based DI, dependencies to a bean are injected as constructor arguments. Basically, the container calls the defined constructor, passing the resolved values of the arguments. It is best practice to resolve mandatory dependencies via a constructor. Let's look at an example of a simple POJO @Service class, a ready candidate for constructor-based DI:

public class SimpleTaskService implements TaskService {
...
   private UserService userService;
   private TaskDAO taskDAO;

   public SimpleTaskService(UserService userService, TaskDAO taskDAO) {
      this.userService = userService;
      this.taskDAO = taskDAO;
   }
...
}

Now, let's define this as a Spring bean in XML:

<bean id="taskService" class="com...SimpleTaskService"">
   <constructor-arg ref="userService" />
   <constructor-arg ref="taskDAO"/>
</bean>

The Spring container resolves dependencies via a constructor based on the argument's type. For the preceding example, you don't need to pass the index or type of the arguments, since they are of complex types.

However, if your constructor has simple types, such as primitives (int, long, and boolean), primitive wrappers (java.lang.Integer, Long, and so on) or String, ambiguities of type and index may arise. In this case, you can explicitly specify the type and index of each argument to help the container match the arguments, as follows:

<bean id="systemSettings" class="com...SystemSettings">
   <constructor-arg index="0" type="int" value="5"/>
   <constructor-arg index="1" type="java.lang.String" value="dd/mm/yyyy"/>
   <constructor-arg index="2" type="java.lang.String" value="Taskify!"/>
</bean>

Remember, index numbers start from zero. The same applies to setter-based injection as well.

Setter-based Dependency Injection

The container calls the setter methods of your bean in the case of setter-based DI after the constructor (with or without args) is invoked. Let's see how the bean definition for the previous SystemSettings would look if the dependencies were injected via setter methods, assuming the SystemSettings now has a no-args constructor:

<bean id="systemSettings" class="com...SystemSettings">
   <property name="openUserTasksMaxLimit" value="5"/>
   <property name="systemDateFormat" value="dd/mm/yyyy"/>
   <property name="appDisplayName" value="Taskify!"/>
</bean>

Spring validates the bean definitions at the startup of the ApplicationContext and fails with a proper message in case of a wrong configuration. The string values given to properties with built-in types such as int, long, String, and boolean are converted and injected automatically when the bean instances are created.

Constructor-based or setter-based DI – which is better?

Which of these DI methods is better purely depends on your scenario and some requirements. The following best practices may provide a guideline:

  1. Use constructor-based DI for mandatory dependencies so that your bean is ready to use when it is first called.

  2. When your constructor gets stuffed with a large number of arguments, it's the figurative bad code smell. It's time to break your bean into smaller units for maintainability.

  3. Use setter-based DI only for optional dependencies or if you need to reinject dependencies later, perhaps using JMX.

  4. Avoid circular dependencies that occur when a dependency (say, bean B) of your bean (bean A) directly or indirectly depends on the same bean again (bean A), and all beans involved use constructor-based DI. You may use setter-based DI here.

  5. You can mix constructor-based and setter-based DI for the same bean, considering mandatory, optional, and circular dependencies.

In a typical Spring application, you can see dependencies injected using both approaches, but this depends on the scenario, considering the preceding guidelines.

Cleaner bean definitions with namespace shortcuts

You can make your bean definitions cleaner and more expressive using p:(property) and c:(constructor) namespaces, as shown here. While the p namespace enables you to use the <bean/> element's attributes instead of the nested <property/> elements in order to describe your property values (or collaborating bean refs), the c namespace allows you to declare the constructor args as the attributes of the <bean/> element:

<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" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context/spring-context.xsd">

   <bean id="p-taskService" class="com...SimpleTaskService" c:userService-ref="userService" c:taskDAO-ref="taskDAO"/>

   <bean id="p-systemSettings" class="com...SystemSettings"
      p:openUserTasksMaxLimit="5"
      p:systemDateFormat"dd/mm/yyyy"
      p:appDisplayName="Taskify!"/>
</beans>

The bean definitions in the preceding listing are cleaner but more expressive. Both c: and p: namespaces follow the same conventions. You need to declare both at the XML root element (<beans/>) before using them with the <bean/> elements. Note that you use the -ref suffix for bean references.

Wiring a List as a dependency

On occasion, we will need to inject static collections of data as bean dependencies. Spring provides a natural method to wire lists. See this example:

<bean id="systemSettings" class="com...SystemSettings">
. . .
  <constructor-arg>
    <list>
      <value>[email protected]</value>
      <value>[email protected]</value>
      <value>[email protected]</value>
    </list>
  </constructor-arg>
</bean>

The preceding example wires a java.util.List<String> for simplicity. If your list contains a collection of beans, you can replace <value> with <ref> or <bean>.

Wiring a Map as a dependency

You can inject java.util.Map instances too in a similar fashion. Look at this example:

<bean id="systemSettings" class="com...SystemSettings">
. . .
  <property name="emails">
    <map>
      <entry key="admin" value="[email protected]"></entry>
      <entry key="it" value="[email protected]"></entry>
      <entry key="devops" value="[email protected]"></entry>
    </map>
  </property>
</bean>

You can inject beans as values, replacing <value> with <ref> or <bean>.

Autowiring dependencies

Spring can autowire dependencies of your beans automatically by inspecting the bean definitions present in the ApplicationContext if you specify the autowire mode. In XML, you specify the autowire attribute of the <bean/> element. Alternatively, you can annotate a bean with @Autowired to autowire dependencies. Spring supports four autowiring modes: no, byName, byType, and constructor.

Note

The default autowiring of Spring beans is byType. If you are autowiring an interface, Spring will try to find an implementation of that interface configured as a Spring bean. If there are multiple, Spring will look for the primary attribute of the configuration to resolve; if not found, it will fail, complaining about an ambiguous bean definition.

Here is an example of autowiring constructor arguments:

@Service
public class AnnotatedTaskService implements TaskService {
...
   @Autowired
   public AnnotatedTaskService(UserService userService, TaskDAO taskDAO) {
      this.userService = userService;
      this.taskDAO = taskDAO;
   }
...
}

Alternatively, you can autowire at the field level, as follows:

@Service
public class AnnotatedTaskService implements TaskService {
...
   @Autowired
   private UserService userService;
   @Autowired
   private TaskDAO taskDAO;
...
}

Autowiring can be fine-tuned with an @Qualifier annotation and required attribute:

@Autowired(required = true)
@Qualifier("taskDAO")
private UserService userService;

You can use @Qualifier at the constructor level too:

@Autowired
public AnnotatedTaskService(@Qualifier("userService") UserService userService, @Qualifier("taskDAO") TaskDAO taskDAO) {
   this.userService = userService;
   this.taskDAO = taskDAO;
}

Bean scoping

When defining a bean with its dependencies and other configuration values, you can optionally specify the scope of a bean in the bean definition. The scope determines the life span of the bean. Spring comes up with six built-in scopes out of the box and supports the creation of custom scopes too. If not explicitly specified, a bean will assume the singleton scope, which is the default scope. The following table lists the built-in Spring scopes:

Scope

Description

singleton

This ensures a single instance inside the container. This is the default scope.

prototype

A new instance is created for every request for the bean.

request

Scopes an instance with the life cycle of every new HTTP request.

session

Scopes with the life cycle of every new HTTP session.

globalSession

Scopes with an HTTP session inside a portlet context.

application

Scopes with the life cycle of a ServletContext. It's singleton for ServletContext.

While singleton and prototype work in all environments, request, session, and application work only in web environments. The globalSession scope is for portlet environments.

In an XML bean definition, the scope is set via the scope attribute of the <bean/> element:

<bean id="userPreferences" class="com...UserPreferences" scope="session">... </bean>

You can annotate the bean scope as a meta-annotation to @Component or its derivations, such as @Service and @Bean, as shown in the following listing:

@Component
@Scope("request")
public class TaskSearch {...}

Generally, service classes and Spring data repositories are declared as singleton, since they are built stateless according to best practice.

Dependency Injection with scoped beans

Beans of different scopes can be wired up as collaborators in your configuration metadata. For example, if you have a session-scoped bean as a dependency to singleton and face an inconsistency problem, the first instance of the session-scoped bean will be shared between all users. This can be solved using a scoped proxy in place of the scoped bean:

<bean id="userPreferences" class="com...UserPreferences" scope="session">
   <aop:scoped-proxy />
</bean>
<bean id="taskService" class="com...TaskService">
   <constructor-arg ref="userPreferences"/>
</bean>

Every time the scoped bean is injected, Spring creates a new AOP proxy around the bean so that the instance is picked up from the exact scope. The annotated version of the preceding listing would look like this:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserPreferences { ... }

public class AnnotatedTaskService implements TaskService {
...
   @Autowired
   private UserPreferences userPreferences;
...
}

Creating a custom scope

At times, the scopes supplied by Spring are not sufficient for your specific needs. Spring allows you to create your own custom scope for your scenario. For example, if you want to keep some business process level information throughout its life, you will want to create a new process scope. The following steps will enable you to achieve this:

  1. Create a Java class extending org.springframework.beans.factory.config.Scope.

  2. Define it in your application context (XML or annotation) as a Spring bean.

  3. Register the scope bean with your ApplicationContext either programmatically or in XML with CustomScopeConfigurer.

 

Hooking to bean life cycles


Often, in enterprise application development, developers will want to plug in some extra functionality to be executed just after the construction and before the destruction of a business service. Spring provides multiple methods for interacting with such stages in the life cycle of a bean.

Implementing InitializingBean and DisposableBean

The Spring IoC container invokes the callback methods afterPropertiesSet() of org.springframework.beans.factory.InitializingBean and destroy() of org.springframework.beans.factory.DisposableBean on any Spring bean and implements them:

public class UserServiceImpl implements UserService, InitializingBean, DisposableBean {
...
   @Override
   public void afterPropertiesSet() throws Exception {
      logger.debug(this + ".afterPropertiesSet() invoked!");
      // Your initialization code goes here..
   }

   @Override
   public void destroy() throws Exception {
      logger.debug(this + ".destroy() invoked!");
      // Your cleanup code goes here..
   }
...
}

Annotating @PostConstruct and @PreDestroy on @Components

Spring supports JSR 250 @PostConstruct and @PreDestroy annotations on any Spring bean in an annotation-supported environment, as shown here. Spring encourages this approach over implementing Spring-specific interfaces, as given in the previous section:

@Service
public class AnnotatedTaskService implements TaskService {
...
   @PostConstruct
   public void init() {
      logger.debug(this.getClass().getName() + " started!");
   }

   @PreDestroy
   public void cleanup() {
      logger.debug(this.getClass().getName() + " is about to destroy!");
   }
...
}

The init-method and destroy-method attributes of <bean/>

If you are using XML-only bean configuration metadata, then your best option is to declare init-method and destroy-method attributes on your <bean/> tags:

<bean id="xmlTaskService" class="com...XmlDefinedTaskService" init-method="init" destroy-method="cleanup">
...
</bean>
 

Container-level default-init-method and default-destroy-method


You can even set container-level default init and destroy methods so that you don't need to set it for each bean. The container invokes these methods on beans only if they are present:

<beans default-init-method="init" default-destroy-method="cleanup">
...
</beans>
 

Working with bean definition profiles


For commercial projects, it is a common requirement to be able to maintain two or more environment-specific configurations and beans, activated selectively only in the corresponding environment. For example, objects such as data sources, e-mail servers, and security settings could be different for development, testing, and production environments. You would want to switch them declaratively without touching the application code, keeping it externally. Developers traditionally write complex scripts and property files with separate builds to do this job. Spring comes to your rescue here with environment abstraction using bean definition profiles and properties.

Bean definition profiles are a mechanism by which application context is configured differently for different environments. You group bean definitions under named profiles in XML or using annotation and activate one or more profiles in each environment. You can set a default profile to be enabled if you do not specify one explicitly.

Let's take a look the following sample listing that configures data sources for development and production environments:

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

   @Bean
   @Profile("dev")
   public DataSource devDataSource() {
      return new EmbeddedDatabaseBuilder()
         .setType(EmbeddedDatabaseType.HSQL) .addScript("scripts/tasks-system-schema.sql") .addScript("scripts/tasks-master-data.sql") .build();
   }
   @Bean
   @Profile("prod")
   public DataSource productionDataSource() throws Exception {
      Context ctx = new InitialContext();
      return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource/tasks");
   }
}

Practically, for production environments, externalizing this profile config in XML would be a better idea, where you allow your DevOps team to modify it for different environments and forbid them to touch your Java code. XML configuration would look like the following listing:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jdbc="http://www.springframework.org/schema/jdbc"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xsi:schemaLocation="...">
  <!-- other bean definitions -->
  <beans profile="dev">
    <jdbc:embedded-database id="dataSource">
      <jdbc:script location="classpath:scripts/tasks-system-schema.sql"/>
      <jdbc:script location="classpath:scripts/tasks-master-data.sql"/>
    </jdbc:embedded-database>
  </beans>

  <beans profile="production">
    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
  </beans>
</beans>

You may create as many profiles as required; it is common for each developer to maintain their own configurations, with profiles named after themselves, say @Profile("mary"). You can have multiple profiles active at the same time too; it depends on how well you organize them without having conflicts or duplicate bean definitions across profiles.

Now you can activate one or more profiles as you need in each (dev, test, or prod) environment using any one of the following methods:

  1. Programmatically invoking ctx.getEnvironment().setActiveProfiles("p1", "p2", ..).

  2. Setting the property spring.profile.active—with comma-separated profile names as value—as an environment variable, JVM system property, or Servlet context param in web.xml.

  3. Add -Dspring.profile.active="p1,p2, .." as a command-line or Java argument while starting up your application.

 

Injecting properties into the Spring environment


Besides the separation of environment-specific configuration using profiles, you would still need to externalize many properties, such as database URLs, e-mails, and date formats in a property file for easier handling. These properties would then either be injected directly into the beans or read from environment by the beans at runtime. Spring's environment abstraction, together with @PropertySource annotation, makes this possible in Spring applications.

The @PropertySource annotation provides a convenient and declarative mechanism for adding a PropertySource to Spring's environment:

@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan(basePackages = "com.springessentialsbook")
public class SpringJavaConfigurator {
...
   @Autowired
   @Lazy
   private SystemSettings systemSettings;

   @Autowired
   private Environment env;

   @Bean
   public SystemSettings getSystemSettings() {
      String dateFormat = env.getProperty("system.date-format");
      String appDisplayName = env.getProperty("app.displayname");

      return new SystemSettings(dateFormat, appDisplayName);
   }
…
}
 

Externalizing properties with PropertyPlaceholderConfigurer


PropertyPlaceholderConfigurer is another convenient utility to externalize property values from a bean definition into a separate file that uses the standard java.util.Properties format. It replaces placeholders in XML bean definitions with matching property values in the configured property file, as shown here. This is the best way to externalize profile or environment-specific information such as datasource config, e-mail settings, and so on. The DevOps team will just edit these property files and never mess with your code:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:datasource.properties"/>
</bean>

<bean id="dataSource" destroy-method="close"
        class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

Here is another simpler declaration of PropertyPlaceholder:

<context:property-placeholder location="classpath:datasource.properties"/>
 

Handling resources


Spring Framework provides excellent support for accessing low-level resources, thus solving many limitations of Java's standard java.net.URL and standard handlers. The org.springframework.core.io.Resource package and its many concrete implementations form a solid foundation for Spring Framework's robust resource handling.

Resource abstraction is used extensively in Spring itself, inside many implementations of ApplicationContext—it's actually very useful to use as a general utility class by itself in your own code in order to access resources. You will find the following resource implementations that come supplied right out of the box in Spring:

Resource Implementation

Description

UrlResource

It wraps java.net.URL and is useful for accessing anything that can be accessed via a URL, such as files (file:///), HTTP targets (http://), and FTP targets (ftp://).

ClassPathResource

It is used for accessing any resource from classpath using the prefix classpath:

FileSystemResource

This is the resource implementation of java.io.File.

ServletContextResource

This is the parent bean for inheriting configuration data from a parent bean definition.

InputStreamResource

This is the resource implementation for a given InputStream.

Generally, you do not directly instantiate any of these resources; rather, you use a ResourceLoader interface to do that job for you. All ApplicationContext implement a ResourceLoader interface; therefore, any ApplicationContext can be used to obtain resource instances. The code for this is as follows:

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"application-context.xml"});
Resource classPathResource = ctx.getResource("classpath:scripts/tasks-schema.sql");

Resource fileResource = ctx.getResource("file:///scripts/master-data.sql");

Resource urlResource = ctx.getResource("http://country.io/names.json");

You can inject resources into your beans by simply passing the filename or URL of your resource as an argument, as shown here. ApplicationContext, which is a ResourceLoader interface, will create an instance of an appropriate resource implementation based on the URL you supply:

@Value("http://country.io/names.json")
private Resource countriesResource;

Here is the XML version of injecting a resource:

<property name="countriesResource" value="http://country.io/names.json"/>
 

Spring Expression Language


Expression languages are generally used for simple scripting to manipulate object graphs in a non object-oriented context. For example, if we want to read data or call a method of a Java object from a JSP, XML, or XHTML page, JSP EL and Unified Expression Language (UEL) come to the rescue. These expression languages allow page authors to access external data objects in a simple and easy-to-use way, compatible with tag-based languages such as XML and HTML.

The Spring Expression Language (SpEL), with a language syntax similar to UEL, is a powerful expression language built for querying and manipulating an object graph at runtime. It offers additional features, most notably method invocation and basic string-templating functionality.

SpEL can be used inside a wide variety of technologies that come under the Spring family of projects as well as many technologies that integrate with Spring. It can be used directly in the Spring configuration metadata files, both in XML as well as Java annotations in the form #{expression-string}. You can use SpEL inside many view technologies, such as JSP, XML, and XHTML, when integrated with the corresponding technologies, such as JSF, JSP, and Thymeleaf.

SpEL features

The SpEL expression language supports the following functionalities out of the box:

  • Boolean, relational, and ternary operators

  • Regular expressions and class expressions

  • Accessing properties, arrays, lists, and maps

  • Method and constructor invocations

  • Variables, assignments, and bean references

  • Array construction, inline lists, and maps

  • User-defined functions and templated expressions

  • Collection, projection, and selection

SpEL annotation support

SpEL can be used to specify default values for fields, methods and method or constructor arguments using the @Value annotation. The following sample listing contains some excellent usage of SpEL expressions at the field level:

@Component
@Scope("prototype")
public class TaskSnapShot {

   Value("#{taskService.findAllTasks().size()}")
   private String totalTasks;

   @Value("#{taskService.findAllTasks()}")
   private List<Task> taskList;

   @Value("#{ new java.util.Date()}")
   private Date reportTime;

   @Value("#{taskService.findAllTasks().?[status == 'Open']}")
   private List<Task> openTasks;
...

}

The same approach can be used for XML bean definitions too.

The SpEL API

Generally, most users use SpEL to evaluate expressions embedded in XML, XHTML, or annotations. While SpEL serves as the foundation for expression evaluation within the Spring portfolio, it can be used independently in non-Spring environments using the SpEL API. The SpEL API provides the bootstrapping infrastructure to use SpEL programmatically in any environment.

The SpEL API classes and interfaces are located in the (sub)packages under org.springframework.expression. They provide the specification and default SpEL implementations which can be used directly or extended.

The following interfaces and classes form the foundation of the SpEL API:

Class/Interface

Description

Expression

The specification for an expression capable of evaluating itself against context objects independent of any language such as OGNL or UEL. It encapsulates the details of a previously parsed expression string.

SpelExpression

A SpEL-compliant, parsed expression that is ready to be evaluated standalone or in a specified context.

ExpressionParser

Parses expression strings (templates as well as standard expression strings) into compiled expressions that can be evaluated.

SpelExpressionParser

SpEL parser. Instances are reusable and thread-safe.

EvaluationContext

Expressions are executed in an evaluation context, where references are resolved when encountered during expression evaluation.

StandardEvaluationContext

The default EvaluationContext implementation, which uses reflection to resolve properties/methods/fields of objects. If this is not sufficient for your use, you may extend this class to register custom ConstructorResolver, MethodResolver, and PropertyAccessor objects and redefine how SpEL evaluates expressions.

SpelCompiler

Compiles a regular parsed expression instead of the interpreted form to a class containing bytecode for evaluation. A far faster method, but still at an early stage, it does not yet support every kind of expression as of Spring 4.1.

Let's take a look at an example that evaluates an expression using the SpEL API:

@Component
public class TaskSnapshotBuilder {

   @Autowired
   private TaskService taskService;

   public TaskSnapShot buildTaskSnapShot() {
      TaskSnapShot snapshot = new TaskSnapShot();

      ExpressionParser parser = new SpelExpressionParser();
      EvaluationContext context = new StandardEvaluationContext(taskService);
      Expression exp = parser.parseExpression("findAllTasks().size()");
      snapshot.setTotalTasks(exp.getValue(context).toString());

      exp = parser.parseExpression("findAllTasks()");
      snapshot.setTaskList((List<Task>)exp.getValue(context));

      exp = parser.parseExpression("new java.util.Date()");
      snapshot.setReportTime((Date)exp.getValue(context));

      exp = parser.parseExpression("findAllTasks().?[status == 'Open']");
      snapshot.setOpenTasks((List<Task>)exp.getValue(context));

      return snapshot;
   }

}

In normal scenarios, you would not need to directly use the SpEL API in a Spring application; SpEL with annotation or XML bean definitions would be better candidates. The SpEL API is mostly used to load externalized business rules dynamically at runtime.

 

Aspect Oriented Programming


Most software applications usually have some secondary—but critical—features, such as security, transaction, and audit-logging, spanned across multiple logical modules. It would be a nice idea not to mix these cross-cutting concerns in your core business logic. Aspect Oriented Programming (AOP) helps you achieve this.

Object Oriented Programming (OOP) is about modularizing complex software programs, with objects as the fundamental units that hold your core business logic and data. AOP complements OOP to add more complex functionality transparently across modules of your application without polluting the original object structure. AOP stitches (weaves) cross-cutting concerns into your program, either at compile time or runtime, without modifying the base code itself. AOP lets the object-oriented program stay clean and just have the core business concerns.

Static and dynamic AOP

In AOP, the framework weaves the cross-cutting concerns into the main program transparently. This weaving process comes in two different flavors: static and dynamic. In the case of static AOP, as the name implies, Aspects are compiled directly into static files, that is, to the Java bytecode, on compilation. This method performs better, as there is no special interception at runtime. But the drawback is that you need to recompile the entire application every time you change anything in the code. AspectJ, one of the most comprehensive AOP implementations, provides compile-time weaving of Aspects.

In the case of dynamic AOP, the weaving process is performed dynamically at runtime. Different frameworks implement this differently, but the most general way of achieving this is using proxies or wrappers for the advised objects, allowing the Advice to be invoked as required. This is a more flexible method as you can apply AOP with varying behavior at runtime depending on data, which is not possible in the case of static AOP. There is no need for recompiling the main application code if you use XML files for defining your AOP constructs (schema-based approach). The disadvantage of dynamic AOP is a very negligible performance loss due to the extra runtime processing.

Spring AOP is proxy based, that is, it follows the dynamic flavor of AOP. Spring provides the facility to use static AOP by integrating with AspectJ too.

AOP concepts and terminology

Understanding AOP concepts and terms gives you an excellent starting point for AOP; it helps you visualize how and where AOP can be applied in your application:

  • Aspect: The concern that cuts across multiple classes or modules. Transaction and security are examples. Spring Transaction is implemented as Aspects.

  • Join point: A point during the execution of the program at which you want to insert additional logic using AOP. A method execution and a class instantiation are examples.

  • Advice: The action taken by (the code or method that executes) the Aspect at a particular join point. Different types of advices include before, after, and around advices. Typically, an Aspect has one or more Advices.

  • Pointcut: An expression that defines or matches a set of join points. The Advice associated with a pointcut executes at any join point it matches. Spring supports the AspectJ pointcut expression language by default. An example is execution(* com.xyz.service.*.*(..)).

  • Target object: The advised object. If you use dynamic AOP, this would be a proxied object.

  • Weaving: Inserting Aspects into a target object to make it advised at compile time, load time or runtime. AspectJ supports compile-time weaving and Spring weaves at runtime.

  • Introduction: The process by which you add a new method or field to an advised object, with or without making it implement an interface.

Spring AOP – definition and configuration styles

Spring provides a proxy-based dynamic implementation of AOP, developed purely in Java. It neither requires a special compilation process like AspectJ nor controls the class loader hierarchy, hence it can be deployed inside any Servlet container or application server.

Although not a full-blown AOP framework like AspectJ, Spring provides a simple and easy-to-use abstraction of most of the common features of AOP. It supports only method execution join points; field interception is not implemented. Spring provides tight integration with AspectJ, in case you want to advise very fine-grained Aspect orientation that Spring AOP doesn't cover by adding more AspectJ-specific features without breaking the core Spring AOP APIs.

Spring AOP uses standard JDK dynamic proxies for Aspect orientation by default. JDK dynamic proxies allow any interface (or set of interfaces) to be proxied. If you want to proxy classes rather than interfaces, you may switch to CGLIB proxies. Spring automatically switches to use CGLIB if a target object does not implement an interface.

Starting from Spring 2.0, you can follow either a schema-based approach or an @AspectJ annotation style to write custom Aspects. Both of these styles offer fully typed Advice and use of the AspectJ pointcut language while still using Spring AOP for weaving.

XML schema-based AOP

When using schema-based AOP, you need to import aop namespace tags into your application-context file, as follows:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- bean definitions here -->
</beans>

@AspectJ annotation-based AOP

@AspectJ refers to a style of declaring Aspects as regular Java classes that are annotated. Spring interprets the same annotations as AspectJ 5, using a library supplied by AspectJ for pointcut parsing and matching. Spring AOP has no dependency on the AspectJ compiler or weaver, though.

When using the @AspectJ annotation style, you first need to enable @AspectJ support in your Spring configuration, whether or not it is in the XML or Java configuration. Additionally, you need to make sure you add aspectjweaver.jar in your classpath. Adding an @EnableAspectJAutoProxy annotation to your Java @Configuration annotation will enable @AspectJ support in your project:

@Configuration
@ComponentScan(basePackages = "com.springessentialsbook")
@EnableAspectJAutoProxy
public class AOPJavaConfigurator {
...
}

Alternatively, if you use XML-based configuration, @AspectJ support can be enabled by adding the <aop:aspectj-autoproxy/> element in your application-context file.

Declaring an @Aspect annotation

Your Aspect is a simple POJO, either annotated with @Aspect (org.aspectj.lang.annotation.Aspect) or declared as <aop:aspect/> under the <aop:config> section of your application-context XML file. Remember, the class marked as @Aspect should be declared as a Spring bean using either an annotation or <bean/> declaration in your application context XML file.

Here is an annotated Aspect, a Spring component annotated as @Aspect:

@Component("auditLoggerAspect")
@Aspect
public class AuditLoggerAspect {
...
}

Note that @Aspect is a Spring bean too. It can be any of the specializations of @Component.

Now, let's take a look at the XML alternative for Aspect declaration:

<aop:config>
   <aop:aspect id="audLogAspect" ref="auditLoggerAspect">
</aop:config>
<bean id="auditLoggerAspect" class="com...AuditLoggerAspect"/>

Aspects may have methods and fields, just like any other class. They may also contain pointcut, advice, and introduction (inter-type) declarations. Aspects themselves cannot be the target of Advice from other Aspects; they are excluded from auto-proxying.

Pointcuts

A pointcut comprises two parts, as shown in the following code snippet: a method signature (an empty method with a void return type inside the Aspect class) with any parameters and an expression that matches the exact method executions we are interested in. Remember, Spring AOP only supports method execution join points:

@Pointcut("execution(* com.springessentialsbook.service.TaskService.createTask(..))") //Pointcut expression
private void createTaskPointCut() {} //Signature

The pointcut expression follows the standard AspectJ format. You may refer to the AspectJ pointcut expression reference for the detailed syntax. The following section gives you a strong foundation for constructing pointcuts for Spring AOP.

Pointcut designators

Spring AOP supports just a subset of the original AspectJ pointcut designators (PCDs) for use in pointcut expressions, as given in the following table:

PCD

Description

execution

Method execution join point; the default PCD for Spring AOP

within

Matches methods in a range of types, packages, and so on

this

Matches proxy instances of a given type

target

Matches target object with a given type

args

Matches methods with the given argument types

@target

Matches methods of classes with the given annotation

@args

Matches methods having argument (s) with the given annotation (s)

@within

Matches methods within types that have a given annotation

@annotation

Matches methods with the given annotation

In addition to the preceding table, Spring supports an extra non-AspectJ PCD, bean, which is useful to directly refer to a Spring bean or a set of beans with a comma-separated list of beans using bean(idsOrNamesOfBean).

Note that the pointcuts intercept only public methods due to the proxy nature of Spring AOP. If you want to intercept protected and private methods or even constructors, consider using AspectJ weaving (integrated with Spring itself) instead.

Pointcut examples

Pointcut expressions can be combined using &&, ||, and !. You can refer to pointcut expressions by name, too. Let's see a few examples:

@Pointcut("execution(* com.taskify.service.*.*(..))")
private void allServiceMethods() {}

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}

@Pointcut("anyPublicOperation() && allServiceMethods()")
private void allPublicServiceMethods() {}

@Pointcut("within(com.taskify.service..*)")
private void allServiceClasses() {}

@Pointcut("execution(* set*(..))")
private void allSetMethods() {}

@Pointcut("execution(* com.taskify.service.TaskService.*(..))")
private void allTaskServiceMethods() {}

@Pointcut("target(com.taskify.service.TaskService)")
private void allTaskServiceImplMethods() {}


@Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
private void allTransactionalObjectMethods() {}

@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
private void allTransactionalAnnotatedMethods() {}

@Pointcut("bean(simpleTaskService)")
private void allSimpleTaskServiceBeanMethods() {}

An XML version of a pointcut definition goes like this:

<aop:config>
  ...
   <aop:pointcut id="allTaskServicePointCut"
         expression="execution(*com.taskify.service..TaskService.*(..))"/>
</aop:config>

Advices

An Advice is the action that gets injected before, after, or around the method executions matched by the pointcut expression. The pointcut expression associated with an Advice could be a named or defined pointcut, as listed in the above examples, or a pointcut expression declared in place, that is, advices and pointcuts can be declared together.

Let's see an example for an Advice that refers to a pointcut expression named Pointcut:

@Pointcut("execution(* com.taskify.service.TaskService.*(..))")
private void allTaskServiceMethods() {}

@Before("allTaskServiceMethods()")
private void logBeforeAllTaskServiceMethods() {
  logger.info("*** logBeforeAllTaskServiceMethods invoked ! ***");
}

The following code listing combines both a join point and Advice in one go. This is the most common approach:

@After("execution(* com.taskigy.service.TaskService.*(..))")
private void logAfterAllTaskServiceMethods() {
  logger.info("***logAfterAllTaskServiceMethods invoked ! ***");
}

The following table lists the available Advice annotations:

Advice annotation

Description

@Before

Runs before method execution.

@After

Runs after method exit (finally).

@AfterReturning

Runs after the method returns without an exception. You can bind the return value with the Advice as the method argument.

@AfterThrowing

Runs after the method exits by throwing an exception. You can bind the exception with the Advice as the method argument.

@Around

The target method actually runs inside this Advice. It allows you to manipulate the method execution inside your Advice method.

The @Around Advice

The @Around Advice gives you more control over method execution, as the intercepted method essentially runs inside your Advice method. The first argument of the Advice must be ProceedingJoinPoint. You need to invoke the proceed() method of ProceedingJoinPoint inside the Advice body in order to execute the target method; else, the method will not get called. After the method execution returns to you with whatever it returns back to your advice, do not forget to return the result in your Advice method. Take a look at a sample @Around advice:

@Around("execution(* com.taskify.service.**.find*(..))")
private Object profileServiceFindAdvice(ProceedingJoinPoint jPoint) throws Throwable {
    Date startTime = new Date();
    Object result = jPoint.proceed(jPoint.getArgs());
    Date endTime = new Date();
    logger.info("Time taken to execute operation: " + jPoint.getSignature() + " is " + (endTime.getTime() - startTime.getTime()) + " ms");
    return result;
}
Accessing Advice parameters

There are two distinct ways of accessing the parameters of the method you are advising in the Advice method:

  • Declaring a join point as the first argument

  • Binding args in the pointcut definition

Let's see the first approach:

@Before("execution(* com.taskify.service.TaskService.createTask(..)")
private void logBeforeCreateTaskAdvice(JoinPoint joinpoint) {
   logger.info("***logBeforeCreateTaskAdvice invoked ! ***");
   logger.info("args = " + Arrays.asList(joinpoint.getArgs()));
}

You can see that joinpoint.getArgs() returns Object[] of all the arguments passed to the intercepted method. Now, let's see how to bind named arguments to the Advice method:

@Before("createTaskPointCut() and args(name, priority, createdByuserId, assigneeUserId)")
private void logBeforeCreateTaskAdvice(String name, int priority, int createdByuserId, int assigneeUserId) {

  logger.info("name = " + name + "; priority = " + priority + ";
  createdByuserId = " + createdByuserId);
}

Note that the joinpoint expression matches the arguments by name. You can have a joinpoint object as an optional first argument in the method signature without specifying it in the expression: you will have both joinpoint and arguments, enabling more manipulation.

 

Testing with Spring


The degree of testability shows the elegance and maturity of any framework. A more testable system is more maintainable. Spring Framework provides comprehensive support for end-to-end testing of applications for both unit testing as well as integration testing. Spring promotes test-driven development (TDD), facilitates integration testing, and advocates a set of best practices for the unit testing of beans. This is another compelling reason for using Spring to build serious applications.

The POJO-based programming model and loosely coupled nature of Spring beans make it easier to participate in JUnit and TestNG tests even without Spring in the middle. On top of this, Spring provides many testing support components, utilities, and mock objects to make the testing easier.

Mock objects

Spring provides mock implementations of many container-specific components so that the beans can be tested outside a server or container environment. MockEnvironment and MockPropertySource are useful for testing environment-dependent beans. To test beans that depend on HTTP communications, Spring provides mock classes for both client and server sides inside the org.springframework.mock.http and org.springframework.mock.http.client packages.

Another set of useful classes can be found under org.springframework.mock.jndi to run test suites that depend on JNDI resources. The org.springframework.mock.web package contains mock objects for web components based on Servlet 3.0, such as web contexts, filters, controllers, and asynchronous request processing.

Unit and integration testing utilities

Spring ships certain general-purpose and context-specific utilities for unit and integration testing. The org.springframework.test.util package contains a set of utility classes for various testing purposes, including reflection, AOP, JSON, and XML manipulations. Classes under org.springframework.test.web and its nested subdirectories contain a comprehensive set of utility classes to test beans dependent on the web environment. Another set of useful classes for usages specific to ApplicationContext can be found under org.springframework.test.context and its child packages. Their support includes the loading and caching of web, portlet, or application contexts in the test environment; resolving profiles; loading property sources and SQL scripts; managing transactions for test environments; and so on.

The support classes and annotations under the packages listed earlier facilitate the easy and natural testing of Spring applications. A comprehensive discussion over Spring test support is beyond the scope of this book. However, gaining a good understanding of Spring's comprehensive support for unit and integration tests is vital in order to develop elegant code and maintainable applications using Spring.

 

Summary


We have successfully covered all the major technologies and concepts of core Spring Framework in this chapter. We are now capable of developing robust, standalone Spring applications composed of loosely-coupled beans inside the powerful Spring IoC container. We know how to apply cross-cutting concerns transparently across different layers of an application using the very flexible pointcut expressions of Spring AOP. We can manipulate Spring beans using Spring Expression Language, which helps keep the code clean and highly maintainable. We learned how to maintain multiple environment-specific bean configurations and property files using bean definition profiles. Now, we are all set for professional Spring development.

The source code available with this chapter contains multiple Spring projects that demonstrate the different ways of configuring Spring as well as usage scenarios. The examples listed in this chapter have been extracted from them.

In the next chapter, we will explore Spring Web module, leveraging all that we learned in this chapter in a web-based environment. The topics we have learned in this chapter are going to be the foundation for all the advanced topics that will be covered in the following chapters.

About the Authors

  • Shameer Kunjumohamed

    Shameer Kunjumohamed is a software architect specializing in Java-based enterprise application integrations, SOA, and the cloud. Besides Java, he is well-versed in the Node.js and Microsoft .NET platforms. He is interested in JavaScript MVC frameworks such as EmberJS, AngularJS, and ReactJS.

    Shameer has co-authored another book, Spring Web Services 2 Cookbook, Packt Publishing with Hamidreza Sattari, who is the co-author of this book as well.

    Based in Dubai, UAE, Shameer has over 15 years of experience in various functional domains. He currently works as a principal applications architect for a major shipping company in Dubai.

    Browse publications by this author
  • Hamidreza Sattari

    Hamidreza Sattari started software development in 2002. He has been involved in several areas of Software Engineering--programming to architecture to management. His area of interest has been integration among enterprise applications and SOA. Hamidreza Sattari earned his MSc in Software Engineering in 2008 from Herriot Watt University, UK and his Bachelor's Degree in 1994 in Electrical Engineering (Electronics) from Tehran Azad University, Iran. In recent years his research area of interest has been scientific data mining, using algorithms and statistical techniques in pattern recognition, estimation and machine learning.

    Browse publications by this author
Spring Essentials
Unlock this book and the full library for FREE
Start free trial