动态注入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<?>, IBaseRepository<?, ?>> repositoryCache = new ConcurrentHashMap<>();
private final Map<Class<?>, BaseConverter<?, ?>> converterCache = new ConcurrentHashMap<>();
private final Map<Class<?>, EntityPath<?>> entityPathCache = new ConcurrentHashMap<>();
public DependencyInjectionPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@ -96,7 +102,6 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable>
IBaseService<?, ?, ?> findServiceForEntity(Class<T> entityClass, String controllerName) {
// 先尝试通过命名约定查找
String serviceBeanName = "i" + entityClass.getSimpleName() + "Service";
log.debug("Looking for service bean: {}", serviceBeanName);
@ -104,13 +109,13 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
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))
.map(name -> tryGetService(name, entityClass, controllerName))
.filter(Objects::nonNull)
.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")
@ -177,6 +182,9 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
@Override
public void destroy() {
serviceCache.clear();
repositoryCache.clear();
converterCache.clear();
entityPathCache.clear();
}
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>
void injectRepository(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository";
log.debug("Looking for repository bean: {}", repositoryBeanName);
if (!applicationContext.containsBean(repositoryBeanName)) {
throw new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_ERROR,
new Object[] {entityClass.getSimpleName(), repositoryBeanName});
}
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) applicationContext.getBean(repositoryBeanName);
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) repositoryCache.computeIfAbsent(
entityClass,
key -> {
if (!applicationContext.containsBean(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);
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
void injectConverter(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase()
+ entityClass.getSimpleName().substring(1) + "ConverterImpl";
log.debug("Looking for converter bean: {}", converterBeanName);
if (!applicationContext.containsBean(converterBeanName)) {
throw new BusinessException(
ResponseCode.DEPENDENCY_INJECTION_ERROR,
new Object[] {entityClass.getSimpleName(), converterBeanName});
}
BaseConverter<T, D> converter = (BaseConverter<T, D>) applicationContext.getBean(converterBeanName);
BaseConverter<T, D> converter = (BaseConverter<T, D>) converterCache.computeIfAbsent(
entityClass,
key -> {
if (!applicationContext.containsBean(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);
}
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")
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 {
String qClassName = entityClass.getPackageName() + ".Q" + entityClass.getSimpleName();
Class<?> qClass = Class.forName(qClassName);
Field instanceField = qClass.getDeclaredField(entityClass.getSimpleName().toLowerCase());
return (EntityPath<T>) instanceField.get(null);
EntityPath<T> entityPath = (EntityPath<T>) entityPathCache.computeIfAbsent(
entityClass,
key -> {
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) {
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"),
// 依赖注入相关错误 (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;

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.id=Entity with id {0} not found
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.id=找不到ID为{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}