Whats is the order dependency injection in spring?

2019-07-19 15:45发布

I have a question regarding spring dependency injection. I need to know whether dependency gets injected in the order in which it has been declared in the XML or there is no order as such.

Example :

<bean id="empBean" class="com.test.EmployeeBean">
      <property name="jdbcTemplate" ref="jdbcTemplate" />
       <property name="empAddress" ref="empAddress" />
    </bean>

Can we guarantee that always jdbcTemplate will be initialized before empName? Please help

2条回答
我命由我不由天
2楼-- · 2019-07-19 15:59

You cannot guarantee that these will be injected in any particular order, and you should design your beans such that it doesn't matter -- which is easy to achieve.

So this class is bad code, because its state after bean-creation will differ depending on the order Spring happens to inject:

public class BadClass {
    private String foo = "";
    private String foobar = "";

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public void setBar(String bar) {
        this.foobar = foo + bar;
    }

    public String toString() {
        return foobar;
    }
}

Because:

 BadClass c = new BadClass(); 
 c.setFoo("foo");
 c.setBar("bar"); 
 return c.toString()` 

... returns "foobar".

 BadClass c = new BadClass(); 
 c.setBar("bar"); 
 c.setFoo("foo");
 return c.toString()` 

... returns "bar".

Many people think it's best practice to use constructor injection, in which case all the injections will occur in one invocation of the constructor.

public class BetterClass {
    private String foo = "";
    private String foobar = "";

    public BetterClass(String foo, String bar) {
        this.foo = foo;
        this.foobar = foo + bar;
    }

    public String toString() {
        return foobar;
    }
}
查看更多
3楼-- · 2019-07-19 16:11

Spring container will traverse the DAG (directed acyclic graph) of dependencies and will validate the configuration as much as possible without creating instances of the beans. The exceptions here are singleton-scoped and pre-instanciated beans, which are created on container creation. You can modify this behavior by adding lazy-init="true"property to the bean definition.

Only when the bean is requested in your code, it will get actually created created with all of its dependencies created first (and their dependencies if so needed) traversing the dependencies graph (DAG) all the way to the deepest dependencies.

Another case is when beans are defined later with the exact same name. These override the beans defined earlier - so if you have mocks for some of the beans, just define it after the core application beans have been loaded up.

You can add also add property depends-on="list,of,comma,separated,beanIDs" to your bean config to guide the container, when some dependencies are not explicit.

When configuring using annotated classes, you can also add @Order(N) where lower Ns get higher priority order used mostly to influence the order of beans being added to a collection, where order matters.

查看更多
登录 后发表回答