Решите, какую реализацию использовать в @Inject
У меня есть GenericCrudController<E>
что инкапсулирует экземпляр моего GenericCrudBO<E>
, и мой GenericCrudBO<E>
инкапсулирует экземпляр моего GenericCrudDAO<E>
, Итак, что я хочу сделать, это сделать, например, мой GenericCrudController<User>
по умолчанию имеет реализацию GenericCrudBO<User>
, если есть, конечно. Если нет, я хочу придерживаться универсальной реализации. Я использую CDI в проекте, и я думаю, что это путь, но я не знаю, какие аннотации использовать. Структура и вышеупомянутый сценарий следующие:
public abstract class GenericController<T extends BaseEntity> implements Serializable {
private static final long serialVersionUID = 1L;
protected List<T> list;
protected T entity;
protected T filter;
@Inject
@Named("crudBO")
protected CrudBO<T> bo;
/*IRRELEVANT CODE GOES THERE */
}
@Named("crudBO")
public class GenericCrudBO<E extends BaseEntity> implements CrudBO<E>{
private static final long serialVersionUID = 1L;
@Inject
@Named("crudDAO")
protected GenericCrudDAO<E> dao;
@Override
@SuppressWarnings("unchecked")
public List<E> search(E filter) {
Class<E> clazz = (Class<E>) filter.getClass();
return dao.search(clazz, filter);
}
/*IRRELEVANT CODE GOES THERE*/
}
@Named("crudDAO")
public class GenericCrudDAO<E extends BaseEntity> implements CrudDAO<E>{/*IRRELEVANT CODE GOES THERE*/}
Вот некоторые примеры реализации общей структуры:
public class UserBO extends GenericCrudBO<User>{
/*IRRELEVANT CODE GOES THERE*/
@Override
public List<User> search(User filter) {
/*SPEFIFIC CODE*/
}
}
@Named(value="userController")
@ViewScoped
public class UserController extends GenericController<User>{
@Inject private UserBO userBO;
@Override
public void search() {
if(filter != null) {
list = userBO.search(filter);
} else throw new RuntimeException();
}
}
Теперь обратите внимание, что я должен вручную внедрить экземпляр UserBO и переопределить метод поиска, чтобы достичь своей цели - вызвать метод поиска UserBO вместо GenericCrudBO. Я спрашиваю, возможно ли сделать это с некоторой аннотацией CDI, заставляя процессор вставлять экземпляр правильной реализации на основе универсального типа контроллера. Спасибо
1 ответ
Я решил проблему, используя объект javax.enterprise.inject.Instance для инкапсуляции моих bo и dao. Сюда:
@Inject
private Instance<CrudBO<T>> bo;
public CrudBO<T> getBo() {
return bo.get();
}
Просто чтобы прояснить ситуацию, CrudBO - это интерфейс, который реализует GenericCrudBO, поэтому, зная, что по умолчанию GenericCrudBO аннотирован @Default, я аннотировал специализированные классы @Alternative:
@Alternative
public class SpecializedCrudBO extends GenericCrudBO<SpecificClass>{
}
Я также объявил альтернативные BO и DAO в beans.xml:
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<alternatives>
<class>br.com.logtec.business.SpecializedCrudBO</class>
...
</alternatives>
</beans>
И теперь CDI может обрабатывать мои общие Java-бины во время выполнения, это очень хорошо также потому, что мне не нужно создавать тонны шаблонных классов.