Proxy pattern object-oriented programming (OOP) is probably the most popular concept in programming. Spring, however, introduces another coding specification, faceted Programming (AOP). To simplify the definition, AOP is programming for specific points in the system, such as exception throwing, execution of a specific class of methods, and so on. AOP allows complementary actions to be performed before or after executing these specific points. How is this done? It can be done by listeners. But in this case, we should define listeners to listen wherever calls are possible (such as at the beginning of a method). This is why Spring does not adopt this idea. Instead, Spring implements a design pattern that can accomplish tasks through additional method calls – the proxy design pattern.

A proxy is like a mirror image of an object. Because of this, proxy objects can not only override real objects, but also extend their functionality. So, for objects that only print some text on the screen, we can add another object to filter the words displayed. The invocation of the second object can be defined by proxy. A proxy is an object that encapsulates a real object. For example, if you try to invoke the Waiter Bean, you will invoke the bean’s proxy, which behaves exactly the same way.

A good example of the proxy design pattern is org. Springframework. Aop) framework. ProxyFactoryBean. The factory builds AOP proxies based on Spring Beans. This class implements the FactoryBean interface that defines the getObject() method. This method is used to return an instance of the requirement Bean to the Bean Factory. In this case, it is not a returned instance, but an AOP proxy. Before perform the proxy object method, by calling the add method to further “modification” proxy objects (in fact, the so-called static agent but is in decorative patterns and add a want you to do actions, not decorative pattern adds clothes, do nothing and other authorized by you to finish).

An example of a 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 the House instance, but rather broker it. The proxy calls the before method of the first BeforeConstructAdvice (pointing to execution before execution of the target method, in our case construct()) through which it gives a “permission” to construct the object’s field (house). The proxy layer provides an additional new capability because it can simply be assigned to another object. To do this, we can only modify the filter before the before method.

Composite pattern Another structural pattern is the composite pattern. In our first article on design patterns in Spring, we used a builder to construct complex objects. Another approach is to use the composite pattern. This pattern is based on the existence of multiple objects with common behavior and is used to build larger objects. Larger objects still have the same characteristics as the smallest objects. So use it to define the same behavior.

A non-Spring example of a composite object could be a text object written to HTML, consisting of a paragraph containing a SPAN or em tag:

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<TextTag> getTags();

public void addTag(TextTag tag);

}

class PTag implements TextTagComposite {

private List<TextTag> tags = new ArrayList<TextTag>();

@Override

public void startWrite() {

System.out.println(“<p>”);

}

@Override

public void endWrite() {

System.out.println(“</p>”);

}

@Override

public List<TextTag> getTags() {

return tags;

}

@Override

public void addTag(TextTag tag) {

tags.add(tag);

}

}

class SpanTag implements TextTag {

@Override

public void startWrite() {

System.out.println(“<span>”);

}

@Override

public void endWrite() {

System.out.println(“</span>”);

}

}

class EmTag implements TextTag {

@Override

public void startWrite() {

System.out.println(“

“);


}


@Override


public void endWrite() {


System.out.println(”

“);


}


}


In this case, you see a composite object. We can distinguish composite from non-composite objects because the first can hold one or more non-composite objects (the privateListtags field in the PTag class). Non-composite objects are called leaves. The TextTag interface is called a component because it provides a common behavior for both object types (a bit like the Linux file management system where files in common are managed in a folder, which is node management).

In the Spring in the world, we retrieve the complex object is org. Springframework. Beans. BeanMetadataElement interface, is used to configure the bean object. It is the basic interface for all inherited objects. Now, on the one hand, we have a leaf, by the org. Springframework. Beans. Factory. The parsing. BeanComponentDefinition said, On the other side is composite positeComponentDefinition at org.springframework.beans.factory.parsing.Com. CompositeComponentDefinition is similar to the components, because it contains addNestedComponent (ComponentDefinition component) method, It allows leaves to be added to nestedComponents in private final lists. As you can see, thanks to this list, BeanComponentDefinition and CompositeComponentDefinition ponentDefinition component is org.springframework.beans.factory.parsing.Com.

The third concept described in this article is the policy design pattern. A policy defines several objects that do the same thing in different ways. The manner in which the task is accomplished depends on the strategy employed. For example, we can go to a country. We can go there by bus, plane, boat or even car. All these methods will get us to the destination country. However, we will check our bank accounts to choose the most appropriate approach. If we have a lot of money, we will take the fastest route (probably private flight). If we don’t have enough, we’ll take the slowest (bus, bus). The bank account is used as a factor in determining the adaptation strategy.

Spring in the org. Springframework. Web. Servlet. MVC. Multiaction. MethodNameResolver class (out of date, but does not affect to study) used in the strategy design pattern. It is a parameterized implementation of the (also outdated) MultiActionController. Before we start explaining policies, we need to understand the utility of MultiActionController. This class allows the same class to handle several types of requests. As each controller in Spring, the MultiActionController executes methods in response to provided requests. Policies are used to detect which method should be used. Parsing process is realized in MethodNameResolver implementation, such as in ParameterMethodNameResolver in the same package. Methods can be resolved by multiple criteria: property mapping, HTTP request parameters, or URL paths.

@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 the previous code, the name of the method is resolved by the presence of a predefined attribute or parameter in the URL provided by the parameter mapping (by default, the parameter name is Action).

The final design pattern presented in this article is the template approach. This pattern defines the skeleton of the class’s behavior and delays the execution of some of the substeps (in the example below, a method is placed in another method that is executed only when the other method is called, and may be executed sequentially after the other behavior methods). One method is written (construct() in the example below), which is defined as final and acts as a synchronizer. It executes the methods defined by subclasses in a given order. In the real world, we can compare the template approach to housing construction. Independent of the company that builds the house, we need to start with building the foundation and only do the rest after we’re done. The execution logic will be stored in a method that we cannot change. For example, infrastructure or wall painting can be used as a template method, specific to the company building the house. We can see it in the 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 print:

Constructing very strong foundations Constructing very strong wall Spring in the org. Springframework. Context. Support. AbstractApplicationContext class using the template method. They are not one template method (construct in our case), but multiple. For example, getsFreshBeanFactory returns a new version of the internal bean factory, calling two abstract methods: refreshBeanFactory (to refresh the factory bean) and getBeanFactory (to get the updated factory bean). This method, among others, is used in public void Refresh () to throw the BeansException that constructs the application context, the IllegalStateException method (mentioned again later in Spring and in application Context analysis).

We can find some GenericApplicationContext in the same package by template method implementation example of the realization of the abstract methods (say a bit of a mouthful, it is good to read a few times) :

/** * 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; } The above shows how Spring can better organize context (the template approach) by using behavior and structural design patterns and strategies to address execution methods. It uses two structural design patterns, the proxy pattern to simplify the AOP part and the composite pattern to construct complex objects.