目錄
- 需求描述
- 程式碼實現
- 初始化容器配置
- 廠商型別列舉
- 策略來源註解
- 廠商來源工廠配置
- 初始化來源工廠配置
- 業務程式碼
需求描述
購買手機分為三個手機廠商:華為手機、小米手機、OPPO手機,根據每個手機廠商編碼檢視對應廠商旗艦手機。
程式碼實現
初始化容器配置
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* 初始化配置容器
*
* @author leizi
* @date 2024/03/17
*/
@Component
@Slf4j
public class AppContext implements ApplicationContextAware {
private static ApplicationContext appContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (null == appContext) {
if (null != applicationContext) {
AppContext.appContext = applicationContext;
}
log.info("Spring init successfully");
}
}
public static ApplicationContext getContext() {
if (appContext == null) {
throw new IllegalStateException("applicationContext inject failure,please restart the service");
}
return appContext;
}
}
廠商型別列舉
/**
* 手機廠商列舉
*
* @author leizi
* @date 2024/03/17
*/
public enum SourceTypeEnum {
HUAWEI(1, "華為廠商"),
XIAOMI(2, "小米廠商"),
OPPO(3, "OPPO廠商");
private Integer type;
private String memo;
SourceTypeEnum(Integer type, String memo) {
this.type = type;
this.memo = memo;
}
public Integer getType() {
return type;
}
public String getMemo() {
return memo;
}
/**
* 根據型別獲取例項
*
* @param type
* @return
*/
public static SourceTypeEnum getInstance(Integer type) {
if (null == type) {
return null;
}
for (SourceTypeEnum typeEnum : SourceTypeEnum.values()) {
if (typeEnum.type.equals(type)) {
return typeEnum;
}
}
return null;
}
}
策略來源註解
import com.example.demo.enums.SourceTypeEnum;
import org.springframework.stereotype.Component;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 廠商來源註解
*
* @author leizi
* @date 2024/03/17
*/
@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface SourceType {
SourceTypeEnum value();
}
廠商來源工廠配置
/**
* @author leizi
* @date 2024/03/18
*/
public interface InitProcess {
/**
* 初始化工廠
*/
void init();
}
import cn.hutool.core.map.MapUtil;
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author leizi
* @date 2024/03/17
*/
@Component
@Slf4j
public class FactoryHandlerStrategy implements InitProcess {
private static ConcurrentHashMap<SourceTypeEnum, PhoneManufacturerService> phoneManufacturerMap = new ConcurrentHashMap<>();
@Override
public void init() {
initPhoneManufacturer();
}
/**
* 初始化phoneManufacturerMap
*/
private void initPhoneManufacturer() {
// 載入PhoneManufacturerService 廠商處理實現類
Map<String, PhoneManufacturerService> mapPhoneManufacturer = AppContext.getContext().getBeansOfType(PhoneManufacturerService.class);
mapPhoneManufacturer.entrySet().stream().forEach(entry -> {
Class<? extends Object> clazz = entry.getValue().getClass();
SourceType annotation = clazz.getAnnotation(SourceType.class);
/*if (null == annotation) {
// 這裡為處理方法使用@Async,SourceType型別獲取失效問題
Map<String, Object> map = JSON.parseObject(JSON.toJSONString(entry.getValue()));
Object decoratedClass = map.get("decoratedClass");
try {
clazz = Class.forName(decoratedClass.toString());
annotation = clazz.getAnnotation(SourceType.class);
} catch (Exception e) {
log.error("class forName error:{}", e);
}
}*/
if (null == annotation) {
return;
}
SourceTypeEnum sourceType = annotation.value();
if (null != sourceType) {
PhoneManufacturerService phoneManufacturerService = phoneManufacturerMap.get(sourceType);
if (null != phoneManufacturerService) {
phoneManufacturerMap.remove(sourceType);
}
phoneManufacturerMap.put(sourceType, entry.getValue());
}
});
}
/**
* 根據廠商來源獲取實現類
*
* @param sourceType
* @return
*/
public PhoneManufacturerService getPhoneManufacturer(SourceTypeEnum sourceType) {
if (MapUtil.isEmpty(phoneManufacturerMap)) {
initPhoneManufacturer();
}
return phoneManufacturerMap.get(sourceType);
}
}
初始化來源工廠配置
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 初始配置
*
* @author leizi
* @date 2024/03/18
*/
@Component
public class InitContext implements ApplicationRunner {
private final FactoryHandlerStrategy factoryHandlerStrategy;
public InitContext(FactoryHandlerStrategy factoryHandlerStrategy) {
this.factoryHandlerStrategy = factoryHandlerStrategy;
}
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
/*
* 容器啟動完成把實現InitProcess實現類都執行init初始化操作,根據實際需要實現
* */
// Map<String, InitProcess> processMap = AppContext.getContext().getBeansOfType(InitProcess.class);
factoryHandlerStrategy.init();
}
}
業務程式碼
/**
* @author leizi
* @date 2024/03/17
*/
public interface PhoneManufacturerService {
/**
* 根據廠商型別檢視手機
*
* @param type 廠商型別
* @return
*/
String getPhone(Integer type);
/**
* 購買指定廠商手機
*
* @param type 廠商型別
* @return
*/
String buyPhone(Integer type);
}
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
/**
* OPPO廠商手機
*
* @author leizi
* @date 2024/03/17
*/
@SourceType(SourceTypeEnum.OPPO)
public class OppoManufacturerServiceImpl implements PhoneManufacturerService {
@Override
public String getPhone(Integer type) {
return "一臺OPPOFindX500旗艦手機";
}
@Override
public String buyPhone(Integer type) {
return "購買了OPPOFindX500旗艦手機";
}
}
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
/**
* 小米廠商手機
*
* @author leizi
* @date 2024/03/17
*/
@SourceType(SourceTypeEnum.XIAOMI)
public class XiaomiManufacturerServiceImpl implements PhoneManufacturerService {
@Override
public String getPhone(Integer type) {
return "一臺小米100pro旗艦手機";
}
@Override
public String buyPhone(Integer type) {
return "購買了小米100pro旗艦手機";
}
}
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
/**
* 華為廠商手機
*
* @author leizi
* @date 2024/03/17
*/
@SourceType(SourceTypeEnum.HUAWEI)
public class HuaweiManufacturerServiceImpl implements PhoneManufacturerService {
@Override
public String getPhone(Integer type) {
return "一臺華為Mete100旗艦手機";
}
@Override
public String buyPhone(Integer type) {
return "購買了華為Mete100旗艦手機";
}
}
import com.example.demo.config.FactoryHandlerStrategy;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author leizi
* @date 2024/03/17
*/
@RestController
@RequestMapping("/phone")
public class PhoneController {
private final FactoryHandlerStrategy factoryHandlerStrategy;
public PhoneController(FactoryHandlerStrategy factoryHandlerStrategy) {
this.factoryHandlerStrategy = factoryHandlerStrategy;
}
@GetMapping("/get")
public String getPhone(@RequestParam Integer type) {
PhoneManufacturerService manufacturerService = factoryHandlerStrategy.getPhoneManufacturer(SourceTypeEnum.getInstance(type));
if (null != manufacturerService) {
return manufacturerService.getPhone(type);
}
return "獲取失敗了";
}
}