IoC container is a framework for implementing automated dependency injection. It contains object creation for the longer ways to use and injects dependencies within the class. The IoC container constructs an object of the selected class and also injects all the dependency objects via a constructor, a property, or a function at execution time and disposes it at a suitable time. This approach helps to create and manage objects manually.

In IoC, we can define objects with constructor arguments that are the factory method function and properties that can set on the object instance after it is constructed or returned from a factory function. The container then injects those dependencies when it constructs the bean. We can consider this approach as Inversion of Control (IoC), of the bean itself containing the instantiation or location of its dependencies by operating direct construction of classes or a mechanism such as the Service Locator design pattern.

Here's How to Land a Top Software Developer Job

Full Stack Developer - MERN StackExplore Program
Here's How to Land a Top Software Developer Job

The org.springframework.beans and org.springframework.context packages are the foundation for Spring Framework's IoC container. The BeanFactory interface delivers an advanced configuration mechanism ability to manage any type of object. 

ApplicationContext is a sub-interface of BeanFactory. It adds more effortless integration with Spring's AOP features— message resource handling capability, event publication, and application-layer-specific contexts such as the WebApplicationContext for use in web applications.

BeanFactory has the capability of the configuration framework and fundamental functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is an exclusive superset of the BeanFactory and  can be used within its definitions of Spring's IoC container.

In Spring, the objects that construct the backbone of your application and that are controlled by the Spring IoC container are called beans. A bean is an object that is assembled, instantiated, and can be managed by a Spring IoC container. It can be specified using one of the multiple objects in the application. We can consider Beans with their dependencies among them, which are reflected in the configuration metadata operated by a container.

Container Overview

The IoC container is accountable to instantiate, configure and construct the objects. It gets pieces of information from the XML file and performs accordingly. The main tasks that be executed by the IoC containers are:

  • to set and instantiate the application class 
  • to set the configuration of the object 
  • to construct the dependencies among the objects

Here are two kinds of IoC containers:

  • BeanFactory
  • ApplicationContext

ApplicationContext

The interface org.springframework.context.ApplicationContext represents the Spring IoC container. The ApplicationContext interface is constructed on top of the BeanFactory interface. It integrates some additional functionality than BeanFactory, such as easy integration with Spring's AOP, message resource handling (for I18N), event propagation, and application-layer detailed context (e.g. WebApplicationContext) for the web application. So it is more suitable to use ApplicationContext than BeanFactory.

Using BeanFactory

BeanFactory contains the XmlBeanFactory class that implements for the BeanFactory interface. We can use BeanFactory to create the instance of XmlBeanFactory class as shown below:

Resource resource=new ClassPathResource("applicationContextexample.xml");  

BeanFactory factory=new XmlBeanFactory(resource);  

The constructor of XmlBeanFactory class obtains the Resource object, and it allows us to pass the resource object to construct the object of BeanFactory.

Using ApplicationContext interface defines and implements the ClassPathXmlApplicationContext 

Example:

ApplicationContext context =    new ClassPathXmlApplicationContext("applicationContextexample.xml");  

The constructor of ClassPathXmlApplicationContext class gets the string and it can help to pass the name of the XML file and create the instance of ApplicationContext.

  • Configuration Metadata

To configure metadata Spring, IOC container consumes the metadata. It defines the Spring container to instantiate, configure, and construct the objects in a particular application. In a basic example, we can configure metadata to define an XML-based format. 

We can use the below types of metadata with Spring container.

  • Annotation-based configuration: It defines the annotation-based configuration metadata.
  • Java-based configuration: It provides certain features using the Spring JavaConfig project that is part of Spring Framework. Using this, we can determine beans external to the existing application classes. 

To use these unique features, we can use @Configuration, @Bean, @Import, and @DependsOn annotations.

Spring Boot jars contain metadata files that describe all supported configuration properties.

We create metadata files to allow IDE developers to deliver contextual support and “code completion” with application. properties or application.yml files.

Mainly metadata file is developed automatically at compile-time and annotated with @ConfigurationProperties.

Metadata Format:

Configuration metadata files are discovered within the jars under META-INF/spring-configuration-metadata.json. They operate a JSON format with items classified under either “groups” or “properties” and added values guidance categorized under "hints", as illustrated in the example below:

These bean definitions correspond to the real objects that create your application.

We can determine service layer objects, data access objects (DAOs), presentation objects with Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, etc.

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

The below example indicates the simple structure of XML-based configuration metadata:

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

<beans xmlns="http://www.test.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.test.org/schema/beans

           http://www.test.org/schema/beans/spring-beans.xsd">

  <bean id="..." class="...">

    <!-- collaborators and configuration for this bean will be define here -->

  </bean>

  <bean id="..." class="...">

    <!-- collaborators and configuration for this bean  will be define here -->

  </bean>

  <!-- more bean definitions go here -->

</beans>

  • Instantiating a Container

To instantiate a Spring IoC container is easy. We can define the path to an ApplicationContext constructor. These are resource strings that let the container load configuration metadata from different external resources, for example local file system, from the Java CLASSPATH, etc.

Example:

ApplicationContext contextExample =

    new ClassPathXmlApplicationContext(new String[] {"services.xml", "dao.xml"});

service layer objects (services.xml) configuration file:

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

<beans xmlns="http://www.test.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.test.org/schema/beans

           http://www.test.org/schema/beans/spring-beans.xsd">

  <!-- services -->

  <bean id="Store"

        class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">

    <property name="DepartmentDao" ref="DepartmentDao"/>

    <property name="itemDao" ref="itemDao"/>

    <!-- additional collaborators and configuration for this bean go here -->

  </bean>

  <!-- more bean definitions for services go here -->

</beans>

The following example shows the data access objects dao.xml file:

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

<beans xmlns="http://wwwt.est/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.test.org/schema/beans

           http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="DepartmentDao"

      class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapDepartmentDao">

    <!-- additional collaborators and configuration for this bean go here -->

  </bean>

  <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao">

    <!-- additional collaborators and configuration for this bean go here -->

  </bean>

  <!-- more bean definitions for data access objects go here -->

</beans>

The following example shows the data access objects dao.xml file:

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

<beans xmlns="http://wwwt.est/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.test.org/schema/beans

           http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="DepartmentDao"

      class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapDepartmentDao">

    <!-- additional collaborators and configuration for this bean go here -->

  </bean>

  <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao">

    <!-- additional collaborators and configuration for this bean go here -->

  </bean>

  <!-- more bean definitions for data access objects go here -->

</beans>

Composing XML-Based Configuration Metadata:

To compose XML-based configuration we have to define bean that span multiple XML files. Each individual XML configuration file represents a logical layer or module in your architecture.

We can use the application context constructor to load bean definitions from all these XML fragments. This constructor accepts multiple Resource locations. 

Example:

<beans>

    <import resource="testservices.xml"/>

    <import resource="resources/messageSource.xml"/>

    <import resource="/resources/themeSource.xml"/>

    <bean id="beantest1" class="..."/>

    <bean id="beantest2" class="..."/>

</beans>

  • Using the Container

The ApplicationContext is the interface for a refined factory competent in holding a registry of additional beans and their dependencies. 

Using the method T getTestBean(String name, Class<T> requiredType), you can retrieve instances of your beans.

The ApplicationContext allows you to read bean descriptions and access them shown in below examples:

// create and configure beans

ApplicationContext context =

    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

// retrieve configured instance

PetStoreServiceImpl service = context.getBean("Store", PetStoreServiceImpl.class);

// use configured instance

List userList = service.getUsernameList();

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

Bean Overview

A Spring IoC container contains more than one bean. We constructed these beans with the configuration metadata that we can provide to the container, for example, in the form of XML <bean/> definitions.

Within the container itself, these bean descriptions are represented as BeanDefinition objects, which include (among other information) the following metadata:

  • A package-qualified class name: It is the basic implementation class of the bean being defined.
  • Bean behavioral configuration elements, with the state, should behave using the container (scope, lifecycle callbacks, and so forth).
  • References to different beans that are directed for the bean to do its work; these references are also called collaborators or dependencies.
  • Additional configuration settings to set in the newly constructed object, for example, the number of connections to operate in a bean that contains a connection pool, or the size limit of the pool.

In Bean, this metadata renders to a set of properties that help create a particular bean definition.

Here ApplicationContext implements the registration and allows existing objects that are maintained outside the container using the getBeanFactoy() that gives the output of BeanFactory—DefaultListableBeanFactory. 

DefaultListableBeanFactory helps the registration via the methods registerSingleton(..) and registerBeanDefinition(..).

  • Naming Beans

Each bean can have one or more unique identifiers using the container that can publish the bean. It contains one identifier, but in certain situations, it may contain more than one. 

In XML-based configuration metadata, we have two types of attributes— id, and name, which we can define using the bean identifiers. ID enables users to provide one unique id. It may contain specific alphanumeric and special character names. Using the name attribute, we can give the comma and semicolon and white space.

In Bean, when naming beans, one must follow the standard naming convention, i.e the Java convention. The name of bean should be in lower-case and as per user preference, it can also be defined in camel-case such as 'orgManager', 'orgService', 'EmployeeDao', 'loginController'. Naming beans makes configuration simple to read and easy-to-understand.

Aliasing a Bean Outside the Bean Definition:

With the Bean definition, we can use one or more names using the bean with the combination of the Id and name attribute. These names are equal to the aliases to the bean and it’s the best approach to define a certain situation.

To specify the aliases we can use the large application where we can split the configuration with its own definitions.

In XML-based configuration metadata, we can use the <alias/> element to achieve this.

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

  • Instantiating Beans

Using a bean definition, we can create one or more objects in straightforward ways. We can also encapsulate the metadata that the bean definition allows us to create as per the actual object.

We can use XML-based configuration metadata and can define the type using a class of objects that we can instantiate within the class attribute using the <bean/> element. When we create a class, we can consider it as an attribute that has the internal class property on a BeanDefinition. We can use the Class property in one of two ways:

  • To define the bean class, we can construct it in the scenario where the container defines the bean when we call its constructor using the new operator.
  • To create the actual class, which has the static factory function method that calls to create the object where the containers call a static method.

Here, we have a factory method function in a certain class that we can use while creating the bean. Also, the object type returned from the occurrence of the static factory class methods can be used in the same or another class.

Create Inner Class Name

To configure a bean definition for a certain static nested inner class. We can use the binary name of the inner class.

Example: Here we have the class Foo in a certain com.example package file, and Foo class may contain the static inner class named Bar, the value of the ‘class’ attribute would be as per this syntax.

test.example.Foo$Bar

  • Instantiation With a Constructor:

While creating a bean using the constructor mechanism, many classes can be reachable with Spring compatibility. This class can be developed and maintained using certain codebases.

The Spring IoC container can handle virtually any class as per certain logic.

For example, if we need to define a certain connection pool using the JavaBean specification, Spring can manage it as well.

Using XML-based configuration metadata, you can define the bean class as per the below example:

  1. <bean id="TestBean" class="test.TestBean"/>
  2. <bean name="otherExample" class=test.TestBean.test"/>
  • Instantiation With a Static Factory Method:

We use the class attribute to specify the class containing the static factory method when defining a bean. Also, the attribute factory method which we can call and define to return a live object is used to specify the name of the factory method itself. It is treated as it had been created through a constructor.

The below definition infers that we can create the bean by calling the factory method. The definition, however, does not define the type (class) of the returned object, but only the class containing the factory method. In this example, the createInstance() function method must be the static method.

<bean id="TestclientService"

      class="examples.TestclientService"

      factory-method="createInstance"/>

public class TestclientService{

  private static TestclientService testclientService= new TestclientService ();

  private TestclientService() {}

  public static TestclientService createInstance() {

    return clientService;

  }

}

  • Instantiation Using an Instance Factory Method:

To instantiate an instance factory, we can create a method that invokes a non-static function method of an existing bean using the container to create a new bean. 

We should leave the class attribute empty to use this method, and in the the factory-bean attribute, specify the name of a bean in the current container that has the instance function method that is to be called to create the object. We can set the name of the factory method with its factory-method attribute.

<!-- the factory bean, which contains a method called createInstance() -->

<bean id="serviceLocator" class="test.DefaultServiceLocator">

  <!-- inject any dependencies needed by this locator bean -->

</bean>

<!-- the bean to be created via the factory bean -->

<bean id="clientService"

      factory-bean="serviceLocator"

      factory-method="createClientServiceInstance"/>

public class DefaultServiceLocator {

  private static ClientService clientService = new ClientServiceImpl();

  private DefaultServiceLocator() {}

  public ClientService createClientServiceInstance() {

    return clientService;

  }

}

<bean id="serviceLocator" class="test.DefaultServiceLocator">

  <!-- inject any dependencies required by this locator bean -->

</bean>

<bean id="clientService"

      factory-bean="serviceLocator"

      factory-method="createClientServiceInstance"/>

<bean id="DepartmentService"

      factory-bean="serviceLocator"

      factory-method="createDepartmentServiceInstance"/>

public class DefaultServiceLocator {

  private static ClientService clientService = new ClientServiceImpl();

  private static DepartmentService accountService = new DepartmentServiceImpl();

  private DefaultServiceLocator() {}

  public ClientService createClientServiceInstance() {

    return clientService;

  }

  public AccountService createAccountServiceInstance() {

    return accountService;

  }

}

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

Dependencies

A mostly standardized application does not comprise a single object. Using dependencies, we can create a simple application that has a certain object that work together to provides the best solution for end user. In this section, we will understand how we can define a certain number of bean definitions and develop a stand-alone fully fledged application with the help of all objects.

  • Dependency Injection

Using Dependency injection, we can describe a technique where each object has its dependencies. We can use objects to create constructor arguments to define a factory method or properties that can be set on the object instance after it is constructed or returned from a factory method.

The container can inject the dependencies while constructing the bean. This technique is essentially inverse (hence known as Inversion of Control (IoC)) of the bean controlling its instantiation or location of its dependencies on its own by using the Service Locator pattern which can be considered as direct construction of classes.

  • Constructor-Based Dependency Injection

The container gathering a constructor with several arguments achieves constructor-based DI, each describing a dependency. Calling a static factory method with distinct arguments to construct the bean is almost equivalent, and therefore arguments for a constructor and a static factory method are treated similarly. 

The following example illustrates a class (a POJO (plain old java object) that has no dependencies on container specific interfaces, base classes or annotations) that can only be dependency-injected with constructor injection. 

public class UserLister {

  // the UserLister has a dependency on a UserFinder

  private UserFinder userFinder;

  // a constructor so that the Spring container can 'inject' a UserFinder

  public UserLister(UserFinder userFinder) {

      this.UserFinder = userFinder;

  }

  // business logic that actually 'uses' the injected UserFinder is omitted...

}

  • Constructor Argument Resolution

Constructor argument checks for any ambiguity in the constructor arguments of a bean definition. In case of no ambiguity, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. 

Example:

package x.y;

public class Test {

  public Foo(Test1 test1, Test2 test2) {

      // ...

  }

}

This below configuration with constructor argument indexes and/or types explicitly in the <constructor-arg/> element.

<beans>

  <bean id="test" class="x.y.Test">

      <constructor-arg ref="test1"/>

      <constructor-arg ref="test"/>

  </bean>

  <bean id="test1" class="x.y.Test1"/>

  <bean id="test2" class="x.y.Test2"/>

</beans>

  • Constructor Argument Type Matching

Here, a container can operate to define a type matching with the easy, certain type attribute. 

Example:

<bean id="sampleBean" class="samples.SampleBean">

<constructor-arg type="int" value="8500000"/>

<constructor-arg type="java.lang.String" value="52"/>

</bean>

  • Constructor Argument Index

Here, we can speciy the index attribute to define explicitly the index of constructor arguments. 

Example:

<bean id="sampleBean" class="samples.SampleBean">

<constructor-arg index="0" value="8500000"/>

<constructor-arg index="1" value="52"/>

</bean>

To resolve the ambiguity of different types of certain values, we can define the index that can solve the ambiguity of a constructor that has two arguments of the same data type. Note that the index is 0 based.

  • Constructor Argument Name

As of Spring 3.0  we can use the constructor parameter name for value disambiguation:

<bean id="sampleBean" class="samples.SampleBean">

<constructor-arg name="years" value="8500000"/>

<constructor-arg name="answer" value="52"/>

</bean>

package samples;

public class SampleBean {

  // Fields omitted

  @ConstructorProperties({"years", "Answer"})

  Public SampleBean(int years, String Answer) {

      this.years = years;

      this.Answer = Answer;

  }

}

  • Setter-Based Dependency Injection

The container calling setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean accomplishes setter-based DI.

The below example indicates a class that can only be dependency-injected using better setter injection. This class is a POJO that has no dependencies on base classes, annotations, or container-specific interfaces.

public class UserLister {

  // the UserLister has a dependency on the UserFinder

  private UserFinder userFinder;

  // a setter method so that the Spring container can 'inject' a UserFinder

  public void setUserFinder(UserFinder userFinder) {

      this.userFinder = userFinder;

  }

  // business logic that actually 'uses' the injected UserFinderis omitted...

}

Here in the above example, the ApplicationContext helps constructor- and setter-based DI for the beans it handles. It also enables setter-based DI after some dependencies are injected already via the constructor method. We can set up and configure the dependencies as a BeanDefinition. We can define PropertyEditor instances to transform properties from one format to another. 

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

The below example uses XML-based configuration metadata for setter-based DI.

A small part of a Spring XML configuration file defines few bean definitions:

<bean id="sampleBean" class="samples.SampleBean">

<!-- setter injection using the nested <ref/> element -->

<property name="beanOne"><ref bean="anotherSampleBean"/></property>

<!-- setter injection using the neater 'ref' attribute -->

<property name="beanTwo" ref="yetotherBean"/>

<property name="integerProperty" value="1"/>

</bean>

<bean id="anotherSampleBean" class="samples.otherBean"/>

<bean id="yetotherBean" class="samples.YetotherBean"/>

public class sampleBean {

  private AnotherBean beanOne;

  private YetotherBean beanTwo;

  private int i;

  public void setBeanOne(otherBean beanOne) {

      this.beanOne = beanOne;

  }

  public void setBeanTwo(YetotherBean beanTwo) {

      this.beanTwo = beanTwo;

  }

  public void setIntegerProperty(int i) {

      this.i = i;

  }

  • Dependency Resolution Process

The container performs bean dependency solution as follows:

  • The ApplicationContext is initiated and initialized with configuration metadata which represents all the beans. Configuration metadata can be used with Java programming, XML, or annotations.
  • For each bean, its dependencies are described in the form of properties, constructor arguments, or the static-factory method. These dependencies are delivered to the bean, when the bean is actually created.
  • Each property or constructor argument is an essential definition of the value to set or a reference to another bean in the container.
  • Each property or constructor argument which is a value is transformed from its prescribed format to the actual type of that property or constructor argument. By default, Spring can transform a value provided in string format to all built-in types, such as int, long, String, boolean, etc.

The below example uses XML-based configuration metadata for setter-based DI. 

A small part of a Spring XML configuration file defines few bean definitions:

<bean id="sampleBean" class="samples.SampleBean">

<!-- setter injection using the nested <ref/> element -->

<property name="beanOne"><ref bean="anotherSampleBean"/></property>

<!-- setter injection using the neater 'ref' attribute -->

<property name="beanTwo" ref="yetotherBean"/>

<property name="integerProperty" value="1"/>

</bean>

<bean id="anotherSampleBean" class="samples.otherBean"/>

<bean id="yetotherBean" class="samples.YetotherBean"/>

public class sampleBean {

  private AnotherBean beanOne;

  private YetotherBean beanTwo;

  private int i;

  public void setBeanOne(otherBean beanOne) {

      this.beanOne = beanOne;

  }

  public void setBeanTwo(YetotherBean beanTwo) {

      this.beanTwo = beanTwo;

  }

  public void setIntegerProperty(int i) {

      this.i = i;

  }

Dependencies and Configuration in Detail

We can determine bean properties and constructor arguments as references to different operated beans (collaborators), or as values specified inline. Spring's XML-based configuration metadata sustains sub-element types within its <property/> and <constructor-arg/> elements for this objective.

Straight values (primitives, Strings, and so on):

The value attribute of the <property/> element determines a property or constructor argument as a human-readable string representation.

JavaBeans PropertyEditors are used to transform these string values from a String to the basic type of the property or argument.

<bean id="testDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<!-- results in a setDriverClassName(String) call -->

<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:1809/testdb"/>

<property name="username" value="root"/>

<property name="password" value="pwd123@"/>

</bean>

The below example takes the p-namespace for even more easy and short XML configuration.

<beans xmlns="http://www.yourorg.org/schema/beans"

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xmlns:p="http://www.yourorg.org/schema/p"

     xsi:schemaLocation="http://www.yourorg.org/schema/beans

     http://www.yourorg.org/schema/beans/spring-beans.xsd">

<bean id="testDataSource" class="org.apache.commons.dbcp.BasicDataSource"

      destroy-method="close"

      p:driverClassName="com.mysql.jdbc.Driver"

      p:url="jdbc:mysql://localhost:1809/mydb"

      p:username="root"

      p:password="pwd123@"/>

</beans>

Here we can define and configure a java.util.Properties instance as:

<bean id="mappings"

    class="org.test.beans.factory.config.PropertyPlaceholderConfigurer">

 <!-- typed as a java.util.Properties -->

 <property name="properties">

    <value>

       jdbc.driver.className=com.mysql.jdbc.Driver

       jdbc.url=jdbc:mysql://localhost:1809/mydb

    </value>

 </property>

</bean>

  • The idref Element

Using the idref element we can create an error-proof way to define the id (string value - not a reference) of other beans inside the container to a <constructor-arg/> or <property/> element.

<bean id="testTargetBean" class="..."/>

<bean id="testClientBean" class="...">

  <property name="targetName">

      <idref bean="testTargetBean" />

  </property>

</bean>

The above example of bean definition snippet is similar (at runtime) to the following snippet:

<bean id="testTargetBean" class="..." />

<bean id="client" class="...">

  <property name="targetName" value="testargetBean" />

</bean>

  • References to Other Beans (Collaborators)

The ref element is the definitive element inside a <constructor-arg/> or <property/> definition element. We can also define the value of the defined property of a bean to be a reference to another bean (a collaborator) handled by the container. 

The referenced bean is a dependency of the bean where its property will be defined, (If the collaborator is a singleton bean, it may be initialized already by the container.) All references are eventually a reference to another object. 

Scoping and validation depend on whether you determine the id/name of the different object via the bean, local, or parent attributes.

Selecting the target bean through the bean attribute of the <ref/> tag is the most general form, and permits the creation of a reference to any bean in the exact container or parent container.

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

The value of the bean attribute can be exact as per its id attribute of the target bean, or certain values in the name attribute of the target bean.

<ref bean="testBean"/>

Identifying the target bean through the local attribute leverages the capability of the XML parser to validate XML id references within the same file. The value of the local attribute must be same as the id attribute of the target bean. The XML parser gives an error if no matching element is located in the same file. Using the local variant is the most suitable choice if the target bean is in the same XML file.

<ref local="testBean"/>

  • Inner Beans

A <bean/> element can be used inside the <property/> or <constructor-arg/> elements describe inner bean.

<bean id="outer" class="...">

<property name="target">

  <bean class="com.test.Employee"> <!-- this is the inner bean -->

    <property name="fname" value="test emp nane"/>

    <property name="age" value="35"/>

  </bean>

</property>

</bean>

  • Collections

In the <list/>, <set/>, <map/>, and <props/> elements, we can define the properties and arguments of the Java Collection types List, Set, Map, and Properties, corresponding to certain class.

Example:

<bean id="testComplexObject" class="example.ComplexObject">

<!-- results in a setUserTypesEmails(java.util.Properties) call -->

<property name="userEmails">

  <props>

      <prop key="administrator">administrator@example.org</prop>

      <prop key="support">support@example.org</prop>

      <prop key="development">development@example.org</prop>

  </props>

</property>

<!-- results in a setList(java.util.List) call -->

<property name="List">

  <list>

      <value>a list element followed by a reference</value>

      <ref bean=”testDataSource" />

  </list>

</property>

<!-- results in a setMap(java.util.Map) call -->

<property name="Map">

  <map>

      <entry key="an entry" value="just some string"/>

      <entry key ="a ref" value-ref="testDataSource"/>

  </map>

</property>

<!-- results in a setSet(java.util.Set) call -->

<property name="Set">

  <set>

      <value>just some string</value>

      <ref bean=”testDataSource" />

  </set>

</property>

</bean>

  • Collection Merging

As of Spring 2.0, the container helps the combining of collections. A developer can describe a parent-style <list/>, <map/>, <set/> or <props/> element, and have child-style <list/>, <map/>, <set/> or <props/> elements inherit and override values from the parent collection. The child collection's values result from combining the elements of the parent and child collections, using  the child's collection elements overriding values specified in the parent collection.

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

The following example shows collection merging:

<beans>

<bean id="parent" abstract="true" class="test.ComplexObject">

  <property name="adminEmails">

      <props>

          <prop key="administrator">administrator@example.com</prop>

          <prop key="support">support@example.com</prop>

      </props>

  </property>

</bean>

<bean id="child" parent="parent">

  <property name="adminEmails">

      <!-- the merge is specified on the *child* collection definition -->

      <props merge="true">

          <prop key="sales">sales@example.com</prop>

          <prop key="support">support@example.co.uk</prop>

      </props>

  </property>

</bean>

<beans>

Limitations of Collection Merging:

Using collection merging with various collection types (for example a Map and a List), we may see the challenges of certain appropriate Exceptions. The merge attribute must be defined on lower, inherited child definition; specifying the merge attribute on a parent collection description is repetitious and will not result in the desired merging. The merging feature is present only in Spring 2.0 and later versions.

  • Strongly-Typed Collection (Java 5+ only)

In Java 5 and the latest version, we can utilize strongly typed collections (with generic types). In other words, it is doable to declare a Collection type such that it can only include String elements. To utilize Spring to dependency-inject a strongly-typed Collection into a bean, we can go to the procedure of Spring's type-conversion support such that the elements of your strongly-typed Collection instances are transformed to the suitable type previous to being added to the Collection.

public class TestCollection {

  private Map<String, Float> employees;

  public void setEmployee(Map<String, Float> employees) {

      this.employees = employees;

  }

}

<beans>

  <bean id="collection" class="x.y.TestCollection">

      <property name="employees">

          <map>

              <entry key="one" value="1"/>

              <entry key="two" value="2"/>

              <entry key="three" value="3"/>

          </map>

      </property>

  </bean>

</beans>

  • Null and Empty String Values

We can define Spring as empty arguments for properties and the like. The subsequent XML-based configuration metadata snippet defines and sets the email property to the empty String value ("")

<bean class="TestBean">

<property name="email" value=""/>

</bean>

The preceding example is equivalent to the following Java code: TestBean.setEmail(""). The <null/> element handles null values. 

Example:

<bean class="TestBean">

<property name="email"><null/></property>

</bean>

  • XML Shortcut With p-namespace

The p-namespace allows us to operate the bean element's attributes, rather than nested <property/> elements, to represent the property values and/or collaborating beans.

Spring 2.0 and the latest version enables the extensive design formats with namespaces, which are defined on an XML Schema definition. 

The below example shows two XML snippets that provide the same result.

The first uses standard XML format and the second uses the p-namespace.

<beans xmlns="http://www.test.org/schema/beans"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:p="http://www.test.org/schema/p"

  xsi:schemaLocation="http://www.test.org/schema/beans

      http://www.test.org/schema/beans/spring-beans.xsd">

  <bean name="classic" class="com.test.TestBean">

      <property name="email" value="abc@bar.com"/>

  </bean>

  <bean name="p-namespace" class="com.test.TestBean"

        p:email="abc@bar.com"/>

</beans>

Learn the Ins & Outs of Software Development

Caltech Coding BootcampExplore Program
Learn the Ins & Outs of Software Development

The example displays an attribute in the p-namespace named email in the bean definition. It specifies Spring to include a property declaration. As mentioned earlier, the p-namespace does not contain schema definition, so we can define the name of the attribute to the property name.

In this example we have two more bean definitions that both have a reference to another bean:

<beans xmlns="http://test/schema/beans"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:p="http://test/schema/p"

  xsi:schemaLocation="http://test/schema/beans

      http://test/schema/beans/spring-beans.xsd">

  <bean name="User-classic" class="com.test.User">

      <property name="fname" value="Test first name user 1"/>

      <property name="lname" value="Test last name user 1"/>

  </bean>

  <bean name="Test User-Detail"

      class="com.test.User"

      p:name="Test first name user 1"

      p:spouse-ref="Test last name user 1"/>

</beans>

  • XML Shortcut With c-namespace

The c-namespace, newly instroduced in Spring 3.1 version, authorizes the usage of inlined attributes for configuring the constructor arguments rather than nested constructor-arg elements.

Here we have the examples with the c-namespace:

<beans xmlns="http://www.test.org/schema/beans"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:c="http://www.test.org/schema/c"

  xsi:schemaLocation="http://www.test.org/schema/beans

      http://www.test.org/schema/beans/spring-beans.xsd">

  <bean id="testBean1" class="x.y.testBean1"/>

  <bean id="testBean2" class="x.y.testBean2"/>

  <-- 'traditional' declaration -->

  <bean id="sample" class="x.y.sample">

      <constructor-arg ref="testBean1"/>

      <constructor-arg ref="testBean2"/>

      <constructor-arg value="sample@bar.com"/>

  </bean>

  <-- 'c-namespace' declaration -->

  <bean id="sample" class="x.y.sample" c:testBean1-ref="bar" c:testBean1-ref="testBean2" c:email="sample@bar.com">

</beans>

  • Compound Property Names

We can use compound or nested property names while setting up and define bean properties, as long as all components of the path except the final property name are not null. Consider the below bean definition.

<bean id="test" class="test.BeamTest1">

<property name="BeamTest1Value" value="5" />

</bean>

The test bean has a BeamTest1 property; if this property is null, it will throw the exception.

  • Using depends-on

If a certain bean is the dependency of another, it means one bean is set as a property of another. We can define this with the <ref/> element in XML-based configuration metadata. For example, a static initializer in a class requires to be triggered, such as a database driver roster. The depends-on attribute can force one or more beans to be initialized before the bean with this element is initialized. 

The below example uses the depends-on attribute to describe a dependency on a single bean:

<bean id="beanOne" class="TestBean" depends-on="director"/>

<bean id="director" class="DirectorBean" />

To describe a dependency on deifferent beans, we need to define a list of bean names as the value of the depends-on attribute, with commas, whitespace and semicolons, used as valid delimiters:

<bean id="beanOne" class="TestBean" depends-on="director,accountDao">

<property name="director" ref="director" />

</bean>

<bean id="director" class="DirectorBean" />

<bean id="directorDao" class="x.y.jdbc.JdbcDirectorDao" />

  • Lazy-initiated Beans

ApplicationContext implementations usually start and configure all singleton beans as parts of the initialization procedure. This pre-instantiation helps to discover certain errors in the configuration or surrounding environmment immediately. Otherwise, if this behavior is not desirable, we can mark the bean definition as lazy-initialized and prevent the pre-instantiation of the singleton bean.

A lazy-initialized bean notifies the IoC container to make a bean instance when it is first requested, rather than at startup.

In XML, this behavior is handled by the lazy-init attribute on the <bean/> element.

Example:

<bean id="lazy" class="com.Test.ExpensiveToDefineBean" lazy-init="true"/>

<bean name="not.lazy" class="com.Test.AnotherBean"/>

When the initial configuration is consumed by an ApplicationContext, the bean designated lazy is not eagerly pre-instantiated, whereas the not.lazy bean is eagerly pre-instantiated.

lazy-initialized bean is a dependency of a singleton bean not lazy-initialized. The ApplicationContext starts the lazy-initialized bean at startup, because it must fulfill the singleton's dependencies. 

We can control lazy-initialization at the container level by using the default-lazy-init attribute on the <beans/> element.

Example:

<beans default-lazy-init="true">

  <!-- no beans will be pre-instantiated... -->

</beans>

  • Autowiring Collaborators

The Spring container can autowire connections between connecting beans. We can let Spring resolve collaborators automatically for our bean by checking the contents of the ApplicationContext. Below are a few advantages of Autowiring:

  • Autowiring can remarkably decrease the necessity to identify properties or constructor arguments.
  • Autowiring can update a configuration as your objects develop. For example, if we need to create a dependency to a class, that dependency can be fulfilled automatically without requiring us to change the configuration. Thus, autowiring can be particularly helpful during development.

When using XML-based configuration metadata[2], we can determine autowire mode for a bean description with the autowire attribute of the <bean/> element. The autowiring functionality has five methods. You can choose which ones to autowire after you’ve specifed autowiring per bean.

Limitations and Disadvantages of Autowiring:

Autowiring performs best when it is utilized consistently across a project. If autowiring is not available, it might be illogical to developers to utilize it to wire only one or two bean definitions.

Below are the limitations and disadvantages of autowiring:

  • Detailed dependencies in property and constructor-arg settings consistently override autowiring. It does not allow defining autowire with simple properties such as primitives, Strings, and Classes. This limitation is by design.
  • When using Spring, we have to be careful to avoid assuming in case of ambiguity that might have unexpected effects. The relationships between Spring-managed objects are no longer recorded explicitly.
  • Wiring details may not be functional to tools that may render documentation from a Spring container.
  • Numerous bean definitions within the container may correspond to the type specified by the setter method or constructor argument to be autowired. For dependencies that predict a single value, this ambiguity is not promptly resolved. If no distinctive bean definition is available, an anomaly error is thrown.

Excluding a Bean from Autowiring:

On a per-beam foundation, we can exclude a bean from autowiring. 

In Spring's XML format, set the autowire-candidate feature of the <bean/> element to false; the container drives that exact bean definition inaccessible to the autowiring infrastructure (including annotation style configurations example such as @Autowired).

We can determine autowire candidates founded on pattern-matching against bean names. The top-level <beans/> element obtains one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate class to any bean which name ends with Repository, deliver a value of *Repository. To deliver numerous patterns, describe them in a comma-separated list. A precise value of true or false for bean definitions autowire-candidate attribute always carries precedence, and for such beans, the pattern matching rules do not apply.

These techniques are good for beans that you never want to be injected into other beans by autowiring.

Method Injection

In Different application procedures, most beans in the container are singletons. When a singleton bean requires cooperation with another singleton bean, or a non-singleton bean requires collaboration with another non-singleton bean, we can control the dependency by describing one bean as a property of the other. 

A problem occurs when the bean lifecycles are distinguishable. For example, singleton bean A needs to use non-singleton (prototype) bean B, possibly on each method request on A. The container only constructs the singleton bean A once, and hence only gets one possibility to set the properties. The container cannot supply bean A with a unique instance of bean B each time one is needed.

Example:

package fruit.apple;

// Spring-API imports

import org.test.beans.BeansException;

import org.test.context.ApplicationContext;

import org.test.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

 private ApplicationContext applicationContext;

 public Object process(Map commandState) {

    // take a unique instance of the right Command

    Command testcommand = createCommand();

    // define the state on the  Command instance

    command.setState(commandState);

    return testcommand.execute();

 }

 protected Command createCommand() {

    // notice the Spring API dependency!

    return this.applicationContext.getBean("command", Command.class);

 }

 public void setApplicationContext(ApplicationContext applicationContext)

                                                                  throws BeansException {

    this.applicationContext = applicationContext;

 }

}

  • Lookup Method Injection

Lookup method injection is the ability of the container to override procedures on container-managed beans to return the lookup result output for another named bean within the container. The lookup generally applies a prototype bean as in the method that is described in the preceding section. The Spring Framework executes this method injection by using bytecode generation from the CGLIB library to develop dynamically a subclass that overrides the procedure.

If a certain method is abstract, the dynamically generated subclass executes the method. The dynamically generated subclass overrides the concrete method described in the original class. 

Example:

<!-- a stateful bean deployed as a prototype (non-singleton) -->

<bean id="command" class="fruit.apple.AsyncCommand" scope="prototype">

<!-- inject dependencies here as required -->

</bean>

<!-- commandProcessor uses statefulCommandHelper -->

<bean id="TestcommandManager" class="fruit.appleTest.CommandManager">

<lookup-method name="createCommand" bean="command"/>

</bean>

  • Arbitrary Method Replacement

Method Injection can replace arbitrary methods in an organized bean with other method implementation.

With XML-based configuration metadata, we can utilize the replaced-method element for a deployed bean to return an existing method implementation with another.

Consider the below class, with a method TestcomputeValue, which we need to override:

public class TestValueCalculator {

public String TestcomputeValue(String input) {

  // some real code...

}

// some other methods...

}

A class implementing the customized org.test.beans.factory.support.MethodReplacer interface provides new method definition.

/** override the existing computeValue(String)

  implementation in TestValueCalculator

*/

public class ReplacementComputeValue implements MethodReplacer {

  public Object Testreimplement(Object o, Method m, Object[] args) throws Throwable {

      // get the input value, perform with it, and return a computed result

      String input = (String) args[0];

      ...

      return ...;

  }

}

The bean definition can deploy the original class and define the function to override as per the below example:

Example:

<bean id="TestValueCalculator" class="x.y.z.TestValueCalculator">

<!-- arbitrary method replacement -->

<replaced-method name="TestcomputeValue" replacer="replacementComputeValue">

  <arg-type>String</arg-type>

</replaced-method>

</bean>

<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>

  • Bean Scopes

To create a bean definition, we need to define a recipe for developing actual instances of the class described by that bean definition. 

The concept that a bean definition is a recipe is essential, as we can create numerous object instances from a single recipe. We can plug the configuration values into an object, that is defined from a certain bean definition and control the scope of the objects created from a particular bean definition. This approach is effective and flexible 

Beans can be described to be deployed in one of several scopes. The Spring Framework helps five scopes, three of which are shared only as per the web application context.

Here is the definition of each Bean Scope:

singleton: It (default) Scopes a single bean definition to a single object instance per Spring IoC container.

prototype: It provides a single bean definition to any number of object instances.

request: It defines a single scope of a single bean definition to the lifecycle of a single HTTP request; hence, each HTTP request has its instance of a bean created off the back of a single bean description.

It is simply valid in the context of a web-aware Spring ApplicationContex

session: It defines the scopes as a single bean description of the lifecycle of an HTTP Session. It is only useful in the context of a web-aware-based Spring ApplicationContext.

global session: It defines the scopes of a single bean description to the lifecycle of a global HTTP Session. Commonly, it is valid only in the context of a web-aware Spring ApplicationContext and portlet context.

  • Initial Web Configuration

To enable the scoping of beans at the request, session, and global session classes (web-scoped beans), we would need some initial configuration before we determine beans.

If we need access to scoped beans using Spring Web MVC, in development, we can send a request that can be processed using the Spring DispatcherServlet, or DispatcherPortlet.

If we use a Servlet 2.4+ web container, with the help of processed requests exceeding Spring's DispatcherServlet, you need to add the following javax.servlet.ServletRequestListener to the declarations in your web applications web.xml file.

javax.servlet.ServletRequestListener to the principles in your web applications web.xml file:

<web-app>

...

<listener>

  <listener-class>

      org.test.web.context.request.RequestContextListener

  </listener-class>

</listener>

...

</web-app>

The below snippet of XML configuration must be incorporated in the web.xml file in the web application if we need to access web-scoped beans in incoming requests outside of Spring's DispatcherServlet on a Servlet 2.3 container. 

<web-app>

..

<filter>

  <filter-name>TestrequestContextFilter</filter-name>

  <filter-class>org.test.web.filter.RequestContextFilter</filter-class>

</filter>

<filter-mapping>

  <filter-name>TestrequestContextFilter</filter-name>

  <url-pattern>/*</url-pattern>

</filter-mapping>

...

</web-app>

  • Request Scope

<bean id="TestloginAction" class="com.Test.LoginAction" scope="request"/>

The Spring container starts a new instance of the LoginAction bean by utilizing the loginAction bean description for every HTTP request. That is, the loginAction bean is scooped at the HTTP request group.

Declaration : <bean id="TestloginAction" class="com.Test.LoginAction" scope="request"/>

We can modify the internal state of the instance that is constructed as per our requirement because other instances constructed from the identical loginAction bean description will not see these state modifications. When the request ends processing, the bean that is scoped to the request is discarded.

  • Global Session Scope

The global session scope is equivalent to the standard HTTP Session scope and applies in the context of certain portlet-based web applications. The portlet specification describes the notion of a global Session that is shared among all portlets that construct a single portlet web application.

Declaration : <bean id="TestuserPreferences" class="com.test.UserPreferences" scope="globalSession"/>

Beans determined at the global session scope are scoped to the lifetime of the global portlet Session.

If we write a standard Servlet-based web application and define one or more beans as having global session scope, the standard HTTP Session scope is used, and no error is raised.

Scoped Beans as Dependencies

The Spring IoC container contains not only the instantiation of certain objects (beans) but also the wiring up of dependencies.To inject an HTTP request scoped bean into another bean, we need to inject an AOP proxy in the location of the scoped bean. We require injecting a proxy object that reveals the same public interface as the scoped object but that can also retrieve the real along with the target object from the relevant scope such as an HTTP request and delegate method call on the actual object.

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

<beans xmlns="http://www.test.org/schema/beans"

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xmlns:aop="http://www.test.org/schema/aop"

     xsi:schemaLocation="http://www.test.org/schema/beans

         http://www.test.org/schema/beans/spring-beans.xsd

         http://www.test.org/schema/aop

         http://www.test.org/schema/aop/spring-aop.xsd">

  <!-- an HTTP Session-scoped bean exposed as a proxy -->

  <bean id="TestuserPreferences" class="com.Test.UserPreferences" scope="session">

        <!-- instructs the container to proxy the surrounding bean -->

        <aop:scoped-proxy/>

  </bean>

  <!-- a singleton-scoped bean injected with a proxy to the above bean -->

  <bean id="TestuserService" class="com.test.SimpleUserService">

      <!-- a reference to the proxied userPreferences bean -->

      <property name="TestuserPreferences" ref="TestuserPreferences"/>

  </bean>

</beans>

Choosing the Type of Proxy to Create:

When Spring container constructs a proxy for a bean that is scored up with the <aop:scoped-proxy/> element, a CGLIB-based class proxy is created.

We can configure the Spring container to construct standard JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the <aop:scoped-proxy/> element. Utilizing JDK interface-based proxies indicates that we do not need additional libraries in the application classpath to effect such proxying. 

<!-- DefaultUserPreferences implements the UserPreferences interface -->

<bean id="TestuserPreferences" class="com.Test.DefaultUserPreferences" scope="session">

  <aop:scoped-proxy proxy-target-class="false"/>

</bean>

<bean id="TestuserManager" class="com.test.UserManager">

  <property name="TestuserPreferences" ref="userPreferences"/>

</bean>

Customizing the Nature of a Bean

  • Lifecycle Callback

To communicate using the container's management of the bean lifecycle, we can implement and execute the Spring InitializingBean and DisposableBean interfaces. The container reaches afterPropertiesSet() for the former and destroy() for the latter to authorize the bean to accomplish certain actions upon initialization and destruction of your beans.

Internally, the Spring Framework operates BeanPostProcessor executions to process any callback interfaces it can locate and call the suitable methods. To create custom features or other lifecycle behavior, Spring does not suggest anything out-of-the-box. We can implement a BeanPostProcessor ourselves.

In expansion to the initialization and destruction callbacks, Spring-managed objects may also implement the Lifecycle interface so that we can use those objects in the startup and shutdown process as conducted by the container's lifecycle.

The lifecycle callback interfaces are discussed below.

  • Initialization Callbacks

The org.springframework.beans.factory.InitializingBean interface permits a bean to execute an initialization outcome after all necessary properties on the bean have been set by the container. The InitializingBean interface determines a single method:

void afterPropertiesSet() throws Exception;

We can use the InitializingBean interface because it unnecessarily couples the code to Spring. 

We can operate the @PostConstruct annotation or select a POJO initialization method. In the case of XML-based configuration metadata, we can use the init-method attribute to determine the name of the method that has a void no-argument signature. 

Example:

<bean id="testInitBean" class="test.TestBean" init-method="init"/>

public class TestBean {

  public void init() {

      // do some initialization work

  }

}

...is exactly the same as...

<bean id="testInitBean" class="test.AnotherTestBean"/>

public class AnotherTestBean implements InitializingBean {

  public void afterPropertiesSet() {

      // do some initialization work

  }

}

  • Destruction Callbacks

To implement the org.springframework.beans.factory.DisposableBean interface permits a bean to get a callback when the container containing it is destroyed. The DisposableBean interface determines a single method:

void destroy() throws Exception;

It is suggested that we avoid the DisposableBean callback interface because it can unnecessarily couple the code to Spring. We can use the @PreDestroy annotation or determine a generic method that is supported by bean definitions. With XML-based configuration metadata, we can use the destroy-method attribute on the <bean/>. 

Example:

<bean id="testInitBean" class="test.TestExampleBean" destroy-method="cleanup"/>

public class TestExampleBean {

  public void cleanup() {

     }

}

<bean id="testInitBean" class="test.TestAnotherExampleBean"/>

public class AnotherExampleBean implements DisposableBean {

  public void destroy() {

  }

}

Default Initialization and Destroy Methods

To define the initialization and destroy method callbacks we can use Spring-specific InitializingBean and DisposableBean callback interfaces and can write custom methods with names such as init(), initialize(), dispose().

The lifecycles of callback procedures are normalized across a project and accordingly developers use the exact method names and provide consistency.

We can set up and configure the Spring container to examine for named initialization and destroy callback method names on each bean. As an application developer, we can write custom classes and operate an initialization callback called init(), without  configuring an init-method=" init" attribute with each bean definition. The Spring IoC container calls that procedure when the bean is completed. This feature also implements a consistent naming pattern for initialization and destroy method callbacks.

In case your initialization callback methods are named init() and destroy callback methods are named destroy(), your class will resemble the class in the following example.

We can resemble the class in the below example.

public class TestBlogAPI implements BlogAPI {

  private TestBlogDao testblogDao;

  public void setTestBlogDao(TestBlogDao testblogDao) {

      this.testblogDao = testblogDao;

  }

  public void init() {

      if (this.testblogDao == null) {

          throw new IllegalStateException("The [testblogDao] property must be define.");

      }

  }

}

<beans default-init-method="init">

  <bean id="TestblogService" class="com.test.DefaultTestBlogService">

      <property name="testblogDao" ref="testblogDao" />

  </bean>

</beans>

  • Combining Lifecycle Mechanisms

As of Spring 2.5 version, here we have three alternatives for controlling bean lifecycle behaviour: the InitializingBean and DisposableBean callback interfaces; custom init() and destroy() methods; and the @PostConstruct and @PreDestroy annotations. You can incorporate these mechanisms to maintain a specified bean.

  • If multiple lifecycle mechanisms are set up and configured for a bean, and every mechanism is configured with a various method name, then each configured method is implemented in the below order.
  • If the same method name is configured - for example, init() for an initialization procedure - for more than one of these lifecycle scenarios, that method is performed once, as described in the prior section.

Multiple lifecycle mechanisms configured for the exact bean, with various initialization methods, are named as follows:

  • Methods can be annotated using @PostConstruct afterPropertiesSet() as described by the InitializingBean callback interface.
  • A custom-configured init() method Destroy procedures are called in the exact order.
  • Methods annotated with @PreDestroy destroy() as defined by the DisposableBean callback interface.
  • A custom-configured destroy() method.
  • Startup and Shutdown Callbacks

We can describe the Lifecycle interface using the necessary methods for any object that has its lifecycle requirements using starts and stops some background techniques:

public Createinterface Lifecycle {

  void start();

  void stop();

  boolean isRunning();

}

Spring-managed object may execute that interface. Then, when the ApplicationContext itself starts and stops, it will spread those calls to all Lifecycle implementations described within that context. It does this by tasking to a LifecycleProcessor:

public interface TestLifecycleProcessor extends Lifecycle {

  void onRefresh();

  void onClose();

}

LifecycleProcessor is itself an extension of the Lifecycle interface. It also integrates two other techniques for responding to the context being refreshed and closed.

To create startup and shutdown requests we can define the "depends-on" relationship that exists between any two objects, the dependent side will begin after its dependency, and it will stop before its dependency. 

Any Spring-managed object may implement that interface. Then, when the ApplicationContext itself starts and stops, it will cascade those calls to all Lifecycle implementations defined within that context. It does this by delegating to a LifecycleProcessor:

Sometimes the direct dependencies are unidentified. We can define the objects of a specific type that should start before objects of another type. 

In such scenarios, the SmartLifecycle interface describes another option, namely the getPhase() method as described on its super-interface, Phased.

public interface TestPhased {

  int getPhase();

}

public interface CreateLifecycle extends Lifecycle, TestPhased {

  boolean isAutoStartup();

  void stop(Runnable callback);

}

Shutting Down the Spring IoC Container Gracefully in Non-web Applications

To define a Spring's IoC container in a non-web-based application environment; for example,in a client desktop environment; we can register a shutdown hook using the JVM. We can trace the shutdown and call the relevant destroy methods on certain singleton beans so that all resources are released. 

If you are using Spring's IoC container in a non-web application environment; for example, in a rich client desktop environment; you register a shutdown hook with the JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released. Of course, you must still configure and implement these destroy callbacks correctly.

To register a shutdown hook, we can call the registerShutdownHook() function that is declared on the AbstractApplicationContext class:

import org.testframework.context.support.AbstractApplicationContext;

import org.testframework.context.support.ClassPathXmlApplicationContext;

public final class TestBoot {

  public static void main(final String[] args) throws Exception {

      AbstractApplicationContext ctx

          = new ClassPathXmlApplicationContext(new String []{"beans.xml"});

      // describe a shutdown hook for the defined context... 

      ctx.registerShutdownHook();

      // app runs here...

      // this main method function exits and as per the shutting down, hook is called as per the above defined to the app shutting down...

  }

}

  •  Bean Definition Inheritance

A bean definition can include various types of configuration details, including constructor arguments, property values, and container-specific details such as initialization procedure, static factory method name, etc. A child bean connotation inherits configuration data from a parent definition. 

The child definition can override some values and can be added as per certain requirements.

Using the ApplicationContext interface programmatically, child bean descriptions are described by the ChildBeanDefinition class. 

When we define XML-based configuration metadata, we define a child bean definition by using the parent attribute, and specify the parent bean as the value of this attribute.

Configuring bean definitions declaratively in something like the ClassPathXmlApplicationContext; most users do not work with them on this level.

<bean id="inheritedTestTypeBean" abstract="true"

    class="org.testframework.beans.TestBean">

  <property name="name" value="parent"/>

  <property name="age" value="1"/>

</bean>

<bean id="inheritsWithDifferentClass"

      class="org.test.beans.DerivedTestBean"

      parent="inheritedTestTypeBean" init-method="initialize">

  <property name="name" value="override"/>

  <!-- the age property value of 1 will be inherited from  parent -->

</bean>

A child bean definition utilizes the bean class from the parent description if none is established, but can also override it. 

The child bean class must be consistent with the parent's property it accepts the values from.

A child bean connotation inherits scope, constructor argument values, property values, and method overrides from the parent, using the option to include new values. 

Child definition settings depend on, autowire mode, dependency check, singleton, lazy init.

The preceding sample explicitly defines the parent bean definition as abstract by using the abstract attribute.

Trying to use such an abstract parent bean on its own, by referring to it as a ref property of another bean or doing an explicit getBean() call with the parent bean id, returns an error. Similarly, the container's internal preInstantiateSingletons() method ignores bean definitions that are defined as abstract.

<bean id="inheritedTestBeanWithoutClass" abstract="true">

    <property name="name" value="parent"/>

    <property name="age" value="1"/>

</bean>

<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"

    parent="inheritedTestBeanWithoutClass" init-method="initialize">

  <property name="name" value="override"/>

  <!-- age will inherit the value of 1 from the parent bean definition-->

</bean>

Master front-end and back-end technologies and advanced aspects in our Post Graduate Program in Full Stack Web Development. Unleash your career as an expert full stack developer. Get in touch with us NOW!

Conclusion

We hope this in-depth article helped you understand the detailed concept of the IoC container with its features. In this article, we discussed the concept of various samples code and syntax examples of IoC containers, Bean containers, etc. This article will be helpful to professional developers from Java and .net backgrounds, application architectures, cloud specialists, testers, and other learners looking for various ways to use Docker with containers.

If you want to read more about this concept or any web development related topic, enroll in a good Web development course. You can also check out Simplilearn’s Full Stack Developer - MERN Stack. The Post Graduate Program in Full Stack Web Development works in conjunction with the CTME at Caltech to provide a fully immersive experience for a tight-knit group of students learning the latest trends in web development. 

Accelerate your career as a software besides pursuing varied courses provided by Simplilearn, you can also sign up on our SkillUp platform. This platform, a Simplilearn initiative, offers numerous free online courses to help with the basics of multiple programming languages, including Nodejs ubuntub. 

Our Software Development Courses Duration And Fees

Software Development Course typically range from a few weeks to several months, with fees varying based on program and institution.

Program NameDurationFees
Caltech Coding Bootcamp

Cohort Starts: 16 Dec, 2024

6 Months$ 8,000
Automation Test Engineer Masters Program

Cohort Starts: 18 Dec, 2024

8 months$ 1,499
Full Stack Java Developer Masters Program

Cohort Starts: 18 Dec, 2024

7 months$ 1,449
Full Stack (MERN Stack) Developer Masters Program

Cohort Starts: 8 Jan, 2025

6 Months$ 1,449