Spring实现动态注入并按照类别获取相应实例的方法

有时我们在写项目的时候可能会遇见这种情况,就是我想写一个接口,但是这个接口又有多个实现类。这是符合接口实现原则的,但是有个问题就是当我在使用Spring框架进行此接口的自动注入时,在启动时会出问题(***Controller required a single bean, but 2 were found)。当然遇到这种情况我们也可以自己去按照类别new相应的实例,但是如果确实需要使用自动注入时,下边提供一个可选方案供参考。

假如我有个品牌工厂,这个品牌工厂即生产电脑又生产手机,当我需要生产电脑时就调用电脑工厂的生产方法,需要生产手机时就调用手机工厂的生产方法。

1、创建一个品牌工厂类

public interface IBrandFactory {
	
	public String getSupportProductType();  
	
	public String product();
}

2、创建电脑生产类实现品牌工厂类

public class ComputerProduct implements IBrandFactory {


	public String getSupportProductType() {
		return "computer";
	}


	public String product() {
		return "我负责生产电脑";
	}
	
}
3、创建手机生产类实现品牌工厂类

public class MobilePhoneProduct implements IBrandFactory {

	public String getSupportProductType() {
		return "mobilePhone";
	}

	public String product() {
		return "我负责生产手机";
	}
	
}
4、创建Controller类并使用@Autowired自动注入品牌工厂类

@RestController
public class TestController {
	@Autowired
	private List brandFactorys;
	
	@Autowired
	private IBrandFactory brand;
	
	public IBrandFactory get(String type) {  
		IBrandFactory brandFactory = null;  
  
        for (IBrandFactory tmpFactory : brandFactorys) {  
            if (tmpFactory.getSupportProductType().equals(type)) {  
            	brandFactory = tmpFactory;  
                break;  
            }  
        }  
  
        return brandFactory;  
    }  
	

	@RequestMapping(value = "/test", method = RequestMethod.GET)
	ResponseEntity findBlockDataByBlockId() {
		IBrandFactory bf = get("mobilePhone");
		return new ResponseEntity(bf.product(), HttpStatus.OK);

	}
} 
  

大功告成,此方案的重点就是在@Autowired注入时,不是注入的一个IBrandFactory接口,而是注入的一个接口集合,这样就可以避免项目启动时,有多个实现类而导致Spring无法判断正确的实例创建。然后再通过一个get方法去按照不同类别去List集合(注意此处的自动注入的集合已经包含了ComputerProduct和MobilePhoneProduct的实例,不用再自己创建,实际使用中你有多少个接口实现类,此处就会自动注入所有的实例)中取相应的实例。


另外还有个知识点,就是如果你在Controller中已经明确知道你所需注入的类,那么可以使用@Autowired搭配@Qualifier("你需注入的其中一个实现类类名首字母小写或者自己取的bean id的名字");另外还有个@Primary注解,它可以让Spring在注入bean时,当有多个实现类,Spring就只注入有@Primary注解的那个实现bean。






你可能感兴趣的:(Spring/Spring,boot)