动态注入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<?>, 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);
|
||||||
|
|
||||||
|
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) repositoryCache.computeIfAbsent(
|
||||||
|
entityClass,
|
||||||
|
key -> {
|
||||||
if (!applicationContext.containsBean(repositoryBeanName)) {
|
if (!applicationContext.containsBean(repositoryBeanName)) {
|
||||||
throw new BusinessException(
|
throw new BusinessException(
|
||||||
ResponseCode.DEPENDENCY_INJECTION_ERROR,
|
ResponseCode.DEPENDENCY_INJECTION_REPOSITORY_NOT_FOUND,
|
||||||
new Object[] {entityClass.getSimpleName(), repositoryBeanName});
|
new Object[] {key.getSimpleName(), repositoryBeanName});
|
||||||
}
|
}
|
||||||
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) applicationContext.getBean(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);
|
||||||
|
|
||||||
|
BaseConverter<T, D> converter = (BaseConverter<T, D>) converterCache.computeIfAbsent(
|
||||||
|
entityClass,
|
||||||
|
key -> {
|
||||||
if (!applicationContext.containsBean(converterBeanName)) {
|
if (!applicationContext.containsBean(converterBeanName)) {
|
||||||
throw new BusinessException(
|
throw new BusinessException(
|
||||||
ResponseCode.DEPENDENCY_INJECTION_ERROR,
|
ResponseCode.DEPENDENCY_INJECTION_CONVERTER_NOT_FOUND,
|
||||||
new Object[] {entityClass.getSimpleName(), converterBeanName});
|
new Object[] {key.getSimpleName(), converterBeanName});
|
||||||
}
|
}
|
||||||
BaseConverter<T, D> converter = (BaseConverter<T, D>) applicationContext.getBean(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>
|
@SuppressWarnings("unchecked")
|
||||||
void injectEntityPath(BaseServiceImpl<T, D, ID> service, 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 {
|
||||||
EntityPath<T> entityPath = initEntityPath(entityClass);
|
EntityPath<T> entityPath = (EntityPath<T>) entityPathCache.computeIfAbsent(
|
||||||
ReflectionUtils.setField("entityPath", service, entityPath);
|
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) {
|
} catch (Exception e) {
|
||||||
throw new BusinessException(
|
throw new BusinessException(
|
||||||
ResponseCode.DEPENDENCY_INJECTION_ERROR,
|
ResponseCode.DEPENDENCY_INJECTION_ENTITYPATH_FAILED,
|
||||||
new Object[] {entityClass.getSimpleName(), e.getMessage()});
|
new Object[] {key.getSimpleName(), e.getMessage()});
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
ReflectionUtils.setField("entityPath", service, entityPath);
|
||||||
@SuppressWarnings("unchecked")
|
} catch (BusinessException e) {
|
||||||
private <T extends Entity<ID>, ID extends Serializable> EntityPath<T> initEntityPath(Class<T> entityClass) {
|
throw e;
|
||||||
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);
|
|
||||||
} 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()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -27,3 +27,9 @@ system.retry.exceeded.error=Operation retry limit exceeded, please try again lat
|
|||||||
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}
|
||||||
@ -27,3 +27,9 @@ system.retry.exceeded.error=操作重试次数超限,请稍后再试
|
|||||||
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}
|
||||||
Loading…
Reference in New Issue
Block a user