【问题标题】:Java CDI: Decorator with multiple generic paramsJava CDI:具有多个通用参数的装饰器
【发布时间】:2017-06-21 04:27:44
【问题描述】:

我有以下结构:

@Decorator
public abstract class MyDecorator<T extends BaseEntity, Q extends QueryParams> implements EntityService<T, Q> {

    @Any
    @Inject
    @Delegate
    EntityService<T, Q> delegate;

    @Override
    public T save(T entity) { ... }

} 

这是EntityService 接口声明:

public interface EntityService<T extends BaseEntity, Q extends QueryParams> {

    T save(T entity);

    void deleteById(Integer id);

    void deleteAllById(List<Integer> ids);

    void delete(T entity);

    void deleteAll(List<T> entities);

    T findById(Integer id);

    QueryResultWrapper<T> query(Q parameters);

    Long count(Q parameters);

}

不幸的是,虽然没有显示任何错误,但装饰器保存方法从未被调用过……我让它工作的唯一方法是这样的:

@Decorator
public abstract class MyDecorator<T extends BaseEntity> implements EntityService<T> { ... }

没有Q extends QueryParams 通用参数。

MyDecoratorbeans.xml 中声明。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
   bean-discovery-mode="all" version="1.1">

    <decorators>
        <class>fortuna.backend.comum.decorators.MyDecorator</class>
    </decorators>

</beans>

有什么线索吗?

【问题讨论】:

  • 您可能需要提供更多信息。我试着用上面的方法做一个快速的 sn-p,它对我很有效(使用 Weld,我认为你也使用)。同样在您的问题中,您提到了EntityService,但您显示了带有CrudService 的代码sn-p。这是一个错字还是介于两者之间的另一个泛型类?
  • 一个错字,抱歉,刚刚修正。无论如何,我可以提供什么样的额外信息?
  • 你能提供你的 beans.xml 文件吗?
  • @hya 抱歉拖了这么久,我刚刚添加了
  • 你能分享任何实现 QueryParams 的类吗?

标签: java generics cdi decorator


【解决方案1】:

设法解决了这个问题。我的问题是我在大多数端点/服务实现中直接使用QueryParams,例如:

public class PersonService extends EntityService&lt;Person, QueryParams&gt; { ... }

其实QueryParams实际上并不是extends QueryParams,它是类本身!这就是PersonService 根本没有触发MyDecorator 的原因!

因此,我创建了一个名为 IQueryParams 的接口并改用它,就像这样:

public abstract class MyDecorator&lt;T extends BaseEntity, Q extends IQueryParams&gt; implements EntityService&lt;T, Q&gt; {

现在PersonService 保存方法会触发MyDecorator

【讨论】:

    【解决方案2】:

    你正在这样做 ->

    EntityService<T extends BaseEntity, Q extends QueryParams>
    

    如果那个接口取两个Object,一个T扩展BaseEntity,另一个Q扩展QueryParams,分别可以尝试直接把Specific types代替。就像这样:

    到接口(这里,最重要的是尽可能通用,因此,您选择两个名称,如 A、B 或在您的情况下):

    public interface EntityService<T, Q> {
    
    T Save(T param);
    
    void otherMethod(Q param);
    

    }

    给装饰者(这里,此时你可以选择类型,所以不必是“通用”):

    public abstract class MyDecorator implements EntityService<BaseEntity, QueryParams>{
    
    @Any
    @Inject
    @Delegate
    EntityService<BaseEntity, QueryParams> delegate;
    //If I understood well the problem, this just work and solve your problem, 
    //or else... I'm sorry, you can give me more data so I could help you
    //a little more
    
    //Check here, I give a concrete type for T abstract generic type, in 
    //your case BaseEntity
    @Override
    public BaseEntity save(BaseEntity entity) { 
        BaseEntity retSomething; //this is ilustrative
        super.save(entity);  //save your entity as you know how.
        return retSomething; //I really don't know why your save method has a 
                             //return statament, but, if you need it, check the 
                             //return type
    }
    
    @Override
    public void otherMethod(QueryParams param) {
        // Check here, in the interface the name was Q, now here you only
        // can use as param an QueryParams type object
    
    }
    

    }

    【讨论】:

    • 您好 Damian,首先非常感谢您的回答。但是现在,'@Delegate' 实例呢?它需要知道具体类型,而不仅仅是超类型才能正确注入.. @Damian Lattenero
    • 好的,我将更改我原来的答案以便也回答这个问题。
    • 很抱歉,答案是肯定的,@Delegate 实例必须知道具体的(比具体的词更好)类型。让我知道这是否有效
    • Damian,问题在于依赖注入将被破坏,因为该注入点将有多个可用的 bean :(
    • 嘿!恭喜!很高兴为您提供帮助
    猜你喜欢
    • 2021-12-16
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多