服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 基于BeanPostProcessor接口+自定义注解玩转策略模式

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

2022-11-01 18:02深漂小小熊 Java教程

BeanPostProcessor是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法。

前言

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

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

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

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

原文地址:https://www.toutiao.com/article/7160661452180226573/

延伸 · 阅读

精彩推荐