用工厂模式演示springboot三种注入方式 | @Autowired
背景:看了个demo工厂模式,示例代码的工厂类是new出来的,但是实际项目中都是用springboot框架、bean都是会给容器管理的,所以在思考这个工厂类要交给springboot托管要怎么改。以下是总结笔记
依赖注入
- 1.工厂类用new实现
- 2.工厂类用springboot容器,依赖注入
- 3.三种注入方式演示
- 4.其他总结
思考过程:看不懂工厂 -> 工厂用new -> 想改成bean注入,交给springboot管理
案例里提供两种实现方式:new 转成 依赖注入,交给springboot管理
难点:对依赖注入@Autowired理解不到位
1.工厂类用new实现
工厂模式:直接用new实现的代码
public class StoreFactory {
public ICommodity getCommodityService(Integer commodityType) {
if (null == commodityType) return null;
if (1 == commodityType) return new CouponCommodityService();
if (2 == commodityType) return new GoodsCommodityService();
if (3 == commodityType) return new CardCommodityService();
throw new RuntimeException("不存在的商品服务类型");
}
}
2.工厂类用springboot容器,依赖注入
难点:
- 不知道怎么把StoreFactory 变成bean :加@Component
- StoreFactory 变成bean之后要怎么往里面加入CouponCommodityService、GoodsCommodityService、CardCommodityService这些依赖到的bean:三种方式,@Autowired字段注入,构造器注入,set注入
- 压根不知道@Autowired还能标注在方法上:构造器注入和set注入都是@Autowired用来修饰方法的案例
- 这样的话,直接@Autowired标接口不就OK了?:是的,用字段注入就行
改用依赖注入的代码如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
public interface ICommodity {
void sendCommodity();
}
@Service
public class CouponCommodityService implements ICommodity {
@Override
public void sendCommodity() {
System.out.println("Coupon Commodity Service");
}
}
@Service
public class GoodsCommodityService implements ICommodity {
@Override
public void sendCommodity() {
System.out.println("Goods Commodity Service");
}
}
@Service
public class CardCommodityService implements ICommodity {
@Override
public void sendCommodity() {
System.out.println("Card Commodity Service");
}
}
@Component
public class StoreFactory {
private final CouponCommodityService couponCommodityService;
private final GoodsCommodityService goodsCommodityService;
private final CardCommodityService cardCommodityService;
@Autowired
public StoreFactory(CouponCommodityService couponCommodityService,
GoodsCommodityService goodsCommodityService,
CardCommodityService cardCommodityService) {
this.couponCommodityService = couponCommodityService;
this.goodsCommodityService = goodsCommodityService;
this.cardCommodityService = cardCommodityService;
}
public ICommodity getCommodityService(Integer commodityType) {
if (commodityType == null) {
return null;
}
switch (commodityType) {
case 1:
return couponCommodityService;
case 2:
return goodsCommodityService;
case 3:
return cardCommodityService;
default:
throw new RuntimeException("不存在的商品服务类型");
}
}
}
3.三种注入方式演示
@Component
public class BizService {
//TODO 三种依赖注入方式
@Value("${testFlag:0}")
private Integer testFlag;
//1.字段注入
@Autowired
private GoodsCommodityService goodsCommodityService;
private CouponCommodityService couponCommodityService;
private CardCommodityService cardCommodityService;
//2.构造器注入
@Autowired
public BizService(CouponCommodityService couponCommodityService) {
this.couponCommodityService = couponCommodityService;
}
//3.set注入(set注入不限置方法名是setxxx,spring是根据类型注入的)
@Autowired
public void cardCommodityServiceInject (CardCommodityService cardCommodityService) {
this.cardCommodityService = cardCommodityService;
}
/**
* 根据类型获取不同的Service 简单工厂
* @param type
* @return
*/
public ICommodity getICommodityByType(Integer type) {
System.out.println(testFlag);
if(testFlag == 0) {
System.out.println(0);
} else {
System.out.println(1);
}
switch (type) {
case 1:
return goodsCommodityService;
case 2:
return couponCommodityService;
case 3:
return cardCommodityService;
default:
return null;
}
}
}
4.其他总结
- @Component注解可以和 @Controller @Service @Repository互相替换。之所以常用后者是因为后者具备语义
- switch case的case用不了表达式、必须放已知的值。相比起if-else用在工厂模式里面,更直观
- 之前的在框架里使用到new但可以优化的例子:在项目里创建线程任务,用了new,依赖到的Service都是通过构造器传入的,很麻烦。现在应该直接用@Component修饰任务类,依赖的service直接@Autowired注入。最后要使用到任务类的时候就@Autowired字段注入就行