@Service字段的自动装配失败

时间:2015-12-28 09:45:38

标签: java spring spring-mvc

我一整天都在看我的代码,我找不到原因。存储库(@Repository)运行正常,它是 @Service 字段,我一直无法让它自动装配,我一直在努力,因为一切都很好

enter image description here

调度的servlet:

<mvc:annotation-driven />
<context:component-scan base-package="com" /> 

com.repository

Repo.java

package com.repository;
import com.domain.Student;
import java.util.List;

public interface Repo { public List<Student> getAllSiswa();  }

RepoImplement.java

import com.domain.Student;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;

@Repository
public class RepoImplement implements Repo {
 List<Student> ls = new ArrayList<>();

public RepoImplement(){  
        Student s1 = new Student();
        s1.setNama("paul");

        Student s2 = new Student();
        s2.setNama("robert");

        ls.add(s1);
        ls.add(s2);
}

    @Override
    public List<Student> getAllSiswa() {    
       return this.ls;
    }
}

package com.service;

Serve.java

import com.domain.Student;
import java.util.List;

public interface Serve {
    void changeName(String namaBaru);
    public List<Student> newList();
}

我怀疑这里有什么问题

ServeImplement.java

import com.domain.Student;
import com.repository.Repo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ServeImplement implements Serve {
    @Autowired
    public Repo repo;  
    List<Student> s = repo.getAllSiswa(); // THIS IS SUSPECTING ME.

    @Override
    public void changeName(String namaBaru) {
        s.get(0).setNama(namaBaru); // get first Student, then update its name.
      }
    @Override
    public List<Student> newList() {
        return this.s;
    }
}

controller2.java 这是服务学生的映射请求

package com.controlller;
import com.domain.Student;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.service.Serve;

@Controller
public class controller2 {

    @Autowired
    public Serve serv;

    @RequestMapping("/changename")
    public ModelAndView sdaf() {
        serv.changeName("New name");
        List<Student> list = serv.newList();
        return new ModelAndView("page2", "out", list);
    }
}

错误:

  

创建名为'controller2'的bean时出错:注入自动装配   依赖失败;嵌套异常是   org.springframework.beans.factory.BeanCreationException:不能   autowire字段:public com.service.Serve   com.controlller.controller2.serv;嵌套异常是   org.springframework.beans.factory.BeanCreationException:错误   创建文件中定义名为'serveImplement'的bean   [C:\用户\汉斯\文件\的NetBeansProjects \ WebApplication2 \构建\网络\ WEB-INF \类\ COM \服务\ ServeImplement.class]:   bean的实例化失败;嵌套异常是   org.springframework.beans.BeanInstantiationException:不能   实例化bean类[com.service.ServeImplement]:构造函数抛出   例外;嵌套异常是java.lang.NullPointerException

2 个答案:

答案 0 :(得分:4)

您需要了解自动装配,或者事实上Java的工作原理。

Spring必须创建ServImpl类的实例,并使用存储库bean填充字段repo。它使用反射来做到这一点,但它的作用基本上等同于以下代码:

ServImpl s = new ServImpl();
s.repo = theRepoBean;

因此,在构造函数执行完后,您会看到s.repo变为非null 。并且,在执行构造函数时,执行以下代码行:

List<Student> s = repo.getAllSiswa();

此时,repo尚未初始化。所以它是空的。所以你得到一个NullPointerException。

使用构造函数注入而不是字段注入,或使用@PostConstruct带注释的方法。

请将您的字段设为私有而非公开。

也就是说,存储库的目标通常是从数据库中获取数据。学生可以在数据库中修改,删除或创建。因此,初始化您的服务字段并始终返回相同的列表会破坏拥有回购的重点。您应该在每次调用时从newList()调用repo.getAllSiswa(),以获取最新的最新学生列表。

答案 1 :(得分:1)

由于Autowired字段在构建后立即发生,因此您需要更改代码才能使其生效。

这应该有效:

@Service
public class ServeImplement implements Serve {

    public Repo repo;
    List<Student> s;

    @Autowired
    public ServeImplement(Repo repo) {
        this.repo = repo;
        s = repo.getAllSiswa();
    }

    @Override
    public void changeName(String namaBaru) {
        s.get(0).setNama(namaBaru); // get first Student, then update its name.
    }

    @Override
    public List<Student> newList() {
        return this.s;
    }

}

此外,在构造函数上使用Autorwired注释,如果实例不必更改,则允许您将字段标记为final