Ввести InjectionPoint в Generi c Class, чтобы получить фактический тип класса? - PullRequest
0 голосов
/ 13 июля 2020

в моем проекте JSF 2.3 (сервер приложений wildfly 19) у меня есть общий c класс EntityService, который принимает два параметра типа. Класс EntityService также внедряет другой класс GenericEntityService. GenericEntityService - это @Stateless bean-компонент, который использует EntityManager для выполнения реальной работы (поиск объекта, обновление объекта, удаление объекта, вставка объекта ...)

@Dependent
public class EntityService<T, ID> {

    @Inject
    private GenericEntityService<T, ID> entityService;
    private Class<T> entityClass;
    
    @Inject
    private void entityClass(InjectionPoint injectionPoint) {
        ParameterizedType type = (ParameterizedType) injectionPoint.getType();
        Class<T> entityClass = (Class<T>) type.getActualTypeArguments()[0];
        this.entityClass = entityClass;
    }
    
    public T find(ID id) {
        return entityService.find(entityClass, id);
    }
    
    public List<T> findAll() {
        return entityService.findAll(entityClass);
    }

  [...]
}

Поскольку для метода поиска EntityManager нужен класс типа в качестве аргумента, я внедрил InjectionPoint в метод entityClass, чтобы получить фактический «тип класса сущности» и передать его в качестве аргумента методам GenericEntityService.

Что-то не так с этим подходом для получения класса тип из аргумента типа?

1 Ответ

0 голосов
/ 15 июля 2020

Поскольку ваша функция entityClass не вызывается, она не заполняет ваше поле entityClass, поэтому при вызове она всегда будет иметь значение null.

Вы можете использовать аналогичный подход, избегая необходимости в точке инъекции, используя метод получения, который использует параметризованный тип. Ваш код изменится на:

@Dependent
public abstract class EntityService<T, ID> {

    @Inject
    private GenericEntityService<T, ID> entityService;

    private Class<T> entityClass;

    public synchronized Class<T> getEntityClass() {
        if (entityClass == null) {
            entityClass = inferEntityClass(getClass());
        }
        return entityClass;
    }

    private Class<?> inferEntityClass(Class<?> clazz) {
        // This code should be safer
        ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
        return (Class<T>) parameterizedType.getActualTypeArguments()[0];
    }

    public T find(ID id) {
        return entityService.find(getEntityClass(), id);
    }
    // ...
}

Кстати, не связанное с этим: я не понял причины, по которой вы должны создать еще один уровень bean-компонентов вместо вызова EntityManager непосредственно из EntityService. Обратите внимание, что некоторые функции, оправдывающие эту архитектуру, такие как управление транзакциями, уже присутствуют в CDI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...