zoukankan      html  css  js  c++  java
  • 利用ApplicationListener和ContextRefreshedEvent加载自己的beanPool

    基本原理:

      1、Spring的ApplicationListener和ContextRefreshedEvent一般都是成对出现的。

      2、在IOC的容器的启动过程中,当所有的bean都已经处理完成之后,spring ioc容器会有一个发布事件的动作。

      3、当该发布事件的监听者监听到此动作时,ApplicationListener接口实例中的onApplicationEvent(E event)方法就会被调用。

      4、调用该方法时,通过父类找到实现类,再根据业务场景(以下示例中为serviceID),将对应的bean填充至beanPool中。

      5、这样,在编写业务代码时,直接通过serviceID就能找到对应处理的类

    上代码

    父类及各实现子类:

    package com.test;
    
    /**
     * @author zyydd
     * @date 2019/12/9 10:37
     */
    public abstract class TestServiceBase {
        protected abstract String getServiceId();
    
        public abstract void handle();
    }
    
    
    package com.test;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    
    /**
     * @author zyydd
     * @date 2019/12/9 10:36
     */
    @Service
    public class AtestService extends TestServiceBase {
        private static final Logger logger = LoggerFactory.getLogger(AtestService.class);
    
        @Value("${testService.serviceId.aTest}")
        private String serviceId;
    
        @Override
        protected String getServiceId() {
            return serviceId;
        }
    
        @Override
        public void handle() {
            logger.info("hi everyOne, this is A!");
        }
    }
    
    
    package com.test;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    
    /**
     * @author zyydd
     * @date 2019/12/9 10:36
     */
    @Service
    public class BtestService extends TestServiceBase {
        private static final Logger logger = LoggerFactory.getLogger(BtestService.class);
    
        @Value("${testService.serviceId.bTest}")
        private String serviceId;
    
        @Override
        protected String getServiceId() {
            return serviceId;
        }
    
        @Override
        public void handle() {
            logger.info("hi everyOne, this is B!");
        }
    }

    其中,serviceID是通过读取yaml中的配置,填充进去的,yaml配置:

    testService:
      serviceId:
        aTest: 1001
        bTest: 1002

    自建的beanPool,系统启动时填充,业务流程中通过serviceID获取:

    package com.test;
    
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import java.util.HashMap;
    
    /**
     * @author zyydd
     * @date 2019/12/9 10:42
     */
    @Service
    public class TestServicePool {
        private HashMap<String, TestServiceBase> testServiceMap = new HashMap<>(16);
    
        public TestServiceBase get(String serviceId) {
            return testServiceMap.get(serviceId);
        }
    
        public void put(String serviceId, TestServiceBase testService) {
            if (StringUtils.isEmpty(serviceId) || testService == null) {
                return;
            }
            this.testServiceMap.put(serviceId, testService);
        }
    }

    ApplicationListener接口实例,填充beanPool:

    package com.test;
    
    import com.**.util.JsonUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.event.ContextRefreshedEvent;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    
    import java.util.Map;
    
    /**
     * @author zyydd
     * @date 2019/12/9 10:46
     */
    @Component
    public class TestServiceLoadListener implements ApplicationListener<ContextRefreshedEvent> {
        private static final Logger logger = LoggerFactory.getLogger(TestServiceLoadListener.class);
    
        @Autowired
        private TestServicePool testServicePool;
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            if (event.getApplicationContext().getParent() == null) {
                logger.info("TestServiceLoadListener 开始加载");
                //根据父类(TestServiceBase)加载子类bean
                Map<String, TestServiceBase> beanMap = event.getApplicationContext().getBeansOfType(TestServiceBase.class);
                logger.info("TestServiceLoadListener 加载结果={}", JsonUtils.toJSONString(beanMap));
                //将子类挨个填充到testServicePool中
                if (CollectionUtils.isEmpty(beanMap)) {
                    logger.error("TestServiceLoadListener 加载失败,无法获取TestServiceBase的子类!");
                    return;
                } else {
                    for (TestServiceBase bean : beanMap.values()) {
                        testServicePool.put(bean.getServiceId(), bean);
                        logger.info("TestServiceLoadListener 加载一个: serviceid={} bean={}", bean.getServiceId(), bean.getClass().getName());
                    }
                }
            }
        }
    }

    单元测试类:

    package com.**.service;
    
    import com.**.web.Application;
    import com.test.TestServiceBase;
    import com.test.TestServicePool;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * @author zyydd
     * @date 2019/6/3 10:54
     */
    @SpringBootTest(classes = Application.class)
    @RunWith(SpringRunner.class)
    public class TestServiceTest {
        private static final Logger logger = LoggerFactory.getLogger(TestServiceTest.class);
    
        @Autowired
        private TestServicePool testServicePool;
    
        @Test
        public void testTestServicePool() {
            TestServiceBase a = testServicePool.get("1001");
            logger.info(a.getClass().getName());
            a.handle();
        }
    
    }

    单元测试执行结果:

    2019-12-09 11:12:26.100 INFO  [main] com.test.TestServiceLoadListener [28] - TestServiceLoadListener 开始加载
    2019-12-09 11:12:26.112 INFO  [main] com.test.TestServiceLoadListener [31] - TestServiceLoadListener 加载结果={"atestService":{},"btestService":{}}
    2019-12-09 11:12:26.113 INFO  [main] com.test.TestServiceLoadListener [39] - TestServiceLoadListener 加载一个: serviceid=1001 bean=com.test.AtestService
    2019-12-09 11:12:26.113 INFO  [main] com.test.TestServiceLoadListener [39] - TestServiceLoadListener 加载一个: serviceid=1002 bean=com.test.BtestService
    
    2019-12-09 11:12:27.067 INFO  [main] com.**.service.TestServiceTest [30] - com.test.AtestService
    2019-12-09 11:12:27.067 INFO  [main] com.test.AtestService [26] - hi everyOne, this is A!
  • 相关阅读:
    shell学习之杂项
    boot小知识
    记一个数组的问题
    lnmp安装exif扩展
    国内的Git比GitHub快
    重用思想,要有识别出好代码的眼睛,识别出腐朽代码的眼睛
    CSS3之超出隐藏
    如何测量设计图中图片的尺寸,像素
    Linux 软链接操作项目
    微信小程序申请。很蛋疼的流程。
  • 原文地址:https://www.cnblogs.com/zhenyuyaodidiao/p/12010053.html
Copyright © 2011-2022 走看看