001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.db.transactional;
017
018import com.jfinal.aop.Invocation;
019import io.jboot.utils.ClassUtil;
020import io.jboot.utils.NamedThreadFactory;
021import io.jboot.utils.StrUtil;
022
023import java.util.Map;
024import java.util.concurrent.*;
025
026public class TransactionalManager {
027
028    private static TransactionalManager instance = new TransactionalManager();
029
030    public static TransactionalManager me() {
031        return instance;
032    }
033
034
035    private Map<String, ExecutorService> executorServiceMap = new ConcurrentHashMap<>();
036    private ThreadFactory threadFactory = new NamedThreadFactory("Transactional", true);
037
038    //当未配置线程池名称的时候,是否使用 threadFactory 来执行
039    private boolean runDefaultWithoutConfigName = false;
040
041
042    public void addExecutorService(String name, ExecutorService service) {
043        executorServiceMap.put(name, service);
044    }
045
046    public ExecutorService getExecutorService(String name) {
047        return executorServiceMap.get(name);
048    }
049
050    public void removeExecutorService(String name) {
051        executorServiceMap.remove(name);
052    }
053
054    public Map<String, ExecutorService> getExecutorServiceMap() {
055        return executorServiceMap;
056    }
057
058    public ThreadFactory getThreadFactory() {
059        return threadFactory;
060    }
061
062    public void setThreadFactory(ThreadFactory threadFactory) {
063        this.threadFactory = threadFactory;
064    }
065
066    public boolean isRunDefaultWithoutConfigName() {
067        return runDefaultWithoutConfigName;
068    }
069
070    public void setRunDefaultWithoutConfigName(boolean runDefaultWithoutConfigName) {
071        this.runDefaultWithoutConfigName = runDefaultWithoutConfigName;
072    }
073
074    public Future<Boolean> execute(String byName, Callable<Boolean> callable, Invocation inv) {
075        if (StrUtil.isBlank(byName)) {
076            FutureTask<Boolean> task = new FutureTask<>(callable);
077            threadFactory.newThread(task).start();
078            return task;
079        }
080
081
082        ExecutorService executorService = executorServiceMap.get(byName);
083        if (executorService != null) {
084            return executorService.submit(callable);
085        }
086
087        if (!runDefaultWithoutConfigName) {
088            throw new IllegalStateException("Can not find threadPoolName: \"" + byName + "\" for @Transactional() in method: "
089                    + ClassUtil.buildMethodString(inv.getMethod())
090                    + ".\n Please invoke TransactionalManager.me().addExecutorService() to configure transactional threadPool on application started.");
091        }
092
093
094        FutureTask<Boolean> task = new FutureTask<>(callable);
095        threadFactory.newThread(task).start();
096        return task;
097    }
098
099
100}