即使在Spring容器管理依赖项之后,也无法自动装配服务

时间:2016-06-09 21:13:51

标签: java spring spring-mvc

我一直在修改我的类,以避免在我的控制器中new(让Spring的容器管理它)上的 StudentService 运算符。我需要Student student;字段注入StudentService,但不是注入student,而是注入异常:   No qualifying bean of type [com.Student] is defined: expected single matching bean but found 2: studentService,ss

我想要打印这个程序

  

NAME:bravo

学生:

package com;
public interface Student {
    public String getN();
}

StudentService:

package com;
import org.springframework.stereotype.Service;
@Service
public class StudentService implements Student{
String name;
    @Override
    public String getN() {
      return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

控制器

 package com;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TheController {

    @Autowired
    private ApplicationContext appContext;

    @Autowired
    Student student; 

    @RequestMapping("/")
    public String aMethod() {

        StudentService ss = (StudentService) appContext.getBean("ss");
        ss.setName("bravo");

        System.out.println("NAME : " + student.getN());
        // while "NAME : " + ss.getN() will work, of course
        return "";
    }
}

调度员的servlet

...
 <context:component-scan base-package="com" /> 

 ...
  <bean id="ss" class="com.StudentService" />

...

编辑:如果我这样做:

@Service ("st")

public class StudentService implements Student{

和(在控制器中)

@Autowired
@Qualifier("st")
Student student; // tipenya interface

没有例外,但它会产生

  

NAME:null

如果我删除了@Service并将StudentService加载为<bean class="com.StudentService".. >并通过应用程序上下文手动加载它,那么它就能正常工作。

我的意思是@Service无法自动装配

2 个答案:

答案 0 :(得分:2)

Spring知道两种以上的方式来声明&#​​34; bean&#34; (它可以用来注入的对象)。一个是xml:

<bean id="ss" class="com.StudentService" />

这将导致spring通过执行"ss"创建名为new com.StudentService(...)的bean。它甚至应该通过查找匹配的其他bean来尝试找出构造函数参数。生成的对象存储在应用程序上下文中以供将来使用。例如。当某些地方请求获取StudentService类型的bean或名为"ss"的bean时。

@Service

@Component以及其他一些人一样,会让spring对待这个附加到bean的类。该名称将来自班级名称:它只是低级的。它还将new该类型的实例并注意所有依赖项。 XML和@ -annotation配置的bean都可以在应用程序上下文中使用。

在你的情况下,你用两种不同的方式告诉spring:你希望com.StudentService可以作为bean使用,一旦通过xml明确命名"ss",一旦隐式命名为{{1在java。

现在,当您在控制器中请求与"studentService"类型相匹配的bean时,

Student

它有2个同样优秀的候选人,无法决定注入哪一个。这是你目前的例外。

要解决此问题,您可以只声明1个bean(最好),或者通过提供名称来限定您的意思。例如

@Autowired
Student student; 

这几乎就是你以后用

做的事情
@Autowired
@Qualifier("ss")
Student student;

当你将两者结合起来时

StudentService ss = (StudentService) appContext.getBean("ss");

现在你有2个独立的bean / @Autowired @Qualifier("st") Student student; ... StudentService ss = (StudentService) appContext.getBean("ss"); ss.setName("bravo"); System.out.println("NAME : " + student.getN()); 实例,它们都是&#34;单身&#34; (他们的豆子名字)。您将名称设置为1,并读取另一个的名称。预期的结果是StudentService bean的名称仍为空。

答案 1 :(得分:1)

让我们看一下aMethod

@RequestMapping("/")
public String aMethod() {

    StudentService ss = (StudentService) appContext.getBean("ss");
    ss.setName("bravo");

    System.out.println("NAME : " + student.getN());
    // while "NAME : " + ss.getN() will work, of course
    return "";
}

在此方法中,您需要创建名为StudentService的{​​{1}}对象。在下面,您调用ss接口方法,将setName名称设置为bravo。 但是,当您致电StudentService时,您正在检索其他对象的名称

要解决此问题,您可以检索由student.getN()管理的Student对象:

StudentService

但是为了特殊性,我建议将两者分离,只使用@Service public class StudentService { @Autowired Student student; public Student getStudent() { return student; } public void setName() { this.student.setName(Alfred); } } Student而不使用服务。