Design patterns in Spring Framework - part 2

The last time we talked about design patterns in Spring, we discovered 3 creational and 1 behavioral patterns. This time we'll focus more on structural and behavioral ones.

In this article we'll see 2 patterns of each family. The two first will concern the family of structural design patterns. It will be proxy and composite. Two next samples will present the behavioral patterns: strategy and template method.

Spring design pattern - proxy

Object-Oriented Programming (OOP) is maybe the most popular concept in programming. However, Spring introduces another paradigm of coding, Aspect-Oriented Programming (AOP). To simplify the definition, AOP is a kind of programming oriented to specific points of the system, as: exception throwing, execution of specific category of methods etc. AOP allows to execute supplementary actions before or after the execution of these specific points. How this manipulation can be achieved ? It could be make through listeners. But in this case, we should define everywhere the possible invocations of listeners (for example at the begin of one method). It's why Spring doesn't privilege this idea. Instead, Spring implements a design pattern able to accomplish the tasks with supplementary methods invocation - proxy design pattern.

Proxy works like a mirror for objects. Thanks to it, proxy objects can not only override the real objects, but also extend theirs features. So, for one object which can only print some text at the screen, we could add another object to filter displaying words. The invocation of the second object could be defined through proxy. Proxy is an object that encapsulates the real object. For example, if you try to invoke Waiter bean, you'll invoke the proxy of this bean which acts exactly at the same manner.

A good example of proxy design pattern is org.springframework.aop.framework.ProxyFactoryBean. This factory constructs AOP proxy based on Spring beans. This class implements FactoryBean interface which defines getObject() method. This method is used to return an instance of demanded bean to beans factory. In this case, it's not an instance which is returned, but AOP proxy. This proxy object can be further "decorated" with invocations of supplementary methods before executing the method of proxied object.

An example of use of ProxyFactory is:

public class TestProxyAop {

  @Test
  public void test() {
    ProxyFactory factory = new ProxyFactory(new House());
    factory.addInterface(Construction.class);
    factory.addAdvice(new BeforeConstructAdvice());
    factory.setExposeProxy(true);

    Construction construction = (Construction) factory.getProxy();
    construction.construct();
    assertTrue("Construction is illegal. "
      + "Supervisor didn't give a permission to build "
      + "the house", construction.isPermitted());
  }

}

interface Construction {
  public void construct();
  public void givePermission();
  public boolean isPermitted();
}

class House implements Construction{
        
  private boolean permitted = false;
  
  @Override
  public boolean isPermitted() {
    return this.permitted;
  }
  
  @Override
  public void construct() {
    System.out.println("I'm constructing a house");
  }

  @Override
  public void givePermission() {
    System.out.println("Permission is given to construct a simple house");
    this.permitted = true;
  }
}

class BeforeConstructAdvice implements MethodBeforeAdvice {

  @Override
  public void before(Method method, Object[] arguments, Object target) throws Throwable {
    if (method.getName().equals("construct")) {
      ((Construction) target).givePermission();
    }
  }
        
}

This test should pass because we don't operate directly on House instance but on its proxy. The proxy invokes first BeforeConstructAdvice's before method (point to execute before executing the target method, construct() in our case). Thanks to it, a "permission" is given to construct the object's field (house). A proxy layer provides a supplementary feature because it can be simply dispatched to another objects. To do that, we can only modify the filter in before method.

Spring design pattern - composite

Another structural pattern is composite. In the first article about design patterns in Spring, we used builder to construct complex objects. Another way to achieve that is the use of composite. This pattern is based on the existence of multiple objects with common behavior, which are used to construct a bigger object. The bigger object will still have the same characteristics as the smallest ones, ie. it will define the same behavior.

An non-Spring example of composite object could be the writting of a HTML text, composed by paragraphs which can contain spans or em tags:

public class CompositeTest {

  @Test
  public void test() {
    TextTagComposite composite = new PTag();
    composite.addTag(new SpanTag());
    composite.addTag(new EmTag());
    
    // sample client code
    composite.startWrite();
    for (TextTag leaf : composite.getTags()) {
      leaf.startWrite();
      leaf.endWrite();
    }
    composite.endWrite();
    assertTrue("Composite should contain 2 tags but it contains "+composite.getTags().size(), composite.getTags().size() == 2);
  }

}


interface TextTag {
  public void startWrite();
  public void endWrite();
}

interface TextTagComposite extends TextTag {
  public List getTags();
  public void addTag(TextTag tag);
}

class PTag implements TextTagComposite {
  private List tags = new ArrayList();
        
  @Override
  public void startWrite() {
    System.out.println("

"); } @Override public void endWrite() { System.out.println("

"); } @Override public List getTags() { return tags; } @Override public void addTag(TextTag tag) { tags.add(tag); } } class SpanTag implements TextTag { @Override public void startWrite() { System.out.println(""); } @Override public void endWrite() { System.out.println(""); } } class EmTag implements TextTag { @Override public void startWrite() { System.out.println(""); } @Override public void endWrite() { System.out.println(""); } }

In this case,

is a composite object. We can distinguish a composite from non-composite objects because the first one is able to hold one or more non-composite objects (private List tags field in PTag class). Non-composite objects are called the leafs. TextTag interface is called component because it provides common behavior for two object types.

In Spring world we retrieve the concept of composite objects is the org.springframework.beans.BeanMetadataElement interface, used to configure bean objects. It's the basic interface for all inheriting objects. Now, in one side we have the leafs, represented by org.springframework.beans.factory.parsing.BeanComponentDefinition, and in another side the composite org.springframework.beans.factory.parsing.CompositeComponentDefinition. CompositeComponentDefinition acts like component because it contains addNestedComponent(ComponentDefinition component) method which allows to add leafs into private final List nestedComponents. As you can see thanks to this list, component for BeanComponentDefinition and CompositeComponentDefinition is org.springframework.beans.factory.parsing.ComponentDefinition.

Spring design pattern - strategy

The third concept described in this article is strategy design pattern. Strategy defines several objects that accomplish the same thing by in different ways. The way of accomplish given thing depends on adopted strategy. As example to illustrate that, we can take the way to go to one foreign country. We can go there by bus, airplane, boat or even by car. All of these methods will transport us to the destination country. But we we'll choose the most adapted way by checking our bank account. If we've a lot of money, we'll take the fastest way (probably the private fly). If we don't have it enough, we'll take the slowest (bus, car). This bank account acts as a factor defining adapted strategy.

Spring uses strategy design pattern in org.springframework.web.servlet.mvc.multiaction.MethodNameResolver class. Its implementations are destined to parameterize MultiActionController. Before starting to explain the strategy, we need to understand the utility of MultiActionController. This class allows to handle several types of requests by the same class. As every controller in Spring, MultiActionController executes method to respond to provided request. Strategy is used to detect which method should be used. The resolving process is implemented in MethodNameResolver implementations, as for example in ParameterMethodNameResolver from the same package. Method can be resolved through multiple criteria: properties mapping, HTTP request parameters or URL path. The example of this strategy implementation is the getHandlerMethodName from ParameterMethodNameResolver class:

@Override
public String getHandlerMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException {
  String methodName = null;

  // Check parameter names where the very existence of each parameter
  // means that a method of the same name should be invoked, if any.
  if (this.methodParamNames != null) {
    for (String candidate : this.methodParamNames) {
      if (WebUtils.hasSubmitParameter(request, candidate)) {
        methodName = candidate;
        if (logger.isDebugEnabled()) {
          logger.debug("Determined handler method '" + methodName +
            "' based on existence of explicit request parameter of same name");
        }
        break;
      }
    }
  }

  // Check parameter whose value identifies the method to invoke, if any.
  if (methodName == null && this.paramName != null) {
    methodName = request.getParameter(this.paramName);
    if (methodName != null) {
      if (logger.isDebugEnabled()) {
        logger.debug("Determined handler method '" + methodName +
          "' based on value of request parameter '" + this.paramName + "'");
      }
    }
  }

  if (methodName != null && this.logicalMappings != null) {
    // Resolve logical name into real method name, if appropriate.
    String originalName = methodName;
    methodName = this.logicalMappings.getProperty(methodName, methodName);
    if (logger.isDebugEnabled()) {
      logger.debug("Resolved method name '" + originalName + "' to handler method '" + methodName + "'");
    }
  }

  if (methodName != null && !StringUtils.hasText(methodName)) {
    if (logger.isDebugEnabled()) {
      logger.debug("Method name '" + methodName + "' is empty: treating it as no method name found");
    }
    methodName = null;
  }

  if (methodName == null) {
    if (this.defaultMethodName != null) {
      // No specific method resolved: use default method.
      methodName = this.defaultMethodName;
      if (logger.isDebugEnabled()) {
        logger.debug("Falling back to default handler method '" + this.defaultMethodName + "'");
      }
    }
    else {
      // If resolution failed completely, throw an exception.
      throw new NoSuchRequestHandlingMethodException(request);
    }
  }

  return methodName;
}

As we can see in previous code, the method's name is resolved by provided parameters mapping, predefined properties or parameter existence in URL (by default, the name of this parameter is action).

Spring design pattern - template method

The last design pattern presented in this article is template method. This pattern defines a skeleton for class behavior and defers the execution of some steps to subclasses. One method, usually final, plays the role of synchronizer. It executes methods defined by subclasses in given order. In the real world, we can compare template method to house construction. Independently on company which constructs the house, we need to start by make the foundations and only after we can make the rest. This execution logic will be hold in one method which we can't change. The other methods, as foundation construction or wall color, will be template methods, specific to the company constructing the house. We can see it in given example:

public class TemplateMethod {

  public static void main(String[] args) {
    HouseAbstract house = new SeaHouse();
    house.construct();
  }

}

abstract class HouseAbstract {
  protected abstract void constructFoundations();
  protected abstract void constructWall();
  
  // template method
  public final void construct() {
    constructFoundations();
    constructWall();
  }
}

class EcologicalHouse extends HouseAbstract {

  @Override
  protected void constructFoundations() {
    System.out.println("Making foundations with wood");
  }

  @Override
  protected void constructWall() {
    System.out.println("Making wall with wood");
  }
        
}

class SeaHouse extends HouseAbstract {

  @Override
  protected void constructFoundations() {
    System.out.println("Constructing very strong foundations");
  }

  @Override
  protected void constructWall() {
    System.out.println("Constructing very strong wall");
  }
        
}
This code should output:
Constructing very strong foundations
Constructing very strong wall

Spring uses template method in org.springframework.context.support.AbstractApplicationContext class. They're no one template method (as construct in our example), but multiple. For example, obtainFreshBeanFactory returning fresh version of internal bean factory, calls two abstract methods: refreshBeanFactory (to refresh the factory bean) and getBeanFactory (to get refreshed factory bean). This method, as some others, is used in public void refresh() throws BeansException, IllegalStateException method which constructs the application context (you can read more about it in the article consacred to application context in Spring). The sample implementation of abstract methods used by template method can be GenericApplicationContext from the same package, which defines them as below:

/**
  * Do nothing: We hold a single internal BeanFactory and rely on callers
  * to register beans through our public methods (or the BeanFactory's).
  * @see #registerBeanDefinition
  */
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
  if (this.refreshed) {
    throw new IllegalStateException(
      "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
  }
  this.beanFactory.setSerializationId(getId());
  this.refreshed = true;
}

@Override
protected void cancelRefresh(BeansException ex) {
  this.beanFactory.setSerializationId(null);
  super.cancelRefresh(ex);
}

/**
  * Not much to do: We hold a single internal BeanFactory that will never
  * get released.
  */
@Override
protected final void closeBeanFactory() {
  this.beanFactory.setSerializationId(null);
}

/**
  * Return the single internal BeanFactory held by this context
  * (as ConfigurableListableBeanFactory).
  */
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
  return this.beanFactory;
}

/**
  * Return the underlying bean factory of this context,
  * available for registering bean definitions.
  * 

NOTE: You need to call {@link #refresh()} to initialize the * bean factory and its contained beans with application context semantics * (autodetecting BeanFactoryPostProcessors, etc). * @return the internal bean factory (as DefaultListableBeanFactory) */ public final DefaultListableBeanFactory getDefaultListableBeanFactory() { return this.beanFactory; }

This time we discovered how Spring uses behavioral and structural design patterns to better organize the context ionization (template method), to resolve method to execute (strategy). Two structural design patterns are used by it to simplify AOP part (proxy) and construct complex objects (composite).


If you liked it, you should read:

📚 Newsletter Get new posts, recommended reading and other exclusive information every week. SPAM free - no 3rd party ads, only the information about waitingforcode!