diff --git a/pom.xml b/pom.xml
index a178321..d5ff0bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,11 @@
org.springframework.boot
spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
diff --git a/src/main/java/org/anyin/gitee/shiro/config/AppConfig.java b/src/main/java/org/anyin/gitee/shiro/config/AppConfig.java
index 41731b9..1da9c2f 100644
--- a/src/main/java/org/anyin/gitee/shiro/config/AppConfig.java
+++ b/src/main/java/org/anyin/gitee/shiro/config/AppConfig.java
@@ -2,6 +2,8 @@ package org.anyin.gitee.shiro.config;
import org.anyin.gitee.shiro.advisor.ApiMessageAdvisor;
import org.anyin.gitee.shiro.base.MdcExecutor;
+import org.anyin.gitee.shiro.extension.DefaultExtensionHandlerFactoryImpl;
+import org.anyin.gitee.shiro.extension.IExtensionHandlerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -17,6 +19,11 @@ public class AppConfig {
return new ApiMessageAdvisor();
}
+ @Bean
+ public IExtensionHandlerFactory extensionHandlerFactory(){
+ return new DefaultExtensionHandlerFactoryImpl();
+ }
+
@Bean
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
diff --git a/src/main/java/org/anyin/gitee/shiro/extension/DefaultExtensionHandlerFactoryImpl.java b/src/main/java/org/anyin/gitee/shiro/extension/DefaultExtensionHandlerFactoryImpl.java
new file mode 100644
index 0000000..e22e585
--- /dev/null
+++ b/src/main/java/org/anyin/gitee/shiro/extension/DefaultExtensionHandlerFactoryImpl.java
@@ -0,0 +1,63 @@
+package org.anyin.gitee.shiro.extension;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.util.Assert;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+public class DefaultExtensionHandlerFactoryImpl implements IExtensionHandlerFactory, ApplicationContextAware {
+
+ private final Map> serviceListCache = new ConcurrentHashMap<>();
+ private final Map serviceCache = new ConcurrentHashMap<>();
+
+ @Override
+ public > void addExtensionHandler(IExtensionHandler extensionHandler) {
+ Assert.notNull(extensionHandler.extension(), "add extension handler failed, bean class " + extensionHandler.getClass().getName() + " extension is null");
+ serviceListCache.putIfAbsent(extensionHandler.extension(), new LinkedList<>());
+ serviceListCache.get(extensionHandler.extension()).add(extensionHandler);
+ }
+
+ @Override
+ public , Y extends Enum> T getExtensionHandler(Y extension, Class type) {
+ ExtensionCacheKey cacheKey = new ExtensionCacheKey(extension, type);
+ IExtensionHandler result = this.serviceCache.get(cacheKey);
+ if (result == null) {
+ List payPlatformAbles = serviceListCache.getOrDefault(extension, Collections.synchronizedList(Collections.emptyList()));
+ for (IExtensionHandler payPlatformAble : payPlatformAbles) {
+ if (type.isAssignableFrom(payPlatformAble.getClass())) {
+ result = payPlatformAble;
+ serviceCache.put(cacheKey, result);
+ break;
+ }
+ }
+ if (result == null) {
+ log.warn("No IExtensionHandler found by CacheKey : " + cacheKey + " !");
+ }
+ }
+ return (T) result;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ Map handlerMap = applicationContext.getBeansOfType(IExtensionHandler.class);
+ log.info("疯狂加载扩展ing ...");
+ long start = System.currentTimeMillis();
+ handlerMap.forEach((k, v) -> {
+ //排除组合类自己
+ if (!this.getClass().isAssignableFrom(v.getClass())) {
+ addExtensionHandler(v);
+ }
+ });
+ long end = System.currentTimeMillis();
+ log.info("加载扩展点结束,耗时: {}, 扩展点个数: {}", end - start, handlerMap.size());
+ }
+}
diff --git a/src/main/java/org/anyin/gitee/shiro/extension/ExtensionCacheKey.java b/src/main/java/org/anyin/gitee/shiro/extension/ExtensionCacheKey.java
new file mode 100644
index 0000000..cdded8f
--- /dev/null
+++ b/src/main/java/org/anyin/gitee/shiro/extension/ExtensionCacheKey.java
@@ -0,0 +1,16 @@
+package org.anyin.gitee.shiro.extension;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Data
+@AllArgsConstructor
+@ToString
+@EqualsAndHashCode
+public class ExtensionCacheKey {
+
+ private T extension;
+ private Class extends IExtensionHandler> extensionHandlerClass;
+}
diff --git a/src/main/java/org/anyin/gitee/shiro/extension/IExtensionHandler.java b/src/main/java/org/anyin/gitee/shiro/extension/IExtensionHandler.java
new file mode 100644
index 0000000..afa2cfd
--- /dev/null
+++ b/src/main/java/org/anyin/gitee/shiro/extension/IExtensionHandler.java
@@ -0,0 +1,6 @@
+package org.anyin.gitee.shiro.extension;
+
+public interface IExtensionHandler{
+
+ Y extension();
+}
diff --git a/src/main/java/org/anyin/gitee/shiro/extension/IExtensionHandlerFactory.java b/src/main/java/org/anyin/gitee/shiro/extension/IExtensionHandlerFactory.java
new file mode 100644
index 0000000..0caf9aa
--- /dev/null
+++ b/src/main/java/org/anyin/gitee/shiro/extension/IExtensionHandlerFactory.java
@@ -0,0 +1,8 @@
+package org.anyin.gitee.shiro.extension;
+
+public interface IExtensionHandlerFactory {
+
+ >void addExtensionHandler(IExtensionHandler extensionHandler);
+
+ ,Y extends Enum> T getExtensionHandler(Y extension, Class type);
+}