Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why did Spring ignore my @DependsOn annotation?

Tags:

I'm using Spring 3.1.3 for a webapp, using XML configuration with component scanning.

I realized that one of the scanned components has to be initialized before several others. On all the classes that need post-construct initialization, I have a @PostConstruct annotation on a method.

To set up the dependency order, I changed '@Component' to '@Component("configData")' on the class that needs to be post-constructed before the others. I then added '@DependsOn("configData")' just before each class definition that needs to be post-constructed AFTER the "configData" bean.

From what I've read, this is all I need to enforce the dependency order.

I then built everything, set my breakpoints, and started up the app. I expected to hit the breakpoint in the "configData" bean before any of the dependent beans. This isn't what happened. The first breakpoint was in the "init" method of one of the dependent beans.

I then changed my "log4j.xml" to set "debug" as the logging level for "org.springframework" and reran my test. The breakpoint behavior was the same, and my logging didn't show any debug information about Spring initialization (I have debugging on for log4j initialization itself, so I confirmed that I had DEBUG set for "org.springframework").

What might I be missing?

Update:

If it matters, here are a couple of skeleton examples of what I'm doing here.

@Component("configData") public class ConfigData {     ....     @PostConstruct     public void init() {         ....     } }  @Component @DependsOn("configData") public class ClassDependentOnConfigData extends BaseClass {     ....     @Override     @PostConstruct     public void init() {         super.init();         ....     } } 

To reiterate, what I'm finding at runtime is that the "init()" method in "ClassDependentOnConfigData" is being called by Spring before the "init()" method in "ConfigData".

Note also that "BaseClass" has an "@Autowired" for "ConfigData".

like image 356
David M. Karr Avatar asked Mar 04 '14 17:03

David M. Karr


People also ask

What is @DependsOn in Spring?

The @DependsOn annotation in spring forces the IoC container to initialize one or more beans. This annotation is directly used on any class or indirectly annotated with @Component or on methods annotated with @Bean .

How do you turn on annotation wiring in Spring?

Annotation wiring is not turned on in the Spring container by default. So, before we can use annotation-based wiring, we will need to enable it in our Spring configuration file. So consider the following configuration file in case you want to use any annotation in your Spring application.


2 Answers

(From someone else's correct but now deleted answer)

The @DependsOn contract only guarantees that the bean has been constructed and properties have been set. This will not guarantee that any @PostConstruct methods have been called.

The way to get this to work is to have the "dependee" class (the class that others depend on) implement the "InitializingBean" class, which requires implementing the "afterPropertiesSet()" method. I put the original body of my "init()" method into this method. I verified that this is now executed before any of the classes that depend on this.

Another thing that was mentioned in the original answer is that if I had defined my "dependee" bean in XML and used the "init-method" property, this WOULD have executed before any of the classes that depend on this. I didn't verify this.

like image 171
David M. Karr Avatar answered Feb 22 '23 23:02

David M. Karr


I also encoutered the same problem, but still not properly resolved. As a part of a solution Spring documentation says:

"Using DependsOn at the class level has no effect unless component-scanning is being used."

This is the reason why the @dependsOn annotation has no effect.

like image 35
FredEtHop Avatar answered Feb 23 '23 00:02

FredEtHop