How to instantiate a bean with an instance factory method in Spring ?

Instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To instantiate a bean with an instance factory method, the class attribute should be empty, and in the factory-bean attribute, the name of a bean should be specified in the current (or parent/ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-method attribute.

package com.roytuts.spring.di;

public class DefaultServiceLocator {

    private static InstanceFactoryExample instanceFactoryExample = new InstanceFactoryExample();
    
    private DefaultServiceLocator() {}

    public InstanceFactoryExample createInstance() {
        return instanceFactoryExample;
    }

}

Define XML configuration metadata – applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                              http://www.springframework.org/schema/beans/spring-beans.xsd">
                           
    <!-- the factory bean, which contains a method called createInstance() -->
    <bean id="serviceLocator" class="com.roytuts.spring.di.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
    </bean>

    <!-- the bean to be created via the factory bean -->
    <bean id="instanceFactory" factory-bean="serviceLocator" factory-method="createInstance"/>

</beans>

One factory class can also hold multiple factory methods as shown here:

package com.roytuts.spring.di;

public class DefaultServiceLocator {

    private static AccountService accountService = new AccountServiceImpl();
    private static ClientService clientService = new ClientServiceImpl();
    
    private DefaultServiceLocator() {}

    public AccountService createAccountInstance() {
        return accountService;
    }
    
    public ClientService createClientInstance() {
        return clientService;
    }

}

Define XML configuration metadata – applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                              http://www.springframework.org/schema/beans/spring-beans.xsd">
                           
    <!-- the factory bean, which contains a method called createInstance() -->
    <bean id="serviceLocator" class="com.roytuts.spring.di.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
    </bean>

    <!-- the bean to be created via the factory bean -->
    <bean id="accountService" factory-bean="serviceLocator" factory-method="createAccountInstance"/>
    
    <!-- the bean to be created via the factory bean -->
    <bean id="clientService" factory-bean="serviceLocator" factory-method="createClientInstance"/>

</beans>

Which Dependency Injection is better to use – Constructor based or Setter based ?

It is recommended to use Constructor based DI for mandatory dependencies and Setter based DI for optional dependencies. Though using @Required annotation on the setter method you can make the property as a required dependency.

The Spring usually advocates constructor based injection as it enables you to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. Although, a large number of constructor arguments is a bad for source code maintenance, implying that the class likely has too many responsibilities and should be re-factored to address properly separation of concerns.

Setter based DI should primarily be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Use the DI style that fits the most for a particular class. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

20. How does dependency resolution happen in Spring ?

The Spring container validates the configuration of each bean when the container is created. However, the bean properties or constructor arguments are not set until the bean is actually created. Beans that are singleton-scoped (the default scope of the bean if not specified) are created when the container is created and all other scoped-beans are created only as per the request. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies’ dependencies (and so on) are created and assigned. Resolution mismatches among those dependencies may show up on first creation of the affected bean.

The Spring container platforms dependency resolution as follows:

i. The ApplicationContext is created and initialized with configuration metadata that defines all beans and can be specified via XML, Java code or Java annotations.
ii. Dependencies for each bean are expressed in the form of properties, constructor arguments, or arguments to the static factory-method. These dependencies are provided to the bean when the bean is actually created.
iii. Then Spring finds each property or constructor argument is either an actual value or a reference to another bean in the container.
iv. Next Spring converts each property or constructor argument from its specified format to the actual type of property or constructor argument. By default Spring converts a value supplied in string format to all built-in types, such as int, long, String, boolean, etc.

What is circular dependency in Spring ? How to resolve it ?

It is possible to occur an unresolvable circular dependency scenario if constructor injection is used predominantly.

Let’s take an example how it may occur. Suppose class A requires an instance of class B through constructor injection and class B requires an instance of class A through constructor injection.  If you configure beans for classes A and B to be injected into each other through constructor injections, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

One possible solution is to edit the source code of some classes to be injected by setters injection rather than constructor injection. In other words but not recommended, you can configure circular dependencies with setter injection.

Unlike the typical case (with no circular dependencies), a circular dependency between beans A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself.

How can datasource be defined in Spring XML configuration ?

First approach

<bean id="myDataSource" 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:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

or

Second approach

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/mydb"
        p:username="root"
        p:password="root"/>

</beans>

From the above definitions, the second approach using p-namespace is more cleaner and briefly expressed.

How do you define properties in XML file in Spring ?

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

    <bean id="configProperties"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="properties">
            <value>
                jdbc.driver.className=com.mysql.jdbc.Driver
                jdbc.url=jdbc:mysql://localhost:3306/mydb
            </value>
        </property>
    </bean>

</beans>

The Spring container converts the text inside the <value/> element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism.

What is idref element in Spring ?

The idref element is simply an error-proof way to pass the id (which is a string value not a reference) of another bean in the container to a <constructor-arg/> or <property/> element.

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

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

    <bean id="theClientBean" class="...">
        <property name="targetName">
            <idref bean="theTargetBean" />
        </property>
    </bean>

</beans>

The equivalent snippet is shown below but it is resolved at runtime

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

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

    <bean id="client" class="...">
        <property name="targetName" value="theTargetBean" />
    </bean>

</beans>

The first approach is preferred over second one because container validates the idref bean name at deployment time whether it actually exists but in second approach no validation is performed. The exception may be discovered when the client bean is created or if client bean is of prototype bean then the exception may occur long after the container is deployed.

What is ref element in Spring ?

The ref element is the final element inside a <constructor-arg/> or <property/> definition element. It is generally used to set the value of a specified property of a bean to be a reference to another bean managed by the Spring container. The referenced bean is initialized, if not singleton, on demand basis otherwise container will initialize at the time of its creation. ref element allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute will be the same as the id attribute of the target bean, or as one of the values in the name attribute of the target bean.

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

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

    <bean id="client" class="...">
        <ref bean="theTargetBean" />
    </bean>

</beans>

What is an inner bean in Spring ?

A <bean/> element inside the <property/> or <constructor-arg/> element is called an inner bean. An inner bean definition does not require an id or name attribute; the container ignores these values if we specify. It also ignores the scope flag. Inner beans are always anonymous and they are always created with the outer bean. It is not possible to inject inner beans into collaborating beans other than into the enclosing bean.

For example,

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

    <bean id="outerBean" class="...">
        <!-- instead of using a reference to a target bean, simply define the target bean inline -->
        <property name="target">
            <bean class="com.roytuts.di.Student"> <!-- this is the inner bean -->
                <property name="name" value="Soumitra"/>
                <property name="email" value="contact@roytuts.com"/>
                <property name="age" value="28"/>
            </bean>
        </property>
    </bean>

</beans>