1

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

 1 year ago
source link: https://www.51cto.com/article/721730.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

作者:深漂小小熊 2022-11-01 11:15:56
有人说不要用业务类实现InitializingBean接口,可以借助自定义的注解来实现类似的逻辑。那我们换这种思路实现下。

有人说不要用业务类实现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

620df6b64ee277d300c939575f3d77704f6a36.png

测试阿里支付:http://localhost:10001/pay/zfb

684823a8947d08c425f925c9ea9a9eba7c3924.png
责任编辑:武晓燕 来源: 今日头条

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK