当前位置: 首页 > 科技观察

基于BeanPostProcessor接口+自定义注解玩策略模式

时间:2023-03-14 16:31:20 科技观察

前言有人说不应该使用业务类实现InitializingBean接口,可以使用自定义注解实现类似的逻辑。那么我们改变这种思路来实现它。定义注解PayType/***消息通知类型注解*@authorfrancis**/@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfacePayType{/***支付类型*@return*/PayTypeEnum值();}wherePayTypeEnumenumeration@Getter@AllArgsConstructorpublicenumPayTypeEnum{WX("WX","WeChat"),ZFB("A","支付宝支付"),;私有字符串类型;私有字符串描述;}BeanPostProcessor(Beanpost-processor)函数:是Spring中定义的一个接口,在Spring容器的创建过程中(具体是Bean初始化前后)会回调BeanPostProcessor中定义的两个方法。postProcessBeforeInitialization方法会在每个bean对象的初始化方法被调用之前被回调。postProcessAfterInitialization方法会在每个bean对象的初始化方法被调用后回调。源码如下:packageorg.springframework.beans.factory.config;导入org.springframework.beans。BeansException;importorg.springframework.lang.Nullable;publicinterfaceBeanPostProcessor{@NullabledefaultObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)抛出BeansException{returnbean;}@NullabledefaultObjectpostProcessAfterInitialization(Objectbean,Stringbean)prowtbeanbean;}}两个方法入参:bean:容器正在创建的bean的引用beanName:容器正在创建的bean的名称Policyfactory实现了BeanPostProcessor接口getClass()返回对象在运行时的类目的。该方法返回一个Class对象,通过该对象可以获取某个类的相关信息,如构造方法、属性方法等。PayTypeEnum;导入lombok.extern.slf4j.Slf4j;导入org.springframework.beans.BeansException;导入org.springframework.beans.factory.config.BeanPostProcessor;导入org.springframework.lang.Nullable;导入org.springframework.stereotype.Component;导入java.util.Map;导入java.util.concurrent.ConcurrentHashMap;@Component@Slf4jpublicclassStrategyFactory2implementsBeanPostProcessorMap{privateserviceMap=newConcurrentHashMap<>();/***@parambeanreferencetotheinstantiatedbean*@parambeanName实例化bean的名字*@return*@throws@NullablepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{//只操作那些类implementPayServiceif(beaninstanceofPayService){//获取对象运行时的类Classclazz=bean.getClass();//获取自定义AnnotationPayTypeannotation=clazz.getAnnotation(PayType.class);//绑定对应关系serviceMap.put(annotation.value(),(PayService)bean);}返回豆;}/***找到对应的策略处理设备*/publicPayServicegetHandler(PayTypeEnumtype){returnserviceMap.get(type);}}业务类加上@PayType@Service@Slf4j@PayType(PayTypeEnum.ZFB)publicclassAliServiceimplementsPayService{publicBooleanpay(Stringtype){log.info("CallAlipay={}",type);返回真;}}importcom.example.demo.strategy2.PayType;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Service;@Service@Slf4j@PayType(PayTypeEnum.WX)公共类WxServiceA实现PayService{@OverridepublicBooleanpay(Stringtype){log.info("调用微信支付={}",type);返回真;}}定义一个控件实现者测试.bind.annotation。RestController;@RestControllerpublicclassPayController{@GetMapping("pay/{type}")publicbooleanpay(@PathVariable("type")字符串类型){StrategyFactory.getService(类型);返回真;}}测试结果测试微信支付:http://localhost:10001/pay/wx测试阿里支付:http://localhost:10001/pay/zfb