5

Some strange behavior from Spring 3.0 here.

package com.service.schedule;

import org.springframework.stereotype.Component;

@Component("outroJob")
public class OutroJob {

    public void printMe() {
        System.out.println("running...");
    }

}

and

package com.service.schedule;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

@Component("testeAutowired")
public class TesteAutowired {

    @Autowired
    public TesteAutowired(OutroJob outroJob) {
        outroJob.printMe();
    }

    public static void main(String[] args) {
        ClassPathResource res = new ClassPathResource("applicationContext.xml");
        XmlBeanFactory ctx = new XmlBeanFactory(res);

        OutroJob outroJob = (OutroJob) ctx.getBean("outroJob");
        outroJob.printMe(); // gives: running...

        ctx.getBean("testeAutowired");
    }
}

None of these beans are declared on applicationContext.xml

So, line outroJob.printMe(); works fine... prints "running..."

But when I try to get the "testeAutowired" bean, it says:

Could not instantiate bean class [com.service.schedule.TesteAutowired]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.service.schedule.TesteAutowired.

The question is: why, if Spring found the "outroJob" bean it doesn't autowired it on the TesteAutowired constructor ?

It seems obvious what it has to do...

javanna
  • 59,145
  • 14
  • 144
  • 125
chuckedw
  • 648
  • 2
  • 9
  • 13
  • What happens if you use ApplicationContext instead of XmlBeanFactory? I see XmlBeanFactory is deprecated in 3.1, maybe that's one of the reasons. – soulcheck Dec 01 '11 at 01:25

4 Answers4

1

Try using ApplicationContext instead of XmlBeanFactory. XmlBeanFactory doesn't postprocess annotations ie doesn't use AutowiredAnnotationBeanPostProcessor which would explain the behaviour you're experiencing.

Here's some more explanation

Community
  • 1
  • 1
soulcheck
  • 36,297
  • 6
  • 91
  • 90
0

I get the same error message but have different problem. I was using XML configuration and put @Autowired on class constructor.

I fixed this problem by enabling annotation driven config in my XML configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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/>
csharpfolk
  • 4,124
  • 25
  • 31
0

Try using

@Autowired(required=true)
public TesteAutowired(OutroJob outroJob) {
    outroJob.printMe();
}

That should force Spring to use that constructor. Otherwise it builds a list of constructors and picks the best candidate. Apparently it really wants a default constructor as a candidate, I guess.

Reference: http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html

Nialscorva
  • 2,924
  • 2
  • 15
  • 16
  • 8
    I can't imagine how this could ever help when the default value for `required` is `true`. I.e. `@Autowired` == `@Autowired(required=true)` – Jan Zyka May 13 '15 at 09:53
0

Create an inteface for the component and try to autowire the interface and nore the class with the autowired contructor.

Kfir Bloch
  • 68
  • 2
  • 6