Почему не удалось внедрить xml autowire, когда метод getter возвращает тип, отличный от свойства? - PullRequest
0 голосов
/ 22 июня 2019

Я написал фрагмент кода для проверки конфигурации xw с autowire. Но я все время получал исключение нулевого указателя, которое указывало на сбой автопроводки поля.

Вопреки некоторым другим примерам, которые могут работать, я обнаружил, что метод getter возвращает тип, отличный от поля, которое должно быть подключено. Удалите этот метод получения или измените тип возвращаемого значения, тогда он будет работать. Но я не знаю причину. Почему метод геттера имеет значение? Я думал, что метод сеттера используется для соединения, как насчет метода геттера?

public class Department {

    private String departName;

    public String getDepartName() {
        return departName;
    }

    public void setDepartName(String departName) {
        this.departName = departName;
    }

}

public class Employee {
    private Department department;

//  1) below code will cause NPE
    public String getDepartment() {
        return department.getDepartName();
    }

//   2)below code works,  or just delete  1) code  works as well
    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public void foo() {
        System.out.println(department.getDepartName());
    }
}

Файл конфигурации autowire xml выглядит следующим образом:

<bean id="depart" class="com.kingdom.Department">
        <property name="departName" value="risk"/>
    </bean>
    <bean id="employee" class="com.kingdom.Employee" autowire="byType">
    </bean>

и, наконец, основной класс:

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

        Employee employee = (Employee) ctx.getBean("employee");
        employee.foo();

Я ожидаю, что отдел может быть автоматически подключен к сотруднику. Но я получил NPE.

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:294)
    at java.lang.Thread.run (Thread.java:748)
Caused by: java.lang.NullPointerException
    at com.kingdom.Employee.foo (Employee.java:17)
    at com.kingdom.Main.main (Main.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:294)
    at java.lang.Thread.run (Thread.java:748)

После изменения типа возвращаемого значения он работает.

Но кто-нибудь должен знать, что происходит позади? почему геттерный метод подрывает автопроводку?

1 Ответ

1 голос
/ 22 июня 2019

Чтобы использовать autowire, вы должны включить его, включив <context:annotation-config> в beans.xml.Вы также можете включить его, включив <context:component-scan>, который неявно активирует функциональность <context:annotation-config>.

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

      <context:annotation-config>

      <bean> .... </bean>

</beans>

Затем вам нужно аннотировать @Autowired на установщике отдела Employee какСкажите Spring, чтобы он автоматически вводил бин Department в бин Employee.Вы также можете аннотировать его в поле отдела или в конструкторе.

public class Employee {

    @Autowired
    public void setDepartment(Department department) {
        this.department = department;
    }
}

Начиная с Spring 4.3, если у целевого бина есть только один конструктор, @Autowired больше не нужно явно аннотировать на целевом бине.Однако, если доступно несколько конструкторов, @Autowired должен существовать, чтобы научить контейнер вводить компонент.

То есть, если вы не хотите аннотировать @Autowired на Employee, вы должны сделать так, чтобы Employee имел только одного конструктора:

public class Employee {

    public Employee(Department department) {
        this.department = department;
    }
}

В обоихслучаях, <context:annotation-config> все еще требуется, чтобы автоматическое подключение вступило в силу.

...