Chapter 3. Containers

A Spring container is the backbone of the framework. A container is basically a pool of beans created in a memory space by the framework when the application starts up. An API provided by the framework exposes methods to query these beans from the container.

We’ll start the chapter by looking at the containers and different categories. We’ll also look at details about concepts such as AutoWiring.

Containers

Understanding containers is an important task when working with the Spring Framework as they are crucial moving pieces in a Spring’s jig-saw puzzle.

During the startup process, the beans are instantiated, the associations and relationships are created, all the relationships are satisfied, and dependencies are injected. All named beans are available for querying using an API. Some beans are lazily loaded while others are loaded during the initialization of the container. This means that unless the bean is requested by our application or some other bean (as a part of dependency), the framework will not instantiate the bean, except loading singletons.

Spring containers primarily fall into two categories: Bean Factories and Application Contexts—supported by the BeanFactory and ApplicationContext classes respectively. The names are sort of misnomers, as they do not give any clue as to what these containers are and what they do.

The BeanFactory is a simple container supporting basic dependency injection, whereas ApplicationContext is an extension of BeanFactory, which has few additional bells and whistles.

In my personal opinion, I would vote for using ApplicationContext over BeanFactory—I’ll tell you why in the next few sections!

BeanFactory Container

The BeanFactory is the simplest of the two types of containers Spring has provided. The concrete factories must implement the org.springframework.beans.factory.BeanFactory interface. This factory creates and instantiates beans with all the dependent configurations as expected. So, when you query a bean, it is obtained in your client as a fully functional instance, meaning all the associations and relationships have already been created. The bean factory implementor can also invoke the customized init-method and the destroy-method.

Spring provides a few of the implementations of BeanFactory out of the box, the most common being XmlBeanFactory. As the name suggests, it reads the configuration metadata from a XML file, basically information about our beans.

Using the XmlBeanFactory in a client is very easy and straightforward. The following snippet shows the code demonstrating how to instantiate the factory. The constructor takes in an XML file passed into a FileInputStream object:

// Instantiate the factory with your beans config file
BeanFactory factory = XmlBeanFactory(new FileInputStream("trade-beans.xml"));

// Use the factory to obtain your TradeService bean
TradeService service = (TradeService) factory.getBean("tradeService");

The BeanFactory is usually preferred in small device applications such as mobile phones, etc, where resources are limited. If you are writing any standard Java or JEE application, ideally you would ditch BeanFactory to go with ApplicationContext implementation. I recommend using the ApplicationContext container unless you have a strong reason not to.

ApplicationContext Container

The ApplicationContext extends the BeanFactory, thus all the functionality of BeanFactory is already embedded in the ApplicationContext container. It also provides some advanced features such as application events, aspect functionality, and a few others as an added bonus. Ideally, we can use this container straight away due to its extended functionality.

Similar to BeanFactory implementations, there are few implementations of ApplicationContext that will soon be our favorites:

  • FileSystemXmlApplicationContext: This container loads the definitions of the beans found in the XML file located in a specified file system location. You should provide the path of the beans file to the constructor. This container will most likely be used if we have an application that has a specific location to load the config files rather than bundling them along with the deployed code.

  • ClassPathXmlApplicationContext: In this container, the XML config file is read from the classpath by the container. As long as the config file is anywhere in the classpath of our application, this container can load it. You can also have the bean files in a jar file.

    The only difference between the FileSystemXmlApplicationContext and the ClassPathXmlApplicationContext is that this context does not require the full path of the file, but expects to be in the classpath of the application.

  • WebXmlApplicationContext: This container loads the bean definitions file within a web application. This context is used mostly in Spring MVC projects or Java Web applications.

We have seen the usage of the ApplicationContext type containers in the earlier chapters, but let’s recap the usage again here. The ClassPathXmlApplicationContext is instantiated with a set of bean config files.

For example, the following snippet creates the container by loading the containers-beans.xml file.

ApplicationContext ctx = 
  new ClassPathXmlApplicationContext("containers-beans.xml");      
Employee employee = 
  ctx.getBean("employee",Employee.class);        

The snippet also shows the mechanism of querying the Employee bean.

If we have to create our container with multiple config files, we instantiate the constructor with an array of Strings:

public class ApplicationContextClient {
  private String[] configLocations = 
    new String[]{"containers-beans.xml","fundamentals-beans.xml"};

  public void testClasspathXmlApplicationContext(){
    ctx = new ClassPathXmlApplicationContext(configLocations);

    Employee employee = ctx.getBean("employee",Employee.class);
    Person person = ctx.getBean("person", Person.class);
    System.out.println(employee);
    System.out.println(person);
  }
  ...
}

Please check the API documentation for various other ways of creating the container.

The FileSystemXmlApplicationContext is no different from the ClassPathXmlApplicationContext—it accepts a config file with a file path. The following code snippet shows the mechanism to create the FileSystemXmlApplicationContext container:

ApplicationContext ctx = 
new FileSystemXmlApplicationContext("/src/main/resources/containers-beans.xml");

Employee employee = ctx.getBean("employee",Employee.class);

The choice of picking one container over the other depends on your application deployment and environment setup across the organization. Some organizations tend to support a central location for all the config files—this way, the config can be changed or tweaked without having to rebuild and re-deploy the application. Because the file location is static, the FileSystemXmlApplicationContext is best suited in this case.

Some projects may not have to read the configuration data from a centralized location, but the config files are bundled and jarred up with the project itself. The ClassPathXmlApplicationContext is the preferred choice in this case. As you may have already noticed, I have used ClassPathXmlApplicationContext extensively in this book.

Instantiating Beans

Beans are instantiated by the framework in more than one way. We have already seen in previous chapters how the beans were instantiated using constructors. You should ideally provide a constructor in your bean and corresponding metadata in the XML file. If the constructor takes any arguments, we should pass them as constructor-arg attributes in our config file. We will look into two other types of instantiating the beans—using static methods and factories.

Using Static Methods

There may be instances where we need to use static methods on some classes to create their instances—the one pattern that comes to mind immediately is a Java Singleton. The framework provides this mechanism of creating the instances via the exposed static methods rather than constructors. This type of instantiating is well suited if your classes have static factories for creating the object instances.

The procedure is simple: we write a class with a static method that would create an instance of that class. The following snippet shows an EmployeeFactory class. This class follows the Java singleton pattern—a private constructor and a static method instantiator.

public class EmployeeFactory {
  private static EmployeeFactory instance;
  private EmployeeFactory() { }
  public static EmployeeFactory getEmployeeFactory() {
    if (instance == null) {
      instance = new EmployeeFactory();
    }
    return instance;
  }
  ...
}

The static getEmployeeFactory() returns the instance of this class.

Now that our class with a static method is ready, the next step is to define the bean in our config. The configuration of the bean is similar to the ones we did earlier except that we add an additional attribute factory-method on the bean .

Let’s see how we can declare a EmployeeFactory in the XML file, using the factory-method attribute:

<bean name="employeeFactory" 
  class="com.madhusudhan.jscore.containers.factory.EmployeeFactory" 
  factory-method="getEmployeeFactory">
</bean>

The factory-method attribute invokes the respective static method on the class—the EmployeeFactory instance will be instantiated by calling the factory-method’s getEmployeeFactory method.

Note that the declaration does not mention the factory-method being static anywhere. However, it must be declared static if you wish to encounter no errors. Also note that the return type method is not imperative (it should return a non-void value); it is only known if you see the implementation of that method in the declared class, unfortunately.

Using Factory Methods

In the previous section, we created an object, using a static method. What if we wish to create the instance by using non-static methods?

Spring Framework does allow us to instantiate the beans by using non-static factory methods, too. Although it’s not straightforward, it’s not hard either to grasp.

The EmployeeCreator is a simple class that creates either employees or executives by using two factory methods. See the following code snippet:

public class EmployeeCreator {
  public Employee createEmployee() {
    return new Employee();
  }
  public Employee createExecutive() {
    Employee emp = new Employee();
    emp.setTitle("EXEC");
    emp.setGrade("GRADE-A");
    return emp;
  }
}

The main crux of using factory methods is in the configuration. The EmployeeCreator bean is declared as a normal bean. The two other beans—employee and executive are declared using two attributes—factory-bean and factory-method. See the snippet here before we understand the details:

<bean name="employee" 
    factory-bean="employeeCreator" factory-method="createEmployee"/>
<bean name="executive" 
    factory-bean="employeeCreator" factory-method="createExecutive"/>

<!-- the EmployeeCreator bean used by the above two beans -->    
<bean name="employeeCreator" 
    class="com.madhusudhan.jscore.containers.factory.EmployeeCreator"/> 

The factory-bean attribute declared on the employee and executive beans both refer to the employeeCreator bean. This is the convention to be followed when working with non-static factory methods. The factory-method points to the actual method on the employeeCreator (factory bean)—in this case, the createEmployee and createExecutive methods on the EmployeeCreator class.

You should have noticed that we do not include the class attribute in the bean definition at all. Take away points are that the actual bean is referred by factory-bean attribute, the respective methods by factory-method attribute. Also, the factory methods are not static in the above implementation.

Initialization and Destruction Callbacks

In our earlier chapter, we have learned that init-method and destroy-method attributes dictate the bean initialization and destruction. These methods will allow us to do some housekeeping jobs during the bean’s lifecycle. As you may have noticed, these attributes are used in the configuration but not in our source code.

We may wish to implement such behavior on the beans programatically too. In such cases, the Spring Framework provides us with this functionality by allowing us to implement our classes with two interfaces—the InitializingBean and DisposableBean interfaces. There is one method each in these interfaces—the afterPropertiesSet and destroy methods, respectively.

InitializingBean’s afterPropertiesSet

The LazyEmployee wishes to work only THREE days a week—the weekDays variable representing this state is set via configuration on the lazyEmployee bean. See the bean definition here:

<bean name="lazyEmployee" 
    class="com.madhusudhan.jscore.containers.lifecycle.LazyEmployee">
  <property name="weekDays" value="THREE"/>
</bean> 

When the bean is intialized, the value is set to THREE as expected. However, someone wishes to override this functionality (perhaps, the LazyEmployee’s boss!) resetting it to FIVE days—this reset has to be done after the bean has been created. In this case, the InitializingBean’s afterPropertiesSet comes to rescue.

What we need to do is to implement our LazyEmployee class with the InitializingBean interface—like this:

public class LazyEmployee implements InitializingBean {
  private String weekDays = null;
  
  public void afterPropertiesSet() throws Exception {
    System.out.println("AfterPropertiesSet called");
    weekDays = "FIVE";
  }
  ...
}

The interface has only one method, afterPropertiesSet, that needs to be implemented. This method is called after all the properties are set and bean is created. Note that the values of these properties are picked up from the config file. In this case, the weekDays value was already set in the XML file with THREE. However, before handing over the already created bean to us, the framework called the afterPropertiesSet method which reset the value to FIVE.

In essence, implementing the InitializingBean interface provides the opportunity to initialize (or reset) the bean’s configuration.

DisposableBean’s destroy

The DisposableBean interface has only one callback method—destroy—which will be called before the Spring container shuts down—thus giving an opportunity to do cleanup of the resources if any.

Continuing with the same example of LazyEmployee, this time, the class implements the DisposableBean interface and its one method, destroy. The souce code is shown in the following snippet:

public class LazyEmployee implements DisposableBean {
  private String weekDays = null;

  public void destroy() throws Exception {
    System.out.println("Destroy called");
    // do your cleanup here
  }
  ...
}

When the context is closed by calling the close method on the ClassPathXmlApplicationContext class, the destroy method will be invoked—thus giving us the chance to perform housekeeping before the bean gets reclaimed.

Declarative or Programmatic Callbacks?

We know that there are two options for bean initialization or destruction functionality. We can use init-method (or destroy-method) by declaring them in configuration files. Or, we can achieve the same result by implementing the InitialzingBean’s afterPropertiesSet (or DispozableBean’s destroy) method in our class.

Let me tell you—there’s another way of doing this job too—using @PostConstruct and @PreDestroy annotations. We might see these annotations in action when we learn about annotations in the coming chapters.

You might be wondering what is the preferred option? My vote is always to the configuration side. In the programmatic callbacks, what we are doing is using the Spring’s interfaces—thus coupling our code to a third-party dependency. This restricts our future migration plans—should you wish to move to some other Dependency Injection framework (say, Google’s Guice), you would have to refactor the code to remove these dependencies.

Remember, the rule of thumb is to avoid vendor lockins as much as possible!

Spring allows us to use all the three types of callbacks that we have discussed so far. But there is a subtle difference if you use all of them in a project—the precedence of one over the other. Spring dictates that if all three types (annotation, programmatic, and config callbacks) are present, the order in which they take precedence is:

  1. Annotation based—@PostConstruct and @PreDestroy

  2. Programming based—afterPropertiesSet and destroy

  3. Config based—the init-method and destroy-method

Event Handling

Sometimes, we may want to react to an event that happened in the container so we can do some custom processing. For example, we want our FilePoller component to start polling a directory for incoming files after our container was started. Framework has a mechanism to notify us when the context has been started (or stopped). We’ll see the mechanics of this in a minute.

There may be a requirement to publish some messages from our beans too—for example, the FilePoller might notify interested parties to say that it has received a file or it has processed an encrypted file, and so on. The Spring framework provides a way to publish and listen to the custom events too.

The ApplicationContext publishes certain types of events when loading the beans. For example, a ContextStartedEvent is published when the context is started and ContextStoppedEvent is published when the context is stopped. We can have our beans receive these events if we wish to do some processing on our side based on these events. We can also publish our own events.

Let’s see the procedure involved in listening to the events first.

Listening to Context Events

The ApplicationContext publishes certain types of events when loading the beans. For example, a ContextStartedEvent is published when the context is started and ContextStoppedEvent is published when the context is stopped.

We can let our beans receive these events to do some processing based on these events. In order to listen to the context events, our bean should implement the ApplicationListener interface. This interface has just one method: onApplicationEvent(ApplicationEvent event). The ContextStartedEventListener is one such class that expects to receive any events related to context’s startup actions.

The following example creates this class:

public class ContextStartedEventListener 
  implements ApplicationListener<ContextStartedEvent> {
  public void onApplicationEvent(ContextStartedEvent event) {
    System.out.println(
  "Received ContextStartedEvent application event:"+event.getSource());
  } 
}

Whenever the ContextStartedEvent is published, this bean will receive it without fail. Currently the onApplicationEvent does not do anything apart from shouting to the world that it has received the event. But we can do pretty much anything here—like starting a brand new component, creating resource loaders, sending an email, and so on.

Now that we have our event listener, the next step is to bind the listener to the context. We do this by declaring the bean in our config file as shown here:

<bean name="contextStartEventListener" 
  class="com.madhusudhan.jscore.containers.event.ContextStartedEventListener"/>  

Once the context is started, the listener will receive a start event as expected.

Spring context publishes the following types of events:

ContextStartedEvent

This event is published when the ApplicationContext is started. All beans receive a start signal once the ApplicationContext is started. The activities such as polling to database or observing a file system can be started once we receive this type of event.

ContextStoppedEvent

This is the opposite of the start event. This event is published when the ApplicationContext is stopped. Our bean receives a stop signal from the framework so we can do housekeeping on the bean.

ContextRefreshedEvent

A refresh event is emitted when the context is either refreshed or initialized.

ContextClosedEvent

This event occurs when the ApplicationContext is closed. From closed state, a context cannot be restarted or refreshed.

RequestHandledEvent

This is a web-specific event informing the receivers that a web request has been received.

For completeness, run the following client program which should start, stop, and refresh the context:

public class ContextEventListenerClient {
  private ConfigurableApplicationContext ctx = null;
  public void test() {
    ctx = new ClassPathXmlApplicationContext("containers-events-beans.xml");
    ctx.start();
    ctx.refresh();    
    ctx.stop();    
  }
  public static void main(String args[]) {
    ContextEventListenerClient client = new ContextEventListenerClient();
    client.test();
  }
}

Our listener will receive the appropriate events.

Publishing Custom Events

It’s a fairly simple task to publish custom events. Let’s suppose we want to publish an event whenever we receive a file larger than 100Mb.

In order to prepare our application for publishing custom events, we need four code structures to develop: The publisher, the listener, the event, and the client. Let’s develop all of them here.

First we have to create an event by extending the ApplicationEvent—as our HugeFileEvent shown here:

public class HugeFileEvent extends ApplicationEvent {
  private String fileName = null;
  public HugeFileEvent(Object source, String fileName) {
    super(source);
    this.fileName = fileName;
  }
}

As mentioned earlier, the event class must extend the ApplicationEvent class.

Now, we need to create a publisher—HugeFileEventPublisher in this case. This class implements Framework’s ApplicationEventPublisherAware interface so it can be injected with a ApplicationEventPublisher object by calling the setApplicationEventPublisher method. The ApplicationEventPublisher has one method—publishEvent—which is used to publish events.

public class HugeFileEventPublisher implements ApplicationEventPublisherAware{
  private ApplicationEventPublisher pub = null;
  
  public void setApplicationEventPublisher(ApplicationEventPublisher pub) {
    this.applicationEventPublisher = pub;
  }
   
  public void publish(String fileName){
    System.out.println("Publishing a HugeFileEvent, file is: "+fileName);
    HugeFileEvent hugeFileEvent = new HugeFileEvent(this,fileName);
    pub.publishEvent(hugeFileEvent);
  }
}

The third piece of code is our listener—no point in publishing events if there is no listener (a bit like one-sided love!). We have already seen the implementation of a listener in our earlier section—here’s the HugeFileEventListener code shown for completeness:

public class HugeFileEventListener implements 
  ApplicationListener<HugeFileEvent> {
  public void onApplicationEvent(HugeFileEvent event) {
    System.out.println("Received Event:"+event.getSource());
  }
}

Now that we have the basic classes in place, all we need is to wire them up and call them from a client. We need to declare the publisher and listener beans as shown in the following snippet:

<bean name="hugeFileEventPublisher" 
 class="com.madhusudhan.jscore.containers.event.publish.HugeFileEventPublisher"/>
    
<bean name="hugeFileEventListener" 
 class="com.madhusudhan.jscore.containers.event.publish.HugeFileEventListener"/>

Let’s create a test client to make these code pieces work for us:

public class HugeFileEventClient {
  private ApplicationContext ctx = null;
  private HugeFileEventPublisher hugeFileEventPublisher = null;
  
  public void test() {
    ctx = new ClassPathXmlApplicationContext("containers-events-publish-beans.xml");
    hugeFileEventPublisher = 
      ctx.getBean("hugeFileEventPublisher", HugeFileEventPublisher.class);
    hugeFileEventPublisher.publish("huge-file.txt");
  }
  public static void main(String args[]) {
    HugeFileEventClient client = new HugeFileEventClient();
    client.test();
  }
}

Once the context is created, fetch the publisher bean and invoke the publish method to publish an event. The event is created in the publish and is sent to the context. The listener then gets this event (framework delivers the event to all the context listeners) and invokes the appropriate processing.

Event Model Is Single Threaded

One important thing to keep in mind when working with Spring events handling is that Spring’s event handling is single threaded—it is primarily synchronous in nature. That is, if an event is published, until and unless all the receivers get the message, the processes are blocked and the flow will not continue. If you have multiple listeners listening for an event, this single-thread model may hamper the performance of the application. Hence, care should be taken when designing your application if event handling is to be used.

Personally I would not depend on Spring’s Events as it is not only single threaded but also locks us to the framework. You have to implement the framework’s interfaces, thus making it worse when you wish to implement other frameworks in the future. There are plenty of open source alternatives such as EventBus, Event Listener Framework (elf), or even Spring’s Integration (although I admit Spring’s Integration or JMS might be overkill for such a simple event mechanism).

See my other book Just Spring Integration if you’re interested in learning Spring’s Integration.

Autowiring

When creating a bean, we used to set the properties of the bean by using either property or constructor-arg attributes. However, to save us typing, Spring has a sophisticated concept of autowiring these relationships and dependencies. This means that you don’t have to explicitly mention the properties and their values, but setting the autowire property to a specfic value allows the framework to wire them with appropriate properties. This mechanism is called autowiring.

By default, there is no autowiring enabled (the same as setting the autowire attribute to “no”). Also, note that autowiring works only for references—the normal Java primities and Strings cannot be set using autowiring.

There are fundamentally three variations of autowiring, by name, by type, by constructor, as explained in the following sections—four if you consider mixing autowiring and explicit wiring!

Autowiring byName

When autowiring byName is enabled, the framework tries injecting the dependencies by matching the names to the property fields.

This is easily understood by an example. Let’s say we have a TradeReceiver bean which has two properties—named as tradePersistor and tradeTransformer beans. When we choose the autowiring mechanism to be byName, Framework will locate these dependednt beans (as long as they are named exactly as the TradeReceiver’s properties) from the context and inject into the TradeReceiver bean.

First, here’s the definition of the TradeReceiver class here:

public class TradeReceiver {
  private TradePersistor tradePersistor = null;
  private TradeTransformer tradeTransformer = null;
  ...
}

Our usual way is to define all three beans in the XML config file, then pass the references of persistor and transformer to TradeReceiver. However, with autowiring, you don’t have to go this far.

In order to enable autowiring byName, we need to set the attribute autowire to byName on the bean in the config:

<bean name="tradeReceiver" 
  class="com.madhusudhan.jscore.containers.autowire.TradeReceiver" 
  autowire="byName"/>

<bean name="tradePersistor" 
  class="com.madhusudhan.jscore.containers.autowire.TradePersistor"/>
<bean name="tradeTransformer" 
  class="com.madhusudhan.jscore.containers.autowire.TradeTransformer"/>

In addition to this, we have defined the tradePersistor and tradeTransformer beans in the config too.

Did you notice we did not define any properties such as tradePersistor or tradeTransformer on the tradeReceiver bean? We would have normally set these properties by declaring them explicitly as shown here:

<bean name="tradeReceiver" 
  class="com.madhusudhan.jscore.containers.autowire.TradeReceiver">
  <property name="tradePersistor" ref="tradePersistor"/>
  <property name="tradeTransformer" ref="tradeTransformer"/>
        </bean>

How does this work then? Well, the attribute autowire="byName" does the magic for us behind the scenes. This setting instructs the container to look for two properties with the same names as tradeReceiver’s variable names (tradePersistor and tradeTransformer in this case). The container looks at all the beans instantiated and tries to match them with the beans with the variable names of tradeReceiver. If matches are found, it will inject those beans straightaway. Otherwise, it will throw exceptions thus notifying the bean creation issues. Note that the autowiring principle works for only references. You have to mix and match the autowiring and explicit wiring (hold on, we will look at mixing these wiring types in couple of minutes).

Autowiring byType

Similar to byName, we need to set the autowire property to byType in order to enable this type of autowiring. In this case, instead of looking for a bean with the same names, the container searches for the same types. Taking the same example of TradeReceiver, setting the autowire="byType" tells the container that it should look for a bean of type TradePersistor and another one with a type of TradeTransformer.

<bean name="tradeReceiver" 
  class="com.madhusudhan.jscore.containers.autowire.TradeReceiver" 
  autowire="byType"/>

If the container finds the appropriate types, it will inject them into the bean. In the above case, framework looks for two types, com.madhusudhan.jscore.containers.autowire.TradePersistor and com.madhusudhan.jscore.containers.autowire.TradeTransformer in the config file. If it finds them, they will be injected into the tradeReceiver bean. However, if it finds more than one bean with the same type defined in the config, a fatal exception is thrown.

Autowiring by constructor

It’s not that hard to guess about our next autowiring counterpart—autowiring by constructor. This is similar to byType but applies to bean’s constructor arguments only. As the name suggests, the constructor argument will be satisfied by searching for that type in the context. That is, if a bean has a constructor that takes an argument of another bean type, the container looks for that reference and injects it.

For example, we define a TradePersistor class with a single constructor that takes a datasource object:

public class TradePersistor {
  public TradePersistor (DataSource datasource){ ..}
}

If we enable autowiring by constructor, the container looks for an object of the type DataSource and injects it into the TradePersistor bean. You enable autowiring by constructor as shown here:

<bean name="tradePersistor" 
  class="com.madhusudhan.jscore.containers.autowire.TradePersitor"
        autowire="constructor"/>

Mixing Autowiring with Explicit Wiring

We can get the best of both worlds by using autowiring and explicit wiring. Any ambiguities encountered while autowiring can be dealt with using explicit wiring.

For example, in the following snippet, the tradeReceiver is injected with two beans—the tradePersitor injected explicitly using our good old way, while the tradeTransformer is wired automatically using a byName variation.

<bean name="tradeReceiver" 
  class="com.madhusudhan.jscore.containers.autowire.TradeReceiver" 
  autowire="byName">
  <!-- The tradePersistor is set traditionally -->
  <property name="tradePersistor" ref="tradePersistor"/>
</bean>

<bean name="tradePersistor" 
  class="com.madhusudhan.jscore.containers.autowire.TradePersistor"/>
<bean name="tradeTransformer" 
  class="com.madhusudhan.jscore.containers.autowire.TradeTransformer"/>

We can also switch off autowiring for specific beans should we wish to do so. All we need to do is to set autowire-candidate to false on the bean definition—see here for an example—the tradePersistor is not interested in participating in autowiring mode:

<bean name="tradePersistor" 
  class="com.madhusudhan.jscore.containers.autowire.TradePersistor" 
  autowire-candidate="false"/>

Although autowiring saves us from writing extra metadata declarations, personally I wouldn’t go for it. I prefer the explicit wiring style—less ambiguity and more readability.

Summary

This chapter completes our journey into core Spring. It explains the fundamentals of containers and their usage. It then delves into using autowiring beans where you do not have to set properties on the beans. It then explains various ways of instantiating the beans, such as static methods or factory methods. We have also seen event handling supported by the framework.

One of the important aspect of Spring is its support for enterprise features such as Spring JMS and Database. The next chapter explains the simplification Spring has brought into the Java messaging world.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.30.62