开发者社区> 问答> 正文

spring ioc解决注入冲突方案,你有解决方法??报错

spring中,如何处理一个接口有两个实现类?

一个用户服务接口

public interface UserService{
   void add(User user){}
}

有老师和学生的两个具体服务

@Service //注入服务
public class StudentService implements UserService{
   public void add(User user){
   
   }
}

@Service //注入服务
public class TeacherService implements UserService{
   public void add(User user){
   
   }
}

老鸟:如果只定义如上代码,启动spring服务,是否会报错?

菜鸟:不会,那为什么?

老鸟:默认spring以实现类的类名首字母小写注入服务,即不同的实现类有不同的类名,故不会冲突,不报错。

那在对应的StudentController和TeacherController如何使用基于UserService接口,注入具体的实现?

@Controller
@RequestMapping("teachers")
public class TeacherController{
   @Autowired  //此处这样引用会不会报错?
   private UserService userService
   
   @PostMapping()
   @ResponseBody
   public ResultResponse add(Teacher teacher){
  
   }
}

上面的通过@Autowired来引用服务会不会报错?

菜鸟:不会?会

老鸟:会报错,因为现在UserService接口有两个实现类,要指定具体的实现,那如何实现?你有几种方式解决?(ps:只能以接口方式来引用,不能注入实现类)

展开
收起
爱吃鱼的程序员 2020-06-06 17:00:38 729 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB
                        <p>@Resource(name = "studentService")</p>
    

    private UserService userService;

                        <h4>引用来自“学而不思则罔”的评论</h4>
    
    public interface UserService {
        void addUser(String userName);
    }
    
    @Service("studentService")
    public class StudentServiceImpl implements UserService {
    
        @Override
        public void addUser(String userName) {
            System.out.println("StudentServiceImpl-->" + userName);
        }
    }
    
    @Service("teacherService")
    public class TeacherServiceImpl implements UserService {
    
        @Override
        public void addUser(String userName) {
            System.out.println("TeacherServiceImpl-->" + userName);
        }
    }
    
    public class UserServiceTest extends BaseSprintTestCase {
        @Autowired
        private UserService studentService;
    
        @Autowired
        private UserService teacherService;
    
        @Test
        public void testAddUser() {
            System.out.println("================测试注入start==============");
            studentService.addUser("学生");
            teacherService.addUser("老师");
            System.out.println("================测试注入end==============");
        }
    }

    工作这么多年,我一直习惯这么用写。

    注入的变量名就用studentService或teacherService还是接口方式注入。

    ps:楼主说会报错,我编辑了下,把自己的源码和测试类都贴上来了,另外附上测试结果:

                                回复 <a class="referer" target="_blank">@学而不思则罔</a>  : 好吧,现在做得更智能了?  Autowired不是按类型来注入,很能自动根据变量名来。
                        
    
                                回复 <a class="referer" target="_blank">@rabbitgg</a>  : 一直在用,你再看看吧,我把我的代码和测试类都放上来了,还有测试截图。
                        
    
                            你可以试试,会报错 
                        
    
                                回复 <a class="referer" target="_blank">@rabbitgg</a>  :     
    

    不是告诉你了吗? @Autowired //此处这样引用会不会报错? private UserService studentService;

    @Autowired private UserService teacherService;

                            我要的是怎么引用?
                        
    
                        <p>使用泛型就好了</p>
    
                    
    
                            泛型,怎么做?
                        
    
                        使用qualifer指定 
                    
    
                            这是其中的一个解决方案,还能想到更多?
                        
    
                        qualifier 
                    
    
                        <pre><code>@Controller
    

    @RequestMapping("teachers") public class TeacherController{ @Autowired //扩展经常使用,可以注入任意多个 private Map<String,UserService> userServices;

    @PostMapping() @ResponseBody public ResultResponse add(Teacher teacher){ UserService userService = chooseUserService(teacher); //userService业务逻辑 } /*选择合适的接口实现类/ private UserService chooseUserService(Teacher teacher)){ String id = xxxx(teacher); return userServices.get(id);

    }

    }

                        <p>UserService<StudentService> userService这样</p>
    
                    
    
                            这样能做?
                        
    
                        <p>使用@Qualifier注解可以解决这个问题。</p>
    

    首先在两个实现上定义不同的beanid:

    @Service("studentService") //定义beanid为studentService
    public class StudentService implements UserService{
       public void add(User user){
       
       }
    }
    
    @Service("teacherService") //定义beanid为teacherService
    public class TeacherService implements UserService{
       public void add(User user){
       
       }
    }

    注入的时候通过@Qualifier("beanid")指定其中一个:

    @Controller
    @RequestMapping("teachers")
    public class TeacherController{
       @Autowired 
       @Qualifier("teacherService") //通过beanid指定注入的服务
       private UserService userService
       
       @PostMapping()
       @ResponseBody
       public ResultResponse add(Teacher teacher){
      
       }
    }

     

                        <p>可以使用@Resource注解啊</p>
    
    2020-06-06 17:00:50
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载

相关实验场景

更多