Changes brought by Function to code encapsulation

The java 8 Function feature has also appeared for a long time, and it is used more and more in the project. Let me record my personal insights.

 

1 The programming idea of ​​functional parameters, a comprehensive replacement for the callback function

    This is easy to understand. Callback itself is a concept close to functional parameters. In code encapsulation, the same part of the same method is often extracted, and different parts are defined as callback. The caller provides a specific implementation. The used class HibernateDaoSupport is A good embodiment, using Function, Consumer can be a perfect replacement, the following is a package for idempotent operations (distributed locks provide lock support)

 

 

    /**
     * Distributed lock support, throw IdempotentException if the lock is not obtained
     * @param lockSuffix lock prefix
     * @param paramSupplier provided parameter bean
     * @param actionFunction the function to handle the parameter
     * @param <T> parameter generic
     * @param <R> return value generic
     * @return
     * @throws IdempotentException
     */
    public <T,R> R idempotentAction(String lockSuffix, Supplier<T> paramSupplier, Function<T, R> actionFunction)
        throws IdempotentException {
        // lock operation
        ZkMutex zkMutex = zkMutexClient.getDistributedLock(lockSuffix);
        logger.info("Start trying to acquire lock!");
        boolean getLock = zkMutex != null ? zkMutex.acquire(5, TimeUnit.SECONDS, 3) : false;
        logger.info("End of lock acquisition! Acquisition result:{}", getLock);
        try {
            if (!getLock) {//The lock is not acquired
                logger.info("Failed to acquire lock! Try again later!");
                throw new IdempotentException("Failed to acquire lock, try again later");
            }
            // logic block
            return actionFunction.apply(paramSupplier.get());
        } finally {
            if (getLock && zkMutex != null) {
                zkMutex.release();
                logger.info("zk distributed release lock");
            }
        }
    }

   ps:  ZkMutex is the InterProcessMutex class inherited from the curator framework , which provides exception shielding

/**
 * zk lock, providing a layer of encapsulation to ensure that zk lock does not affect normal program execution in any abnormal situation
 * Created by mxl on 2017/5/22.
 */
public class ZkMutex extends InterProcessMutex {

    private Logger logger = LoggerFactory.getLogger(ZkMutex.class);

    private CuratorFramework client;

    private String path;

    public ZkMutex(CuratorFramework client, String path) {
        super(client, path);
        this.client = client;
        this.path = path;
    }

    @Override
    public void acquire() throws Exception {
        try {
            super.acquire();
        } catch (Exception e) {
            logger.error("Failed to acquire lock!", e);
        }
    }

    @Override
    public boolean acquire(long time, TimeUnit unit) {
        try {
            return super.acquire(time, unit);
        } catch (Exception e) {
            logger.error("Get zk lock exception!", e);
        }
        return false;
    }

    /**
     * Get lock, support retry
     * @param time
     * @param unit
     * @param tries
     * @return
     */
    public boolean acquire(long time, TimeUnit unit, int tries) {
        for (int i = 0; i < tries; i++) {
            try {
                if (super.acquire(time, unit)) {
                    return true;
                }
            } catch (Exception e) {
                logger.error("Failed to acquire lock, retries: " + tries);
            }
        }
        return false;
    }

    @Override
    public void release() {
        try {
            super.release();
            deleteNode();
        } catch (Exception e) {
            logger.error("release zk lock exception!", e);
        }
    }

    /**
     * Remove the node for the lock
     */
    public void deleteNode() {
        try {
            List<String> children = this.client.getChildren().forPath(path);
            if (children == null || children.size() == 0) {
                this.client.delete().forPath(path);
            }
        } catch (Exception e) {
            logger.error("Failed to delete node!", e);
        }
    }
}

 

2 Generics encapsulates the instantiation of generic objects

 

    /**
     * parameter conversion
     * @param inputParam
     * @param outputParam
     * @param <T>
     * @param <R>
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private <T, R> R convertParam (Supplier<T> inputParam, Supplier<R> outputParam) throws IllegalAccessException,
            InvocationTargetException{
        T t = inputParam.get();
        R r = outputParam.get();
        if (t != null && r != null) {
            BeanUtils.copyProperties (r, t);
        }
        return r;
    }

 

 3 The most commonly used is the support of converting sets into streams for various lambda expressions, which is powerful and saves code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326446737&siteId=291194637