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.core.listener; 017 018import com.jfinal.config.Constants; 019import com.jfinal.config.Interceptors; 020import com.jfinal.config.Routes; 021import com.jfinal.kit.LogKit; 022import com.jfinal.template.Engine; 023import io.jboot.aop.jfinal.JfinalHandlers; 024import io.jboot.aop.jfinal.JfinalPlugins; 025import io.jboot.app.JbootApplicationConfig; 026import io.jboot.core.weight.WeightUtil; 027import io.jboot.utils.ClassScanner; 028import io.jboot.utils.ClassUtil; 029import io.jboot.utils.StrUtil; 030 031import java.util.ArrayList; 032import java.util.HashSet; 033import java.util.List; 034import java.util.Set; 035import java.util.function.Predicate; 036 037public class JbootAppListenerManager implements JbootAppListener { 038 039 private static JbootAppListenerManager me = new JbootAppListenerManager(); 040 041 public static JbootAppListenerManager me() { 042 return me; 043 } 044 045 private List<JbootAppListener> listeners = new ArrayList<>(); 046 047 private JbootAppListenerManager() { 048 049 String listener = JbootApplicationConfig.get().getListener(); 050 051 String listenerPackage = JbootApplicationConfig.get().getListenerPackage(); 052 Set<String> packages = StrUtil.isNotBlank(listenerPackage) && !"*".equals(listenerPackage.trim()) 053 ? StrUtil.splitToSet(listenerPackage, ";") : new HashSet<>(); 054 055 if (StrUtil.isBlank(listener) || "*".equals(listener.trim())) { 056 List<Class<JbootAppListener>> allListeners = ClassScanner.scanSubClass(JbootAppListener.class, true); 057 allListeners.removeIf((Predicate<Class<? extends JbootAppListener>>) c -> 058 c == JbootAppListenerManager.class || c == JbootAppListenerBase.class); 059 060 allListeners.forEach(clazz -> { 061 if (isMatchedPackage(packages, clazz.getCanonicalName())) { 062 JbootAppListener appListener = ClassUtil.newInstance(clazz); 063 if (appListener != null) { 064 listeners.add(appListener); 065 } 066 } 067 }); 068 } else { 069 StrUtil.splitToSet(listener, ";").forEach(className -> { 070 if (isMatchedPackage(packages, className)) { 071 JbootAppListener appListener = ClassUtil.newInstance(className); 072 if (appListener != null) { 073 listeners.add(appListener); 074 } else { 075 // log 组件还未配置,无法使用 log 组件输出 076 System.err.println("Can not create JbootAppListener by class: " + className); 077 } 078 } 079 }); 080 } 081 082 WeightUtil.sort(listeners); 083 } 084 085 private boolean isMatchedPackage(Set<String> packages, String className) { 086 //matched all 087 if (packages == null || packages.isEmpty()) { 088 return true; 089 } 090 091 for (String packageString : packages) { 092 if (className.startsWith(packageString)) { 093 return true; 094 } 095 } 096 return false; 097 } 098 099 public List<JbootAppListener> getListeners() { 100 return listeners; 101 } 102 103 @Override 104 public void onInit() { 105 eachListeners(new TriggerThrowable() { 106 @Override 107 public void trigger(JbootAppListener listener) { 108 listener.onInit(); 109 } 110 111 @Override 112 public void throwable(Throwable ex) { 113 //在 onConstantConfigBefore 的时候, log 组件未初始化,无法使用 114 ex.printStackTrace(); 115 } 116 }); 117 } 118 119 @Override 120 public void onConstantConfigBefore(Constants constants) { 121 eachListeners(new TriggerThrowable() { 122 @Override 123 public void trigger(JbootAppListener listener) { 124 listener.onConstantConfigBefore(constants); 125 } 126 127 @Override 128 public void throwable(Throwable ex) { 129 //在 onConstantConfigBefore 的时候, log 组件未初始化,无法使用 130 ex.printStackTrace(); 131 } 132 }); 133 } 134 135 @Override 136 public void onConstantConfig(Constants constants) { 137 eachListeners(listener -> listener.onConstantConfig(constants)); 138 } 139 140 @Override 141 public void onRouteConfig(Routes routes) { 142 eachListeners(listener -> listener.onRouteConfig(routes)); 143 } 144 145 @Override 146 public void onEngineConfig(Engine engine) { 147 eachListeners(listener -> listener.onEngineConfig(engine)); 148 } 149 150 @Override 151 public void onPluginConfig(JfinalPlugins plugins) { 152 eachListeners(listener -> listener.onPluginConfig(plugins)); 153 } 154 155 @Override 156 public void onInterceptorConfig(Interceptors interceptors) { 157 eachListeners(listener -> listener.onInterceptorConfig(interceptors)); 158 } 159 160 161 @Override 162 public void onHandlerConfig(JfinalHandlers handlers) { 163 eachListeners(listener -> listener.onHandlerConfig(handlers)); 164 } 165 166 @Override 167 public void onStartBefore() { 168 eachListeners(JbootAppListener::onStartBefore); 169 } 170 171 @Override 172 public void onStart() { 173 eachListeners(JbootAppListener::onStart); 174 } 175 176 @Override 177 public void onStartFinish() { 178 eachListeners(JbootAppListener::onStartFinish); 179 } 180 181 @Override 182 public void onStop() { 183 eachListeners(JbootAppListener::onStop); 184 } 185 186 private void eachListeners(TriggerThrowable triggerThrowable) { 187 for (JbootAppListener listener : listeners) { 188 try { 189 triggerThrowable.trigger(listener); 190 } catch (Throwable ex) { 191 triggerThrowable.throwable(ex); 192 } 193 } 194 } 195 196 @FunctionalInterface 197 private interface TriggerThrowable { 198 void trigger(JbootAppListener listener); 199 200 default void throwable(Throwable ex) { 201 LogKit.error(ex.toString(), ex); 202 } 203 } 204}