Friday, January 19, 2018

Different types of Bean Injection in Spring

1. Overview

This post briefly introduces the concept of Bean Injection in Spring Framework.

2. What is Bean Injection in Spring

Bean Injection is a real-life implementation of Dependency Injection (DI) pattern. Spring Framework uses bean injection to resolve bean dependencies. DI delegates control of bean construction from an application to Spring IoC (Inversion of Control) container

3. Types of Bean Injection

Spring provides two ways to handle Bean Injection for dependency resolution. This post will concentrate more at both ways for @Configuration annotated beans. We will also look at implementing the same in XML based configuration files.

3.1. Constructor Based Bean Injection

Dependent beans are injected using class constructors of wrapper beans. Ex. UserCredentials is injected into UserProfile bean using its constructor. These beans are defined in an @Configuration annotated component

    @Bean
    UserProfile userProfile() {
        UserProfile profile = new UserProfile(credentials());
        profile.setDemographic(demographic());
        return profile;
    }

    @Bean
    UserCredentials credentials() {
        String userName = environment.getProperty("uname");
        UserCredentials userCred = new UserCredentials();
        userCred.setUserName(userName);
        return userCred;
    }

Here, application, during start-up, instantiates UserProfile. By default, Spring creates singleton instance from @Bean annotated methods ex. credentials(). Hence, application here has a single instance of UserProfile initialised with a single UserCredentials instance.

3.2. Setter-Based Bean Injection

For setter based injection, we can inject dependent beans into their encapsulating classes using bean setters. Here we have injected Demographic information into UserProfile bean using its bean setter setDemographic

    @Bean
    Demographic demographic() {
        String city = environment.getProperty("city");
        String state = environment.getProperty("state");
        String zip = environment.getProperty("pin");
        return new Demographic(city, state, zip);
    }

    @Bean
    UserProfile userProfile() {
        UserProfile profile = new UserProfile(credentials());
        profile.setDemographic(demographic());
        return profile;
    }

3.3. XML based legacy bean definition

We can inject UserCredentials and Demographic in a custom application context configuration file in case of XML based bean definition.


3.4. Injecting Inner beans 

A real-life application will never expose a UserCredential and Demographic bean independently and individually. We will use inner bean injection in real-life since both are contextually bound to a UserProfile. We need to put both bean definitions under constructor or property tags. Ex. to illustrate

Here we have ensured that the application can never lookup a UserCredentials bean from application context.








Similarly, we can remove @Bean definition for UserCredentials and construct it during user profile creation.

3.5. Building Application Context

We can leverage ClassPathXmlApplicationContext to load beans from XML based configuration files.
    ApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");

4. Conclusion

Today application development world has different DI frameworks for use including Nano and the even more lightweight framework Pico. However, enterprise applications today prefer to use Spring DI. We suggest to leverage DI frameworks for large scale object-oriented implementations. This helps to move out objects instantiation, its timing and object dependency graph management from application to a pre-built and pre-tested IoC container