动态注入Controller、Service所需的类
This commit is contained in:
parent
3e577cac5c
commit
7b3ffc69c0
@ -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()});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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}
|
||||
@ -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}
|
||||
Loading…
Reference in New Issue
Block a user