前言
有人說不要用業務類實現InitializingBean接口,可以借助自定義的注解來實現類似的邏輯。那我們換這種思路實現下。
定義注解PayType
/**
* 消息通知類型注解
* @author francis
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PayType {
/**
* 支付類型
* @return
*/
PayTypeEnum value();
}
其中PayTypeEnum枚舉
@Getter
@AllArgsConstructor
public enum PayTypeEnum {
WX("WX", "微信"),
ZFB("A","支付寶支付"),;
private String type;
private String desc;
}
BeanPostProcessor(Bean后置處理器)
功能:它是Spring中定義的接口,在Spring容器的創建過程中(具體為Bean初始化前后)會回調BeanPostProcessor中定義的兩個方法。
- postProcessBeforeInitialization方法
會在每一個bean對象的初始化方法調用之前回調
- postProcessAfterInitialization方法
會在每個bean對象的初始化方法調用之后被回調
源碼如下:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
兩個方法入參說明:
bean:容器正在創建的那個bean的引用beanName:容器正在創建的那個bean的名稱
策略工廠實現BeanPostProcessor接口
getClass() 返回此 Object 的運行時該對象的類. 該方法返回一個Class對象, 可以通過該對象可以獲取某個類的相關信息, 如構造方法 屬性 方法 等
import com.example.demo.celuemoshi.PayService;
import com.example.demo.celuemoshi.PayTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Slf4j
public class StrategyFactory2 implements BeanPostProcessor {
private static final Map<PayTypeEnum, PayService> serviceMap = new ConcurrentHashMap<>();
/**
* @param bean 實例化bean的引用
* @param beanName 實例化bean的名字
* @return
* @throws
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 只對實現了PayService的類做操作
if (bean instanceof PayService) {
//獲取對象運行時該對象的類
Class<?> clazz = bean.getClass();
//獲取自定義的注解
PayType annotation = clazz.getAnnotation(PayType.class);
//綁定對應關系
serviceMap.put(annotation.value(), (PayService) bean);
}
return bean;
}
/**
* 尋找對應得策略處理器
*/
public PayService getHandler(PayTypeEnum type){
return serviceMap.get(type);
}
}
業務類加上@PayType
@Service
@Slf4j
@PayType(PayTypeEnum.ZFB)
public class AliService implements PayService {
public Boolean pay(String type) {
log.info("調用阿里支付={}",type);
return true;
}
}
import com.example.demo.strategy2.PayType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@PayType(PayTypeEnum.WX)
public class WxServiceA implements PayService {
@Override
public Boolean pay(String type) {
log.info("調用微信支付={}",type);
return true;
}
}
定義一個控制器測試
import com.example.demo.celuemoshi.StrategyFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PayController {
@GetMapping("pay/{type}")
public boolean pay(@PathVariable("type") String type){
StrategyFactory.getService(type);
return true;
}
}
測試結果
測試微信支付:http://localhost:10001/pay/wx

測試阿里支付:http://localhost:10001/pay/zfb

?