A bean definition is essentially a set of rules for creating one or more objects. In response to a request, the container looks up the named bean's rule set and uses the configuration metadata contained in that bean's definition to create (or retrieve) the actual object.

If you use XML-based configuration metadata, you specify the type ( or class) of the object to be instantiated, in the class attribute of the <bean/> element. This class attribute (which is internally the Class property of the BeanDefinition instance) is typically required. The Class property can be used in one of two ways:

  • Typically, to specify the class of the bean that should be built if the container itself directly creates the bean by reflectively calling its constructor, which is somewhat equivalent to Java code with the new operator.

  • To specify the actual class containing the static is a factory method that is called to create an object, in the less common case where the container calls a static factory method on the class to create the bean. The object type returned from a call to a static factory method can be the same class or a completely different class.

Nested class names

If you want to customize a bean definition for a nested class, you can use either a binary name or the original name of the nested class.

For example, if you have a class SomeThing in the package com.example, and this class SomeThing has a static nested class called OtherThing, they can be separated by a dollar sign($) or a dot (.). Thus, the value of the class attribute in the bean definition would be com.example.SomeThing$OtherThing or com.example.SomeThing.OtherThing.

Creating an instance using a constructor

If the bean is instantiated using a constructor, all standard classes can be used and will be compatible with Spring. That is, the class being developed does not have to implement any specific interfaces or be written in a specific way. Simply setting the bean class should be sufficient. However, depending on what type of IoC is used for that particular bean, a default (empty) constructor may be needed.

Spring's IoC container can manage almost any class you need to manage. It is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans using a default (no-argument) constructor and appropriate setters and getters modeled after container properties. Your container may also contain more exotic non-bean-style classes. If, for example, you want to use a legacy connection pool that is completely inconsistent with the JavaBean specification, Spring can manage that too.

Using XML-based configuration metadata, you can define your bean class like this:


<bean id="exampleBean" class=" examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

More details about the mechanism for providing arguments to the constructor (if required) and setting properties object instance after the object is constructed, see Dependency Injection.

Creating an instance using a static factory method

When defining a bean that you instantiate using a static factory method, use the class attribute to specify the class that contains the static code> factory method, and the factory-method attribute to set the name of the factory method itself. You should be able to call this method (with optional arguments, as described below) and return a runnable object, which will then be treated as if it had been created using the constructor. One use case for such a bean definition is to call static factories in legacy code.

The following bean definition specifies that the bean will be created by calling a factory method. The definition does not specify the type (class) of the returned object, but only the class containing the factory method. In this example, the createInstance() method must be static. The following example shows how to set a factory method:


<bean id="clientService"
    class="examples.ClientService"
    factory-method="createInstance"/>

In the following The example shows a class that will work with the previous bean definition:

Java

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}
    public static ClientService createInstance() {
        return clientService;
    }
}
Kotlin

class ClientService private constructor() {
     companion object {
         private val clientService = ClientService()
         @JvmStatic
         fun createInstance() = clientService
     }
}

Learn more about the mechanism for providing (optional) arguments to a factory method and setting the properties of an object instance after the object is returned from the factory.

Creating an instance using an instance factory method

Similar to creating an instance through a static factory method, creating an instance using an instance factory method calls a non-static method of an existing bean in the container to create a new bean. To use this mechanism, leave the class attribute empty, and in the factory-bean attribute specify the name of the bean in the current (or parent or predecessor) container that contains the instance method that will be called to create the object. Set the name of the factory method itself using the factory-method attribute. The following example shows how to configure such a bean:


<!-- a factory bean containing the createInstance() method -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
     <!-- inject any dependencies required by this locator bean -->
</bean>
<!-- bean that will be created using the factory bean -->
<bean id="clientService"
     factory-bean="serviceLocator"
     factory-method="createClientServiceInstance"/>

The following example shows the corresponding class :

Java

public class DefaultServiceLocator {
    private static ClientService clientService = new ClientServiceImpl();
    public ClientService createClientServiceInstance() {
         return clientService;
    }
}
Kotlin

class DefaultServiceLocator {
    companion object {
        private val clientService = ClientServiceImpl()
    }
    fun createClientServiceInstance(): ClientService {
        return clientService
    }
}

One factory class can contain more than one factory method, as shown in the following example:


<bean id="serviceLocator" class="examples. DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>
<bean id="clientService"
      factory-bean="serviceLocator"
      factory-method="createClientServiceInstance"/>
<bean id="accountService"
      factory-bean="serviceLocator"
      factory-method="createAccountServiceInstance"/>

The following example shows the corresponding class :

Java

public class DefaultServiceLocator {
    private static ClientService clientService = new ClientServiceImpl();
    private static AccountService accountService = new AccountServiceImpl();
    public ClientService createClientServiceInstance() {
        return clientService;
    }
    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}
Kotlin

class DefaultServiceLocator {
    companion object {
        private val clientService = ClientServiceImpl()
        private val accountService = AccountServiceImpl()
    }
    fun createClientServiceInstance(): ClientService {
        return clientService
    }
    fun createAccountServiceInstance(): AccountService {
        return accountService
    }
}

This approach demonstrates that A factory bean can be managed and configured using dependency injection (DI). See Dependencies and configuration details.

In the Spring documentation, a "factory bean" means a bean that is configured in a Spring container and creates objects using an instance or static factory method. Conversely, FactoryBean (note the capitalization) refers to the Spring-specific implementation class FactoryBean.

Determining the type of a bean at runtime

Determining the type of a particular bean at runtime is a non-trivial task. The specified class in a bean's metadata definition is simply the original reference to a class, potentially combined with a declared factory method or being a FactoryBean class, which could result in a different bean type at runtime, or not specified at all in the case instance-level factory method (which is resolved instead through the given name factory-bean). Additionally, AOP proxying can place a bean instance in an interface-based proxy with limited discovery of the actual type of the target bean (only its implemented interfaces).

The recommended way to find out the actual runtime type of a particular bean is to call BeanFactory.getType for the given bean name. This takes into account all the above cases and returns the object type that would be returned by calling BeanFactory.getBean for the same bean name.