前言
有人说不要用业务类实现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
原文地址:https://www.toutiao.com/article/7160661452180226573/