Java software development company

Technology: Spring is the popular framework for java developing applications in an obvious way by providing various utility classes. In this post, Java software development company experts will explain Spring Factory beans brief. Let’s get an overview of the spring container that offers two methods to create beans. We will also discuss these two methods – beans and factory beans.

Overview: Spring Container provides two ways to create beans, one is default beans by writing XML file or with Java annotations, second is the factory beans.

Spring Factory beans provide plug ability to Spring IOC Container`s bean initialization. If we need complex code to initialize the bean or if, we have more no of dependencies then instead of writing large XML we can create custom factory class and we can plug into Spring Container.

Factory Beans mostly used to help spring container in constructing beans which couldn`t easily construct by itself.

Example: suppose if we want to get the object from JNDI, we can use JNDIFactoryBean so that a reference to the bean created on loading time, whenever is need we can invoke getObject() method on factory bean which will return the actual bean reference.

Understanding about Factory Beans:

Spring provides a FactoryBean interface for creating factory beans.

Public interface FactoryBean<T> {

            T getObject() throws Exception;

            Class<?>getObjectType();      

            booleanisSingleton();

}

Let`s understand about methods:

getObject(): this is the main method to return an actual instance of the class, it may be the same instance or different instance based on implementation, as spring factory supports both singleton, and prototype design patterns. Before Spring 2.0 while calling getObject method if the factory bean is not fully initialized (depending on other beans, or circular dependencies) it use to throw FactoryBeanNotInitializedException exception, but after spring 2.0 if the factory bean is not loaded fully then it will return null, but it is encouraging to throw FactoryBeanNotInitializedException exception if factory bean not initialized.

getObjectType(): this method will return what type of object that factory bean will create. It will use in auto wiring of the beans without instantiating it. It may call before fully initializing the factory bean it may not depend on the state of the factory bean.

isSingleton(): this is method will tell the spring container, factory bean will return the same instance of the object every time we call getObject() or different instance of an object.

If this method returns true, then spring container will cache the instance of the bean without invoking getObject() method every time.

If this method returns false then spring container will execute getObject() every time, as we call getObject() method.

Creating beans using Spring Factory Bean interface:

We can create beans in two ways.

  1. We can implement the FactoryBean interface.
  2. Spring provides abstract implementation of the interface, by extending class we can write the factory beans. We need to override the createInstance() method to create the instance and getObjectType() method to tell return type to spring container for auto wiring.

If the instance provided by factory bean is singleton then it will return the object instance otherwise it will return, a proxy of the getObjectType() type of the object.

Some of the existing implementations of spring factory beans:

  1. JndiObjectFactoryBean: for creating beans depending upon JNDI lookup
  2. ProxyFactoryBean: for creating beans depends on Spring AOP pointcuts
  3. LocalSessionFactoryBean: for creating a Hibernate session factory in Spring IOC Container.

Writing custom Bean factories:

We will implement StudentFactoryBean to produces an object of the type Student.

Student.java

public class Student {

            private String firstName;

            private String lastName;

            private String email;

public Student(String email) {

                        this.email = email;

}

// getters and setters

}

StudentFactory.java

public class StudentFactory extends AbstractFactoryBean<Student> {

            private String email;  

            //setters and getters  

            @Override

            public Class<?>getObjectType() {

                        returnStudent.class;

            }

            @Override

            protected Student createInstance() throws Exception {

                        return new Student(email);

            }

            @Override

            publicbooleanisSingleton() {

                        return false;

            }

}

StudentFactory is the factory bean which will return student object.

XML Configuration: let’s create a spring beans XML file (student-factory-beans.xml) and add the below bean declaration.

<bean id=”student” class=”com.example.StudentFactory”>

<property name=”email” value=”[email protected]”/>

</bean>

Testing injected Student object:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { “classpath:spring-factory-beans.xml” })

publicclassStudentFactoryXmlTest {

            @Autowired

private Student student;

    @Test

publicvoidtestConstructWorkerByXml() {

assertThat(student.getEmail(), equalTo(“[email protected]”));

    }

}

The above test confirms that student object injected correctly using StudentFactorygetObject() method.

Accessing FactoryBean instance:

We can inject the factoryBean instance using by adding “&” before bean name.

Testing Student object injection using factoryBean injection:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { “classpath:spring-factory-beans.xml” })

publicclassStudentFactoryBeanXmlTest {

       @Resource(name=”&student”)

       privateStudentFactorystudentFactory;

       @Test

publicvoidtestConstructWorkerByXml() throws Exception {

assertThat(studentFactory.getObject().getEmail(), equalTo(“[email protected]”));

    }

}

Creating Factory Beans using Java Annotations:

We can create a configuration class using @Configuration annotation, and we can specify the class in @ContextConfiguration using classes attribute.

Creating configuration class:

@Configuration

publicclassStudentBeanConfig {

       @Bean(name=”student”)

       publicStudentFactorygetStudentFactory()

       {

              StudentFactorystudentFactory = newStudentFactory();

              studentFactory.setEmail(“[email protected]”);

              returnstudentFactory;

       }

}

And test class for Java annotation style:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes = StudentBeanConfig.class)

publicclassStudentFactoryJavaTest {

       @Autowired

       private Student student;

       @Test

       publicvoidtestConstructWorkerByXml() {

              assertThat(student.getEmail(), equalTo(“[email protected]”));

       }

}

The above test confirms that the Student object injected correctly.

We can also inject the factoryBean instance using Java Annotation style similar to XML configuration.

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes=StudentBeanConfig.class)

publicclassStudentFactoryBeanJavaTest {

       @Resource(name=”&student”)

       privateStudentFactorystudentFactory;

       @Test

publicvoidtestConstructWorkerByXml() throws Exception {

assertThat(studentFactory.getObject().getEmail(), equalTo(“[email protected]”));

    }

}

The above confirms that the studentFactory is successfully injected using “&” before the bean name.

Sometimes we need to do some operations before calling getObject() method then we can use InitializingBean interface, and implementing afterPropertiesSet() method or we can use @PostConstruct annotation on operation implemented method so that it called on start-up.

Conclusion: 

We can use factoryBean for a complex scenario for creating bean instances, we can either use XML configuration or annotation style. If the bean is, of the type factoryBean then spring IOC Container will call getObject() method on the instance for creating bean instances.

We can implement Initializing Bean interface or @PostConstruct annotation if we want to some operations before calling getObject() method to return the bean instance. FactoryBean also supports singleton and factory bean scoped bean instances.

You can follow the instructions shared by Java development company here in this post and know the Factory Beans. If you have any question, you may write in comments and wait for experts to respond to you.

By Anurag Rathod

Anurag Rathod is an Editor of Appclonescript.com, who is passionate for app-based startup solutions and on-demand business ideas. He believes in spreading tech trends. He is an avid reader and loves thinking out of the box to promote new technologies.