SpringCache、JetCache、CaffeineCache本地缓存和其他工具使用

一、CaffeineCache

依赖

        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.8.4</version>
        </dependency>

        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>guava</artifactId>
            <version>2.8.4</version>
        </dependency>

代码实现

package com.citydo.jetcache;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import java.util.concurrent.TimeUnit;

/**
 * CaffeineCache
 */
public class CaffeineCache{

    Cache<String, Object> manualCache = Caffeine.newBuilder()
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .maximumSize(10_000)
            .build();

    /**
     * 获取缓存
     * @param key
     * @return
     */
    private Object getById(String key){
       return manualCache.getIfPresent(key);
    }


    /**
     * 添加缓存
     * @param key
     * @param value
     */
    private void addById(String key, String value){
        manualCache.put(key, value);
    }

    /**
     * 删除缓存
      * @param key
     */
    private void invalidate(String key){
       manualCache.invalidate(key);
    }

}

二、SpringCache

代码实现

package com.citydo.jetcache;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;


/**
 * SpringCache
 * @Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
 * @CachePut 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
 * @Cacheable 不同的是,它每次都会触发真实方法的调用
 * @CachEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空
 * @author nick
 */
@EnableCaching
@Configuration
public class SpringCache {

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("default")));
        return cacheManager;
    }

    /**
     * 获取缓存
     * @param id
     * @return
     */
    @Cacheable(value = "getById", key = "#id")
    public int getById(int id){
        return id;
    }

    /**
     * 添加缓存
     * @param id
     */
    @CachePut(value = "getById", key = "#id")
    public void addById(int id){ }

}

三、JetCache

依赖

        <dependency>
            <groupId>com.alicp.jetcache</groupId>
            <artifactId>jetcache-starter-redis</artifactId>
            <version>2.5.3</version>
        </dependency>

代码实现

package com.citydo.jetcache;

import com.alicp.jetcache.anno.CacheInvalidate;
import com.alicp.jetcache.anno.CacheUpdate;
import com.alicp.jetcache.anno.Cached;

public interface JetCacheService {

    /**
     * 查询缓存
     * @param userId
     * @return
     */
    @Cached(name="IdCache-", key="#Id", expire = 3600)
    String getById(String userId);

    /**
     * 更新缓存
     * @param Id
     */
    @CacheUpdate(name="IdCache-", key="#Id", value="#Id")
    void updateUser(String Id);

    /**
     * 删除缓存
     * @param Id
     */
    @CacheInvalidate(name="IdCache-", key="#Id")
    void deleteId(String Id);
}

import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;

import java.util.concurrent.TimeUnit;

/**
 *
 * JetCache
 * 本地TTL、两级缓存和分布式缓存自动刷新
 */
@EnableMethodCache(basePackages = "com.citydo.jetcache")
@EnableCreateCacheAnnotation
public class JetCache {

    private static int count = 0;

    /**
     * 添加缓存
     * @return
     */
    @Cached
    public int count() {
        return count++;
    }

    /**
     * 添加过期时间
     * @return
     */
    @Cached(expire = 50, cacheType = CacheType.LOCAL, timeUnit = TimeUnit.MILLISECONDS)
    public int countWithExpire50() {
        return count++;
    }
}

四、实用工具类

Java动态调用Groove代码

package com.citydo.jetcache;

import groovy.lang.GroovyClassLoader;

public class GroovyUtils{

    private static GroovyClassLoader loader = new GroovyClassLoader();

    public static Class parseClass(String groovy) {
        return loader.parseClass(groovy);
    }

}

字符串转集合,集合转字符串

package com.citydo.jetcache;

import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;



public class ListUtils {

    private static final String REGEX = ",";

    public static List<Integer> string2IntList(String str) {
        if (!StringUtils.hasText(str)) {
            return new ArrayList<>();
        }
        List<Integer> intList = new ArrayList<>();
        for (String elem :str.split(REGEX)) {
            if (!StringUtils.hasText(elem)) {
                continue;
            }
            intList.add(Integer.parseInt(elem));
        }
        return intList;
    }

    public static List<String> string2StrList(String str) {
        if (!StringUtils.hasText(str)) {
            return new ArrayList<>();
        }
        List<String> strList = new ArrayList<>();
        for (String elem: str.split(REGEX)) {
            if (!StringUtils.hasText(elem)) {
                continue;
            }
            strList.add(elem);
        }
        return strList;
    }

    public static String longList2String(List<Long> longList) {
        if (longList == null || longList.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        longList.stream().forEach(e->{
            if (e == null) {
                return;
            }
            sb.append(e).append(REGEX);
        });
        return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString();
    }

    public static String intList2String(List<Integer> intList) {
        if (intList == null || intList.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        intList.stream().forEach(e->{
            if (e == null) {
                return;
            }
            sb.append(e).append(REGEX);
        });
        return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString();
    }

    public static String strList2String(List<String> strList) {
        if (strList == null || strList.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        strList.stream().forEach(e->{
            if (!StringUtils.hasText(e)) {
                return;
            }
            sb.append(e).append(REGEX);
        });
        return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString();
    }
}

缓存锁

package com.citydo.jetcache;

import java.util.concurrent.ConcurrentHashMap;


public class CacheLockUtils {
    private static final ConcurrentHashMap<String, Integer> CACHE_LOCK = new ConcurrentHashMap<>();

    public static boolean lock(String key) {
        return CACHE_LOCK.putIfAbsent(key, 1) == null;
    }

    public static void unlock(String key) {
        CACHE_LOCK.remove(key);
    }
}

线程池工具类

package com.citydo.jetcache;

import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class ExecutorUtils {

    /**
     * The default rejected execution handler
     */
    private static final RejectedExecutionHandler defaultHandler = (r, executor) -> {
        log.info("Thread rejected task,start run task by caller,current queue size {}", executor.getQueue().size());
        if (!executor.isShutdown()) {
            r.run();
        }
    };

    /**
     * ExecutorHelper默认使用CachedThreadPool作为默认的线程池,但是有风险,不建议使用
     */
    private static class DefaultThreadPool {
        public static ExecutorService es = Executors.newCachedThreadPool(new DefaultThreadFactory("cache", null));
    }

    private static ExecutorService getCachedThreadPool() {
        return DefaultThreadPool.es;
    }

    /**
     * 停掉默认的线程池
     */
    public static void shutdown() {
        if (!getCachedThreadPool().isShutdown()) {
            getCachedThreadPool().shutdown();
        }
    }

    /**
     * 停掉线程池
     *
     * @param executorService
     */
    public static void shutdown(ExecutorService executorService) {
        if (!executorService.isShutdown()) {
            executorService.shutdown();
        }
    }

    public static ExecutorService newFixedThreadPool(int nThread, String threadName, int capacity) {
        return new ThreadPoolExecutor(nThread, nThread, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(capacity), new DefaultThreadFactory("fixed", threadName), defaultHandler);
    }

    /**
     * 创建线程名称前缀为threadPrefix的线程池
     *
     * @param threadPrefix
     * @return
     */
    public static ExecutorService newCachedThreadPool(String threadPrefix) {
        return Executors.newCachedThreadPool(new DefaultThreadFactory("cache", threadPrefix));
    }

    /**
     * 创建大小为threadSize的线程池,每个线程名称前缀为threadPrefix
     *
     * @param threadSize
     * @param threadPrefix
     * @return
     */
    public static ExecutorService newFixedThreadPool(Integer threadSize, String threadPrefix) {
        if (threadSize == null) {
            return null;
        }
        return Executors.newFixedThreadPool(threadSize.intValue(), new DefaultThreadFactory("fixed", threadPrefix));
    }

    /**
     * 创建大小为threadSize的缓存线程池,每个线程名称前缀为threadPrefix,超时时间为milliSeconds
     *
     * @param threadSize
     * @param threadPrefix
     * @param milliSeconds
     * @return
     */
    public static ExecutorService newFixedThreadPool(Integer threadSize, String threadPrefix, Long milliSeconds) {
        if (threadSize == null) {
            return null;
        }
        return new ThreadPoolExecutor(threadSize, threadSize,
                milliSeconds == null ? 0L : milliSeconds, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(),
                new DefaultThreadFactory("fixed", threadPrefix));
    }

    /**
     * 创建大小为threadSize,队列容量为capacity的缓存线程池,每个线程名称前缀为threadPrefix
     *
     * @param threadSize
     * @param threadPrefix
     * @param capacity
     * @return
     */
    public static ExecutorService newFixedThreadPool(Integer threadSize, String threadPrefix, Integer capacity) {
        if (threadSize == null) {
            return null;
        }
        return new ThreadPoolExecutor(threadSize, threadSize, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(capacity == null ? Integer.MAX_VALUE : capacity),
                new DefaultThreadFactory("fixed", threadPrefix), defaultHandler);
    }


    /**
     * 默认线程工厂
     */
    private static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory(String threadPoolType, String threadPrefix) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = "pool" + (threadPoolType == null ? "" : "-" + threadPoolType) + "-" + poolNumber.getAndIncrement() + "-thread-"
                    + (threadPrefix == null ? "" : threadPrefix);
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            if (t.isDaemon()) {
                t.setDaemon(true);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }

    /**
     * 交给executor执行任务
     *
     * @param executorService
     * @param call
     * @return
     */
    public static <T> Future<T> execAndReturn(ExecutorService executorService, Callable<T> call) {
        return executorService.submit(call);
    }

    /**
     * 交给executor执行任务
     *
     * @param call
     * @return
     */
    public static <T> Future<T> execAndReturn(Callable<T> call) {
        return execAndReturn(getCachedThreadPool(), call);
    }

    /**
     * 获取future里面的对象,抛出异常,用在对执行结果出错后不影响其他逻辑的地方
     *
     * @param future
     * @return
     */
    public static <T> T getFutureObject(Future<T> future) {

        T result = null;

        try {
            result = future.get();
        } catch (InterruptedException e) {
            log.error("getFutureObject InterruptedException,result=" + result, e.fillInStackTrace());
        } catch (ExecutionException e) {
            log.error("getFutureObject ExecutionException,result=" + result, e.fillInStackTrace());
        }

        return result;
    }

    /**
     * 并发执行多个任务
     *
     * @param executorService
     * @param callList
     * @return
     */
    public static <T> List<T> execListAndReturn(ExecutorService executorService, List<? extends Callable<T>> callList) {

        if (callList == null || callList.size() == 0) {
            return null;
        }

        List<T> result = new ArrayList<>();

        List<Future<T>> futures = new ArrayList<>();

        callList.stream().forEach(e-> futures.add(execAndReturn(executorService, e)));

        futures.stream().forEach(t->{
            boolean success = false;
            T ret = null;
            try {
                ret = t.get();
                result.add(ret);
                success = true;
            } catch (InterruptedException e) {
                log.error("execListAndReturn InterruptedException,ret=" + ret, e.fillInStackTrace());
            } catch (ExecutionException e) {
                log.error("execListAndReturn ExecutionException,ret=" + ret, e.fillInStackTrace());
            } finally {
                if (!success) {
                    result.add(null);
                }
            }
        });

        return result;

    }

    /**
     * 并发执行多个任务
     *
     * @param callList
     * @return
     */
    public static <T> List<T> execListAndReturn(List<? extends Callable<T>> callList) {
        return execListAndReturn(getCachedThreadPool(), callList);
    }

    /**
     * 并发执行多个任务
     *
     * @param executorService
     * @param callMap
     * @return
     */
    public static <K, V> Map<K, V> execMapAndReturn(ExecutorService executorService, Map<K, ? extends Callable<V>> callMap) {

        if (callMap == null || callMap.isEmpty()) {
            return null;
        }

        Set<K> keys = callMap.keySet();

        Map<K, V> result = new HashMap<>();

        Map<K, Future<V>> futures = new HashMap<>();

        keys.stream().forEach(e->{
            Callable<V> call = callMap.get(e);
            futures.put(e, execAndReturn(executorService, call));
        });

        keys.stream().forEach(t->{
            V val = null;
            try {
                val = futures.get(t).get();
                result.put(t, val);
            } catch (InterruptedException e) {
                log.error("execMapAndReturn InterruptedException,key=" + t + ",val=" + val, e.fillInStackTrace());
            } catch (ExecutionException e) {
                log.error("execMapAndReturn ExecutionException,key=" + t + ",val=" + val, e.fillInStackTrace());
            } catch (Exception e) {
                log.error("execMapAndReturn unknown exception,key=" + t + ",val=" + val, e.fillInStackTrace());
            }
        });

        return result;
    }

    /**
     * 并发执行多个任务
     *
     * @param callMap
     * @return
     */
    public static <K, V> Map<K, V> execMapAndReturn(Map<K, ? extends Callable<V>> callMap) {
        return execMapAndReturn(getCachedThreadPool(), callMap);
    }
}

对象复制新类型和同类型深度克隆工具类

package com.citydo.jetcache;

import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对象复制新类型和同类型深度克隆工具类
 */
public class CopyUtils {

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> T deepCopy(T obj) {
        if (obj == null) {
            return null;
        } else if (obj instanceof String) {
            return (T)(String) obj;
        } else if (obj instanceof Integer) {
            return (T)(Integer) obj;
        } else if (obj instanceof Double) {
            return (T)(Double) obj;
        } else if (obj instanceof Byte) {
            return (T)(Byte) obj;
        } else if (obj instanceof Short) {
            return (T)(Short) obj;
        } else if (obj instanceof Long) {
            return (T)(Long) obj;
        } else if (obj instanceof Float) {
            return (T)(Float) obj;
        } else if (obj instanceof Character) {
            return (T)(Character) obj;
        } else if (obj instanceof Boolean) {
            return (T)(Boolean) obj;
        } else if (obj instanceof ArrayList<?>) {
            return (T) arrayListHandler((ArrayList<?>) obj);
        } else if (obj instanceof HashMap<?, ?>) {
            return (T) mapHandler((Map<?, ?>) obj);
        } else if (obj instanceof ConcurrentHashMap<?, ?>) {
            return (T) concurrentMapHandler((Map<?, ?>) obj);
        } else if (obj instanceof TreeMap<?, ?>) {
            return (T) treeMapHandler((Map<?, ?>) obj);
        } else if (obj instanceof LinkedList<?>) {
            return (T) linkedListHandler((LinkedList<?>) obj);
        } else if (obj instanceof HashSet<?>) {
            return (T) hashSetHandler((HashSet<?>) obj);
        } else if (isPrimitiveArray(obj)) {
            return getPrimitiveArray(obj);
        }

        T finObj = null;
        Class rezClass = obj.getClass();
        rezClass.cast(finObj);
        try {
            Constructor<T> constructor = getCompleteConstructor(rezClass);
            finObj = (T) constructor.newInstance(getParamsObjForConstructor(rezClass));
            copyFields(rezClass, obj, finObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return finObj;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static <T> T deepCopy(T obj, Object parrent) {
        if (obj == null) {
            return null;
        } else if (obj instanceof String) {
            return (T)String.valueOf((String) obj);
        } else if (obj instanceof Integer) {
            return (T)Integer.valueOf((Integer) obj);
        } else if (obj instanceof Double) {
            return (T)Double.valueOf((Double) obj);
        } else if (obj instanceof Byte) {
            return (T)Byte.valueOf((Byte) obj);
        } else if (obj instanceof Short) {
            return (T)Short.valueOf((Short) obj);
        } else if (obj instanceof Long) {
            return (T)Long.valueOf((Long) obj);
        } else if (obj instanceof Float) {
            return (T)Float.valueOf((Float) obj);
        } else if (obj instanceof Character) {
            return (T)Character.valueOf((Character) obj);
        } else if (obj instanceof Boolean) {
            return (T)Boolean.valueOf((Boolean) obj);
        } else if (obj instanceof ArrayList<?>) {
            return (T) arrayListHandler((ArrayList<?>) obj);
        } else if (obj instanceof HashMap<?, ?>) {
            return (T) mapHandler((Map<?, ?>) obj);
        } else if (obj instanceof ConcurrentHashMap<?, ?>) {
            return (T) concurrentMapHandler((Map<?, ?>) obj);
        } else if (obj instanceof TreeMap<?, ?>) {
            return (T) treeMapHandler((Map<?, ?>) obj);
        } else if (obj instanceof LinkedList<?>) {
            return (T) linkedListHandler((LinkedList<?>) obj);
        } else if (obj instanceof HashSet<?>) {
            return (T) hashSetHandler((HashSet<?>) obj);
        } else if (isPrimitiveArray(obj)) {
            return getPrimitiveArray(obj);
        }

        T finObj = null;
        Class rezClass = obj.getClass();
        rezClass.cast(finObj);
        try {
            Constructor<T> constructor = getCompleteConstructor(rezClass);
            finObj = (T) constructor.newInstance(getParamsObjForConstructor(rezClass));
            copyFields(rezClass, obj, finObj, parrent);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return finObj;
    }


    @SuppressWarnings({"rawtypes", "unchecked"})
    private static ArrayList<?> arrayListHandler(ArrayList<?> obj) {
        ArrayList srcList = obj;
        ArrayList finList = new ArrayList();
        for (int i = 0; i < srcList.size(); i++) {
            finList.add(CopyUtils.deepCopy(srcList.get(i)));
        }
        return finList;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static <K, V> Map<K, V> mapHandler(Map<K, V> obj) {
        Map<K, V> src = obj;
        Map<K, V> fin = new HashMap<>();
        src.entrySet().stream().forEach(e->{
            K key = (K) CopyUtils.deepCopy(e.getKey());
            V value = (V) CopyUtils.deepCopy(e.getValue());
            fin.put(key, value);
        });
        return fin;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static <K, V> Map<K, V> concurrentMapHandler(Map<K, V> obj) {
        Map<K, V> src = obj;
        Map<K, V> fin = new ConcurrentHashMap<>();
        src.entrySet().stream().forEach(e->{
            K key = (K) CopyUtils.deepCopy(e.getKey());
            V value = (V) CopyUtils.deepCopy(e.getValue());
            fin.put(key, value);
        });
        return fin;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static <K, V> Map<K, V> treeMapHandler(Map<K, V> obj) {
        Map<K, V> src = obj;
        Map<K, V> fin = new TreeMap<>();
        src.entrySet().stream().forEach(e->{
            K key = (K) CopyUtils.deepCopy(e.getKey());
            V value = (V) CopyUtils.deepCopy(e.getValue());
            fin.put(key, value);
        });
        return fin;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    private static LinkedList<?> linkedListHandler(LinkedList<?> obj) {
        LinkedList srcList = obj;
        LinkedList finList = new LinkedList<>();
        for (int i = 0; i < srcList.size(); i++) {
            finList.add(CopyUtils.deepCopy(srcList.get(i)));
        }
        return finList;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    private static HashSet<?> hashSetHandler(HashSet<?> obj) {
        HashSet srcList = obj;
        HashSet finList = new HashSet<>();
        srcList.stream().forEach(e-> finList.add(CopyUtils.deepCopy(e)));
        return finList;
    }


    private static boolean isPrimitiveArray(Object obj) {
        if (obj instanceof byte[] ||
                obj instanceof short[] ||
                obj instanceof int[] ||
                obj instanceof long[] ||
                obj instanceof float[] ||
                obj instanceof double[] ||
                obj instanceof char[] ||
                obj instanceof boolean[]) {
            return true;
        } else {
            return false;
        }
    }

    private static boolean isPrimitiveArray(String type) {
        if ("byte[]".equals(type) ||
                "short[]".equals(type) ||
                "int[]".equals(type) ||
                "long[]".equals(type) ||
                "float[]".equals(type) ||
                "double[]".equals(type) ||
                "char[]".equals(type) ||
                "boolean[]".equals(type)) {
            return true;
        } else {
            return false;
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T getPrimitiveArray(T obj) {
        if (obj instanceof int[]) {
            int[] arr = new int[((int[]) obj).length];
            for (int i = 0; i < ((int[]) obj).length; i++) {
                arr[i] = ((int[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof byte[]) {
            byte[] arr = new byte[((byte[]) obj).length];
            for (int i = 0; i < ((byte[]) obj).length; i++) {
                arr[i] = ((byte[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof short[]) {
            short[] arr = new short[((short[]) obj).length];
            for (int i = 0; i < ((short[]) obj).length; i++) {
                arr[i] = ((short[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof long[]) {
            long[] arr = new long[((long[]) obj).length];
            for (int i = 0; i < ((long[]) obj).length; i++) {
                arr[i] = ((long[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof float[]) {
            float[] arr = new float[((float[]) obj).length];
            for (int i = 0; i < ((float[]) obj).length; i++) {
                arr[i] = ((float[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof double[]) {
            double[] arr = new double[((double[]) obj).length];
            for (int i = 0; i < ((double[]) obj).length; i++) {
                arr[i] = ((double[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof char[]) {
            char[] arr = new char[((char[]) obj).length];
            for (int i = 0; i < ((char[]) obj).length; i++) {
                arr[i] = ((char[]) obj)[i];
            }
            return (T) arr;
        } else if (obj instanceof boolean[]) {
            boolean[] arr = new boolean[((boolean[]) obj).length];
            for (int i = 0; i < ((boolean[]) obj).length; i++) {
                arr[i] = ((boolean[]) obj)[i];
            }
            return (T) arr;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private static <T> T getPrimitiveArray(T obj, String type) {
        if ("int[]".equals(type)) {
            int[] arr = new int[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("byte[]".equals(type)) {
            byte[] arr = new byte[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("short[]".equals(type)) {
            short[] arr = new short[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("long[]".equals(type)) {
            long[] arr = new long[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("float[]".equals(type)) {
            float[] arr = new float[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("double[]".equals(type)) {
            double[] arr = new double[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("char[]".equals(type)) {
            char[] arr = new char[1];
            arr[0] = 0;
            return (T) arr;
        } else if ("boolean[]".equals(type)) {
            boolean[] arr = new boolean[1];
            arr[0] = false;
            return (T) arr;
        }
        return null;
    }


    @SuppressWarnings({"unchecked", "rawtypes"})
    private static Constructor getCompleteConstructor(Class ourClass)
            throws NoSuchMethodException, SecurityException {
        Constructor constructor = null;
        Class[] params = new Class[ourClass.getDeclaredConstructors()[0].getParameterTypes().length];
        for (int i = 0; i < ourClass.getDeclaredConstructors()[0].getParameterTypes().length; i++) {
            params[i] = ourClass.getDeclaredConstructors()[0].getParameterTypes()[i];
        }
        constructor = ourClass.getConstructor(params);
        constructor.setAccessible(true);
        return constructor;
    }

    @SuppressWarnings("rawtypes")
    private static Object[] getParamsObjForConstructor(Class ourClass)
            throws SecurityException {
        Constructor constuctor;
        constuctor = ourClass.getDeclaredConstructors()[0];
        constuctor.setAccessible(true);
        Object[] objParams = new Object[constuctor.getParameterTypes().length];
        for (int i = 0; i < constuctor.getParameterTypes().length; i++) {
            String fieldType = constuctor.getParameterTypes()[i].toString();
            if ("int".equalsIgnoreCase(fieldType) ||
                    "double".equalsIgnoreCase(fieldType) ||
                    "float".equalsIgnoreCase(fieldType) ||
                    "byte".equalsIgnoreCase(fieldType) ||
                    "char".equalsIgnoreCase(fieldType) ||
                    "long".equalsIgnoreCase(fieldType)) {
                objParams[i] = 0;
            } else if ("boolean".equalsIgnoreCase(fieldType)) {
                objParams[i] = false;
            } else if (isPrimitiveArray(constuctor.getParameterTypes()[i].getCanonicalName())) {
                objParams[i] = getPrimitiveArray(constuctor.getParameterTypes()[i],
                        constuctor.getParameterTypes()[i].getCanonicalName()
                );
            } else {
                objParams[i] = null;
            }
        }
        return objParams;
    }

    @SuppressWarnings("rawtypes")
    private static <T> void copyFields(Class ourClass, T srcObj, T finObj)
            throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
        Field[] fields = ourClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            Field modField = Field.class.getDeclaredField("modifiers");
            modField.setAccessible(true);
            modField.setInt(fields[i], fields[i].getModifiers() & ~Modifier.FINAL);
            String fieldType = fields[i].getType().toString();
            if ("int".equalsIgnoreCase(fieldType) ||
                    "double".equalsIgnoreCase(fieldType) ||
                    "float".equalsIgnoreCase(fieldType) ||
                    "byte".equalsIgnoreCase(fieldType) ||
                    "char".equalsIgnoreCase(fieldType) ||
                    "boolean".equalsIgnoreCase(fieldType) ||
                    "short".equalsIgnoreCase(fieldType) ||
                    "long".equalsIgnoreCase(fieldType)) {
                fields[i].set(finObj, fields[i].get(srcObj));
            } else {
                fields[i].set(finObj, CopyUtils.deepCopy(fields[i].get(srcObj), finObj));
            }
        }
    }

    @SuppressWarnings("rawtypes")
    private static <T> void copyFields(Class ourClass, T srcObj, T finObj, Object parent)
            throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
        Field[] fields = ourClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            Field modField = Field.class.getDeclaredField("modifiers");
            modField.setAccessible(true);
            modField.setInt(fields[i], fields[i].getModifiers() & ~Modifier.FINAL);
            String fieldType = fields[i].getType().toString();
            if ("int".equalsIgnoreCase(fieldType) ||
                    "double".equalsIgnoreCase(fieldType) ||
                    "float".equalsIgnoreCase(fieldType) ||
                    "byte".equalsIgnoreCase(fieldType) ||
                    "char".equalsIgnoreCase(fieldType) ||
                    "boolean".equalsIgnoreCase(fieldType) ||
                    "short".equalsIgnoreCase(fieldType) ||
                    "long".equalsIgnoreCase(fieldType)) {
                fields[i].set(finObj, fields[i].get(srcObj));
            } else {
                if (fields[i].get(srcObj).toString().equals(parent.toString())) {
                    fields[i].set(finObj, fields[i].get(srcObj));
                } else {
                    fields[i].set(finObj, CopyUtils.deepCopy(fields[i].get(srcObj), finObj));
                }
            }
        }
    }

    static void setFinalStaticField(Field field, Object newValue) throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }

    public static Object copyProperties(Object target, Object orig) {
        if (target == null || orig == null) {
            return target;
        }

        PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(target);
        try {
            for (int i = 0; i < destDesc.length; i++) {
                Class destType = destDesc[i].getPropertyType();
                Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());
                if (destType != null && destType.equals(origType) && !destType.equals(Class.class)) {
                    if (!Collection.class.isAssignableFrom(origType)) {
                        try {
                            Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());
                            PropertyUtils.setProperty(target, destDesc[i].getName(), value);
                        } catch (Exception ex) {
                        }
                    }
                }
            }

            return target;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static Object copyProperties(Object dest, Object orig, String[] ignores) {
        if (dest == null || orig == null) {
            return dest;
        }

        PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);
        try {
            for (int i = 0; i < destDesc.length; i++) {
                if (contains(ignores, destDesc[i].getName())) {
                    continue;
                }
                Class destType = destDesc[i].getPropertyType();
                Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());
                if (destType != null && destType.equals(origType) && !destType.equals(Class.class)) {
                    if (!Collection.class.isAssignableFrom(origType)) {
                        Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());
                        PropertyUtils.setProperty(dest, destDesc[i].getName(), value);
                    }
                }
            }

            return dest;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    static boolean contains(String[] ignores, String name) {
        boolean ignored = false;
        for (int j = 0; ignores != null && j < ignores.length; j++) {
            if (ignores[j].equals(name)) {
                ignored = true;
                break;
            }
        }
        return ignored;
    }
}

你可能感兴趣的:(JAVA开发,SpringCache,JetCache,CaffeineCache,线程池工具类,同类型深度克隆与对象复制新类)