2016-03-07 3 views
3

Я пытаюсь ввести объект в класс. Однако поле всегда равно нулю. Я попробовал @Autowired и @Resource аннотации. Я не создаю объект с оператором new в любом месте. Конструктор Foo называется правильно.Spring bean создан, но имеет значение null, когда Autowired

Минимальный пример этой проблемы:

Foo класса

package foo.bar; 
public class Foo { 
    Foo(){ 
     System.out.println("Foo constructor"); 
    } 
    public void func() { 
     System.out.println("func()"); 
    } 
} 

Бар класса

package foo.bar; 
public class Bar { 
    @Autowired 
    private Foo foo; 

    public Bar() { 
     foo.func(); 
    } 
} 

Точка входа

package foo.bar; 
public class HelloApp { 
    public static void main(String[] args) { 
     ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); 
    } 
} 

весна-config.xml

<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
    <context:component-scan base-package="foo.bar"/> 
    <bean id = "foo" class="foo.bar.Foo" /> 
    <bean id = "bar" class="foo.bar.Bar" /> 
</beans> 

Почему foo поле Bar класса всегда null? Как я могу это исправить?

+3

Конструкторы вызываются до поля autowired. Поэтому вызов foo.func(); в конструкторе Bar приведет к NullPointer. Вы можете создать метод для вызова foo.func(); и аннотировать его с @PostConstruct, чтобы обойти это – Mick

ответ

2

Как указывал @Mick, вставка поля обязательно происходит после завершения конструктора (нет другого пути для Spring, чтобы увидеть экземпляр и манипулировать им). Измените класс, чтобы использовать инъекции конструктора, и вы оба будете делать ваши зависимости более четко (и, следовательно, легче проверить, например) и устранить то, что по существу состояние гонки:

public class Bar { 
    private Foo foo; 

    @Autowired 
    public Bar(Foo foo) { 
     this.foo = foo; 
     foo.func(); 
    } 
} 
+0

Спасибо, что работает отлично. Я просто подумал, что вся инициализация в Spring всегда (или должна быть) всегда выполняться в XML-файле при объявлении beans. Теперь мне нужно будет создать объект Foo и передать его конструктору. – RK1

+0

@ RK1 Spring знает, как создавать конструкторы autwire. Вам вообще не нужно изменять определения XML-компонентов. (Вы можете * явно указать аргументы конструктора в XML, если хотите, но до тех пор, пока компоненты не однозначны, Spring может решить их для вас.) – chrylis

+0

Да, мне ничего не нужно менять. Я просто подумал, что вам не нужно создавать экземпляры beans везде, когда используете Spring. – RK1

Смежные вопросы