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> 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); +}