动态注入Controller、Service所需的类

This commit is contained in:
dengqichen 2024-11-29 18:01:24 +08:00
parent 3e577cac5c
commit 7b3ffc69c0
4 changed files with 75 additions and 37 deletions

View File

@ -35,6 +35,12 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
private final Map<Class<?>, IBaseService<?, ?, ?>> serviceCache = new ConcurrentHashMap<>(); private final Map<Class<?>, IBaseService<?, ?, ?>> serviceCache = new ConcurrentHashMap<>();
private final Map<Class<?>, IBaseRepository<?, ?>> repositoryCache = new ConcurrentHashMap<>();
private final Map<Class<?>, BaseConverter<?, ?>> converterCache = new ConcurrentHashMap<>();
private final Map<Class<?>, EntityPath<?>> entityPathCache = new ConcurrentHashMap<>();
public DependencyInjectionPostProcessor(ApplicationContext applicationContext) { public DependencyInjectionPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
} }
@ -96,7 +102,6 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable> private <T extends Entity<ID>, ID extends Serializable>
IBaseService<?, ?, ?> findServiceForEntity(Class<T> entityClass, String controllerName) { IBaseService<?, ?, ?> findServiceForEntity(Class<T> entityClass, String controllerName) {
// 先尝试通过命名约定查找
String serviceBeanName = "i" + entityClass.getSimpleName() + "Service"; String serviceBeanName = "i" + entityClass.getSimpleName() + "Service";
log.debug("Looking for service bean: {}", serviceBeanName); log.debug("Looking for service bean: {}", serviceBeanName);
@ -104,13 +109,13 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
return (IBaseService<?, ?, ?>) applicationContext.getBean(serviceBeanName); return (IBaseService<?, ?, ?>) applicationContext.getBean(serviceBeanName);
} }
// 如果找不到再通过类型匹配查找
log.debug("Service not found by name, trying to find by type matching");
return Arrays.stream(applicationContext.getBeanNamesForType(IBaseService.class)) return Arrays.stream(applicationContext.getBeanNamesForType(IBaseService.class))
.map(name -> tryGetService(name, entityClass, controllerName)) .map(name -> tryGetService(name, entityClass, controllerName))
.filter(Objects::nonNull) .filter(Objects::nonNull)
.findFirst() .findFirst()
.orElseThrow(() -> new BusinessException(ResponseCode.DEPENDENCY_INJECTION_ERROR, new Object[] {entityClass.getSimpleName(), serviceBeanName})); .orElseThrow(() -> new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_SERVICE_NOT_FOUND,
new Object[] {entityClass.getSimpleName(), serviceBeanName}));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -177,6 +182,9 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
@Override @Override
public void destroy() { public void destroy() {
serviceCache.clear(); serviceCache.clear();
repositoryCache.clear();
converterCache.clear();
entityPathCache.clear();
} }
public static class DependencyInjectionException extends BeanCreationException { public static class DependencyInjectionException extends BeanCreationException {
@ -190,54 +198,69 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
} }
// 辅助方法用于注入具体的依赖 // 辅助方法用于注入具体的依赖
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable> private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
void injectRepository(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) { void injectRepository(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository"; String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository";
log.debug("Looking for repository bean: {}", repositoryBeanName); log.debug("Looking for repository bean: {}", repositoryBeanName);
if (!applicationContext.containsBean(repositoryBeanName)) {
throw new BusinessException( IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) repositoryCache.computeIfAbsent(
ResponseCode.DEPENDENCY_INJECTION_ERROR, entityClass,
new Object[] {entityClass.getSimpleName(), repositoryBeanName}); key -> {
} if (!applicationContext.containsBean(repositoryBeanName)) {
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) applicationContext.getBean(repositoryBeanName); throw new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_REPOSITORY_NOT_FOUND,
new Object[] {key.getSimpleName(), repositoryBeanName});
}
return (IBaseRepository<?, ?>) applicationContext.getBean(repositoryBeanName);
});
ReflectionUtils.setField("repository", service, repository); ReflectionUtils.setField("repository", service, repository);
} }
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable> private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
void injectConverter(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) { void injectConverter(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase() String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase()
+ entityClass.getSimpleName().substring(1) + "ConverterImpl"; + entityClass.getSimpleName().substring(1) + "ConverterImpl";
log.debug("Looking for converter bean: {}", converterBeanName); log.debug("Looking for converter bean: {}", converterBeanName);
if (!applicationContext.containsBean(converterBeanName)) {
throw new BusinessException( BaseConverter<T, D> converter = (BaseConverter<T, D>) converterCache.computeIfAbsent(
ResponseCode.DEPENDENCY_INJECTION_ERROR, entityClass,
new Object[] {entityClass.getSimpleName(), converterBeanName}); key -> {
} if (!applicationContext.containsBean(converterBeanName)) {
BaseConverter<T, D> converter = (BaseConverter<T, D>) applicationContext.getBean(converterBeanName); throw new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_CONVERTER_NOT_FOUND,
new Object[] {key.getSimpleName(), converterBeanName});
}
return (BaseConverter<?, ?>) applicationContext.getBean(converterBeanName);
});
ReflectionUtils.setField("converter", service, converter); ReflectionUtils.setField("converter", service, converter);
} }
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
void injectEntityPath(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
try {
EntityPath<T> entityPath = initEntityPath(entityClass);
ReflectionUtils.setField("entityPath", service, entityPath);
} catch (Exception e) {
throw new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_ERROR,
new Object[] {entityClass.getSimpleName(), e.getMessage()});
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable> EntityPath<T> initEntityPath(Class<T> entityClass) { private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable> void injectEntityPath(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
try { try {
String qClassName = entityClass.getPackageName() + ".Q" + entityClass.getSimpleName(); EntityPath<T> entityPath = (EntityPath<T>) entityPathCache.computeIfAbsent(
Class<?> qClass = Class.forName(qClassName); entityClass,
Field instanceField = qClass.getDeclaredField(entityClass.getSimpleName().toLowerCase()); key -> {
return (EntityPath<T>) instanceField.get(null); try {
String qClassName = key.getPackageName() + ".Q" + key.getSimpleName();
Class<?> qClass = Class.forName(qClassName);
Field instanceField = qClass.getDeclaredField(key.getSimpleName().toLowerCase());
return (EntityPath<?>) instanceField.get(null);
} catch (Exception e) {
throw new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_ENTITYPATH_FAILED,
new Object[] {key.getSimpleName(), e.getMessage()});
}
});
ReflectionUtils.setField("entityPath", service, entityPath);
} catch (BusinessException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new IllegalStateException("Failed to get Q class for " + entityClass.getName(), e); throw new BusinessException(ResponseCode.DEPENDENCY_INJECTION_ENTITYPATH_FAILED, new Object[] {entityClass.getSimpleName(), e.getMessage()});
} }
} }
} }

View File

@ -29,7 +29,10 @@ public enum ResponseCode {
EMAIL_EXISTS(2003, "user.email.exists"), EMAIL_EXISTS(2003, "user.email.exists"),
// 依赖注入相关错误 (1100-1199) // 依赖注入相关错误 (1100-1199)
DEPENDENCY_INJECTION_ERROR(1100, "dependency.injection.service.not.found"); DEPENDENCY_INJECTION_SERVICE_NOT_FOUND(1100, "dependency.injection.service.not.found"),
DEPENDENCY_INJECTION_REPOSITORY_NOT_FOUND(1101, "dependency.injection.repository.not.found"),
DEPENDENCY_INJECTION_CONVERTER_NOT_FOUND(1102, "dependency.injection.converter.not.found"),
DEPENDENCY_INJECTION_ENTITYPATH_FAILED(1103, "dependency.injection.entitypath.failed");
private final int code; private final int code;

View File

@ -26,4 +26,10 @@ system.retry.exceeded.error=Operation retry limit exceeded, please try again lat
# Entity Not Found Messages # Entity Not Found Messages
entity.not.found.id=Entity with id {0} not found entity.not.found.id=Entity with id {0} not found
entity.not.found.message={0} entity.not.found.message={0}
entity.not.found.name.id={0} with id {1} not found entity.not.found.name.id={0} with id {1} not found
# Dependency Injection
dependency.injection.service.not.found=No service found for entity {0} (tried bean name: {1})
dependency.injection.repository.not.found=No repository found for entity {0}: {1}
dependency.injection.converter.not.found=No converter found for entity {0}: {1}
dependency.injection.entitypath.failed=Failed to initialize EntityPath for entity {0}: {1}

View File

@ -26,4 +26,10 @@ system.retry.exceeded.error=操作重试次数超限,请稍后再试
# Entity Not Found Messages # Entity Not Found Messages
entity.not.found.id=找不到ID为{0}的实体 entity.not.found.id=找不到ID为{0}的实体
entity.not.found.message={0} entity.not.found.message={0}
entity.not.found.name.id=找不到ID为{1}的{0} entity.not.found.name.id=找不到ID为{1}的{0}
# 依赖注入相关
dependency.injection.service.not.found=找不到实体 {0} 对应的服务 (尝试过的bean名称: {1})
dependency.injection.repository.not.found=找不到实体 {0} 对应的Repository: {1}
dependency.injection.converter.not.found=找不到实体 {0} 对应的Converter: {1}
dependency.injection.entitypath.failed=初始化实体 {0} 的EntityPath失败: {1}