• 实用设计模式实战:工厂+策略(另一种实现)


    本节主要的知识点InitializingBean接口和DependsOn注解

    书接上回,我们要用设计模式改造这个if/else

      public static void main(String[] args){
        String type = "common";
        operateByType(type);
      }
    
      private static void operateByType(String type) {
        if ("common".equals(type)){
          System.out.println("先查询缓存,缓存没有在查询数据库,同时更新缓存");
        }
        if ("update".equals(type)){
          System.out.println("直接更新缓存");
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上回我们使用ApplicationContextAware接口,实现了一个工厂+策略模式。这回我们换一种方式使用spring bean的 InitializingBean 接口重写afterPropertiesSet方法来实现工厂 +策略模式。

    InitializingBean 是 Spring 框架中的一个接口,用于在 Spring Bean 初始化时执行自定义的初始化逻辑。当一个 Spring Bean 实现了 InitializingBean 接口,它必须实现接口中的 afterPropertiesSet 方法。这个方法会在 Bean 的属性设置完成后(也就是依赖注入完成后),在 Bean 被容器初始化之后被调用。

    定义一个接口

    public interface AttributeNumberService {
        void operateByType();
    }
    
    
    • 1
    • 2
    • 3
    • 4

    定义一个工厂类

    
    public class AttributeNumberFactory {
    
        private static final Map<String, AttributeNumberService> processServiceMap = new ConcurrentHashMap<>();
    
        public static AttributeNumberService get(String type) {
            Assert.notNull(type, "type can't be null");
            return processServiceMap.get(type);
        }
    
        public static void put(String type,AttributeNumberService attributeNumberService){
            Assert.notNull(type, "transCode can't be null");
            processServiceMap.put(type, attributeNumberService);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    定义一个SpringBeanUtil,从spring上下文获取bean

    
    @Component
    public class SpringBeanUtil implements ApplicationContextAware {
    
      private static ApplicationContext context;
    
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringBeanUtil.context = applicationContext;
      }
    
      /** 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型. */
      public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ApplicationContextAware 接口是 Spring 框架中的一个接口,用于实现对 Spring 应用上下文(ApplicationContext)的感知,从而使一个类能够获取对应用上下文的引用。通过实现这个接口,类可以访问 Spring 容器中的 bean 实例和其他 Spring 特性。
    这个接口定义了一个方法 setApplicationContext,需要在实现类中实现。当 Spring 容器初始化 bean 时,如果 bean 实现了 ApplicationContextAware 接口,容器会自动调用 setApplicationContext 方法,并将应用上下文的引用作为参数传递给这个方法。

    AttributeNumberService实现类CommonAttributeNumberServiceImpl

    @Service
    @DependsOn(value = {"springBeanUtil"})
    public class CommonAttributeNumberServiceImpl implements AttributeNumberService,InitializingBean{
      @Override
      public void operateByType() {
        System.out.println("先查询缓存,缓存没有在查询数据库,同时更新缓存");
      }
    
      @Override
      public void afterPropertiesSet() throws Exception {
        AttributeNumberFactory.put("common", SpringBeanUtil.getBean(CommonAttributeNumberServiceImpl.class));
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这里我们实现了InitializingBean的afterPropertiesSet方法目的是把CommonAttributeNumberServiceImpl实例放入工厂中,我们使用SpringBeanUtil获取CommonAttributeNumberServiceImpl的实例放入工厂。
    使用DependsOn注解是因为springBeanUtil要先加载我们才能使用springBeanUtil工具类

    @DependsOn 注解是 Spring 框架中的一个注解,用于指定 bean 之间的初始化顺序。通过使用 @DependsOn 注解,您可以明确指定一个 bean 依赖于其他 bean,以确保在容器初始化时,依赖的 bean 先于当前 bean 初始化

    @Service
    @DependsOn(value = {"springBeanUtil"})
    public class UpdateAttributeNumberServiceImpl implements AttributeNumberService, InitializingBean {
      @Override
      public void operateByType() {
        System.out.println("直接更新缓存");
      }
    
      @Override
      public void afterPropertiesSet() throws Exception {
        AttributeNumberFactory.put(
            "update", SpringBeanUtil.getBean(UpdateAttributeNumberServiceImpl.class));
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    然后就可以使用啦

    @SpringBootTest()
    class ShejimoshiGcApplicationTests {
    
    
      @Test
      void operateByTypeTest() {
        AttributeNumberService common = AttributeNumberFactory.get("common");
        common.operateByType();
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    我们发现这个方法比上次的方法更复杂些,所以在工作中我们还是用上次的方法比较好

  • 相关阅读:
    【蓝桥杯选拔赛真题30】python开关灯 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
    【氮化镓】GaN HEMT SEEs效应影响因素和机制
    LeetCode每日一题(911. Online Election)
    线程与进程的实现
    One bite of Stream(5)
    MyBatis的一级缓存和二级缓存
    java版Spring Cloud+Mybatis+Oauth2+分布式+微服务+实现工程管理系统
    2:第一章:认识JVM规范1:JVM简介;
    ESP32网络开发实例-物联网声污染监测系统
    开源数据集分享———猫脸码客
  • 原文地址:https://blog.csdn.net/qq_25292419/article/details/133395969