1

I am trying to figure out at what juncture does creation, registration and injection of beans in Spring IOC occur with annotation-config and @Autowired. I have the following test setup which is puzzling me because I don't see injections happening for the setter methods, but the bean properties do get set:

ActiveUser:

package com.example;

public class ActiveUser { 
  public ActiveUser() {
    System.out.println("Active User Created -> " + this);
  }
}

MiscUser:

package com.example;

public class MiscUser {     
    public MiscUser() {
        System.out.println("Misc User Created -> " + this);
    }
}

TopUser:

package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;

public class TopUser {

    private ActiveUser activeUser;

    private MiscUser miscUser;

    public TopUser() {
        System.out.println("Top User Created -> " + this);
        System.out.println("Setting Active User in constructor -> " + this.activeUser);
        System.out.println("Setting Misc User in constructor -> " + this.miscUser);
    }

    @Autowired
    public void setActiveUser(ActiveUser activeUser) {
        System.out.println("Setting Active User -> " + this.activeUser);
        this.activeUser = activeUser;
    }

    @Autowired
    @Required
    public void setMiscUser(MiscUser miscUser) {
        System.out.println("Setting Misc User -> " + this.miscUser);
        this.miscUser = miscUser;
    }

    public ActiveUser getActiveUser() {
        return activeUser;
    }

    public MiscUser getMiscUser() {
        return miscUser;
    }

}

applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
       ">

    <context:annotation-config/>
    <bean id="activeUser" class="com.example.ActiveUser"></bean>
    <bean id="miscUser" class="com.example.MiscUser"></bean>

    <bean id="topUser" class="com.example.TopUser"></bean>

</beans>

Main method class:

package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Executor {

    public static void main(String args[]){
        System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start Context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/example/applicationContext.xml");
        getContextInfo(context);        
        checkTopUser(context);
        System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    }

    private static void checkTopUser(ApplicationContext context) {
        TopUser tu = (TopUser) context.getBean(TopUser.class);
        if (tu.getActiveUser() == null) {
            System.out.println("TU's Active User is null!");
        } else {
            System.out.println("Retrieving Active User -> " + tu.getActiveUser());
        }
        if (tu.getMiscUser() == null) {
            System.out.println("TU's Misc User is null!");
        } else {
            System.out.println("Retrieving Misc User -> " + tu.getMiscUser());
        }
    }
}

The surprisingly part is that I don't see TopUser's properties being injected through setter methods based on the output, however, they are still being injected when TopUser bean is retrieved from the context:

Active User Created -> com.example.ActiveUser@5c5a1b69
Misc User Created -> com.example.MiscUser@3701eaf6
Top User Created -> com.example.TopUser@1f36e637
Setting Active User in constructor -> null
Setting Misc User in constructor -> null
Setting Misc User -> null
Setting Active User -> null

Retrieving Active User -> com.example.ActiveUser@5c5a1b69
Retrieving Misc User -> com.example.MiscUser@3701eaf6
NuCradle
  • 665
  • 1
  • 9
  • 31
  • 1
    Autowiring happens after the construction of an object. https://stackoverflow.com/a/6336013/1679484 – Amit Parashar Jun 14 '18 at 05:13
  • 1
    @NuCradle this is helpful article : (https://www.concretepage.com/spring/spring-autowired-annotation-example-with-setter-method-field-and-constructor-using-xml-and-java-configuration) **@Autowired Annotation Example with Setter Method** – 0gam Jun 14 '18 at 09:32

1 Answers1

1

Try to change as follows, instead of

@Autowired
    public void setActiveUser(ActiveUser activeUser) {
        System.out.println("Setting Active User -> " + this.activeUser);
        this.activeUser = activeUser;
}

1st option : (print after(not before) setting instance variable)

    @Autowired
    public void setActiveUser(ActiveUser activeUser) {
        this.activeUser = activeUser;
        System.out.println("Setting Active User -> " + this.activeUser);

}

2nd option : (grab method argument variable, rather than instance variable)

@Autowired
public void setActiveUser(ActiveUser activeUser) {
    this.activeUser = activeUser;
    System.out.println("Setting Active User -> " + activeUser);
}

Actually there is easier way to achieve your objective : you can ask Spring to notify you whenever bean is initialized through lifecycle methods. One way to do it is to implement InitializingBean interface in each bean, override afterPropertiesSet() method and output anything you like. afterPropertiesSet() will be called by container once bean is initialized and wired with all it's dependencies.

fg78nc
  • 4,774
  • 3
  • 19
  • 32