J2Cache的SpringBootのStarter

法和安
2023-12-01

title: J2Cache的SpringBootのStarter tags:

  • SpringBoot
  • J2Cache
  • Starter categories: springboot date: 2017-11-27 23:28:37

背景

J2Cache是OsChina的两级缓存实现框架 但是代码比较老 代码考虑也比较死板 不支持多种配置

对于多profile的实现来说也 只能使用通过Maven的profile实现【不支持动态变更】

    public class J2Cache {
     
     
     
        private final static Logger log = LoggerFactory.getLogger(J2Cache.class);
     
     
     
        private final static String CONFIG_FILE = "/j2cache.properties";
     
        private final static CacheChannel channel;
     
        private final static Properties config;
     
     
     
        static {
     
            try {
     
                config = loadConfig();
     
                String cache_broadcast = config.getProperty("cache.broadcast");
     
                if ("redis".equalsIgnoreCase(cache_broadcast))
     
                    channel = RedisCacheChannel.getInstance();
     
                else if ("jgroups".equalsIgnoreCase(cache_broadcast))
     
                    channel = JGroupsCacheChannel.getInstance();
     
                else
     
                    throw new CacheException("Cache Channel not defined. name = " + cache_broadcast);
     
            } catch (IOException e) {
     
                throw new CacheException("Unabled to load j2cache configuration " + CONFIG_FILE, e);
     
            }
     
        }
     
     
     
        public static CacheChannel getChannel(){
     
            return channel;
     
        }
     
     
     
        public static Properties getConfig(){
     
            return config;
     
        }
     
     
     
        /**
     
         * 加载配置
     
         * @return
     
         * @throws IOException
     
         */
     
        private static Properties loadConfig() throws IOException {
     
            log.info("Load J2Cache Config File : [{}].", CONFIG_FILE);
     
            InputStream configStream = J2Cache.class.getClassLoader().getParent().getResourceAsStream(CONFIG_FILE);
     
            if(configStream == null)
     
                configStream = CacheManager.class.getResourceAsStream(CONFIG_FILE);
     
            if(configStream == null)
     
                throw new CacheException("Cannot find " + CONFIG_FILE + " !!!");
     
     
     
            Properties props = new Properties();
     
     
     
            try{
     
                props.load(configStream);
     
            }finally{
     
                configStream.close();
     
            }
     
     
     
            return props;
     
        }
     
     
     
    }
复制代码

很明显此处代码必须要读取j2cache.properties

那么在不同环境【profile】想要使用不同的配置只有通过maven在编译时修改配置文件了【或者同样的其他手段】

思路

  1. 为了最小化的修改代价 不建议直接将所有的配置放到SpringBoot的application-${profile}.properties中 因为比如其他Jar中都是依靠J2Cache.getChannel() 来获取对应的cacheChannel
  2. 那么我们可以修改读取的配置文件即可【换言之我们考虑读取不同的j2cache.properties】
  3. 保留静态方法 但是静态代码块移除【以免一旦加载到该Class就会直接初始化】
  4. 在getChannel等方法做检查必须提前调用初始化方法

方案

    /**
     * 缓存入口
     *
     * @author winterlau
     */
    public class J2Cache {
     
        private final static Logger log = LoggerFactory.getLogger(J2Cache.class);
     
        private final static String CONFIG_FILE = "/j2cache.properties";
        private static CacheChannel channel;
        private static Properties config;
        private static AtomicBoolean initlized = new AtomicBoolean(false);
     
     
        public static void init() {
            init(CONFIG_FILE);
        }
     
        public static void init(String filePath) {
            if (initlized.compareAndSet(false, true)) {
                try {
                    config = loadConfig(filePath);
                    String cache_broadcast = config.getProperty("cache.broadcast");
                    if ("redis".equalsIgnoreCase(cache_broadcast)) {
                        channel = RedisCacheChannel.getInstance();
                    } else if ("jgroups".equalsIgnoreCase(cache_broadcast)) {
                        channel = JGroupsCacheChannel.getInstance();
                    } else {
                        initlized.set(false);
                        throw new CacheException("Cache Channel not defined. name = " + cache_broadcast);
                    }
                } catch (IOException e) {
                    initlized.set(false);
                    throw new CacheException("Unabled to load j2cache configuration " + filePath, e);
                }
            } else {
                log.warn("J2cache initlized alerday!");
            }
        }
     
        private static void checkInitlized() {
            if (!initlized.get()) {
                throw new CacheException("J2cache init not yet! You should call j2Cache.init(String) first!");
            }
        }
     
        public static CacheChannel getChannel() {
            checkInitlized();
            return channel;
        }
     
        public static Properties getConfig() {
            checkInitlized();
            return config;
        }
     
        /**
         * 加载配置
         *
         * @param filePath
         * @return
         * @throws IOException
         */
        private static Properties loadConfig(String filePath) throws IOException {
            if (filePath == null || filePath.trim().length() == 0) filePath = CONFIG_FILE;
            log.info("Load J2Cache Config File : [{}].", filePath);
            InputStream configStream = J2Cache.class.getResourceAsStream(filePath);
            if (configStream == null)
                configStream = CacheManager.class.getResourceAsStream(filePath);
            if (configStream == null)
                throw new CacheException("Cannot find " + filePath + " !!!");
     
            Properties props = new Properties();
     
            try {
                props.load(configStream);
            } finally {
                configStream.close();
            }
     
            return props;
        }
     
    }
复制代码

基于目前SpringBoot的使用我们创建对应的Starter

创建配置类

    package net.oschina.j2cache.autoconfigure;
     
    import org.springframework.boot.context.properties.ConfigurationProperties;
     
    @ConfigurationProperties(prefix = "j2cache")
    public class J2CacheConfig {
        private String configLocation = "/j2cache.properties";
     
        public String getConfigLocation() {
            return configLocation;
        }
     
        public void setConfigLocation(String configLocation) {
            this.configLocation = configLocation;
        }
    }
复制代码

创建初始化调用类

    package net.oschina.j2cache.autoconfigure;
     
    import net.oschina.j2cache.J2Cache;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
     
    import javax.annotation.PostConstruct;
     
    public class J2CacheIniter {
        private static Logger logger = LoggerFactory.getLogger(J2CacheIniter.class);
        private final J2CacheConfig j2CacheConfig;
     
        public J2CacheIniter(J2CacheConfig j2CacheConfig) {
            this.j2CacheConfig = j2CacheConfig;
        }
     
        @PostConstruct
        public void init() {
            J2Cache.init(j2CacheConfig.getConfigLocation());
        }
    }
复制代码

根据条件判断加载

    package net.oschina.j2cache.autoconfigure;
     
    import net.oschina.j2cache.J2Cache;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
     
    @ConditionalOnClass(J2Cache.class)
    @EnableConfigurationProperties({J2CacheConfig.class})
    @Configuration
    public class J2CacheAutoConfigure {
        private static Logger logger = LoggerFactory.getLogger(J2CacheAutoConfigure.class);
     
        private final J2CacheConfig j2CacheConfig;
     
        public J2CacheAutoConfigure(J2CacheConfig j2CacheConfig) {
            this.j2CacheConfig = j2CacheConfig;
        }
     
        @ConditionalOnMissingBean(J2CacheIniter.class)
        public J2CacheIniter j2CacheIniter() {
            return new J2CacheIniter(j2CacheConfig);
        }
     
     
    }
复制代码

创建META-INF/spring.factories

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    net.oschina.j2cache.autoconfigure.J2CacheAutoConfigure
复制代码

这样就会自动加载对应的

J2CacheAutoConfigure  可以参考SpringBoot之自动配置
复制代码

使用

系统中我们使用J2Cache作为SpringCache的实现

比如我们可以如此

    /*
     * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
     * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
     * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
     * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
     * Vestibulum commodo. Ut rhoncus gravida arcu.
     */
     
    package com.f6car.base.config;
     
    import net.oschina.j2cache.autoconfigure.J2CacheConfig;
    import net.oschina.j2cache.autoconfigure.J2CacheIniter;
    import org.nutz.j2cache.spring.SpringJ2CacheManager;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.ehcache.EhCacheManagerUtils;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    import org.springframework.context.annotation.PropertySource;
     
    @Configuration
    @PropertySource("classpath:j2cache/j2cache-${spring.profiles.active}.properties")
    public class CacheConfig {
        @Value("${ehcache.ehcache.name}")
        private String ehcacheName;
     
        @Bean("ehCacheManager")
        public net.sf.ehcache.CacheManager ehCacheManager() {
            return EhCacheManagerUtils.buildCacheManager(ehcacheName);
        }
     
        @DependsOn({"ehCacheManager", "j2CacheIniter"})
        @Bean
        public CacheManager springJ2CacheManager() {
            return new SpringJ2CacheManager();
        }
     
        @Bean("j2CacheIniter")
        public J2CacheIniter j2CacheIniter(J2CacheConfig j2cacheConfig) {
            return new J2CacheIniter(j2cacheConfig);
        }
     
    }
复制代码

如上我们就可以加载到不同的j2cache/j2cache-${spring.profiles.active}.properties

这样就完成了J2cache的初始化

 类似资料: