4

我对 CDI 拦截器有疑问。在我的 EJB 模块中,我创建了拦截器注释及其实现,我还在 beans.xml 中添加了实现类。我有一个名为 AbstractFacade 的抽象类和一些从它派生的类。在一个类中,我重写了 create 方法并将我的拦截器注释添加到它。现在在 web 模块中,我有一个带有拦截器注释的 ejb bean 实例,但是对它的引用具有 AbstractFacade 类型。当我在这个引用上调用 create 方法时,会调用 ejb 模块中的适当方法(这个带有注释)但我的拦截器没有被调用,但是如果我将此引用转换为其真实类型并调用 create 拦截器将正常工作。我不确定我是否能很好地描述它,所以这里是代码:

FooInter.java

package foo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding;

@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface FooInter{}

FooInterImpl.java

package foo;

import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Interceptor
@FooInter
public class FooInterImpl {
    @AroundInvoke
    public Object fuckCall(InvocationContext context) throws Exception {
        System.out.println("Interceptor: it works");

        return context.proceed();
    }
}

豆类.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <interceptors>
        <class>foo.FooInterImpl</class>
    </interceptors>
</beans>

AbstractFacade.java

public abstract class AbstractFacade<T> {

    //...

    public void create(T entity) {
        //...
    }
}

FooFacade.java

@Stateless
public class FooFacade extends AbstractFacade<Foo> {

    //...

    @Override
    @FooInter
    public void create(Foo entity) {
        super.create(entity);
    }
}

好的,这是在战争中:

编辑助手.java

public abstract class EditHelper<T> {
    protected T entity;

    //...

    protected abstract AbstractFacade<T> getFacade();

    public void save() {
        //...
        //if T is foo and getFacade returns FooFacade, interceptor won't be called here!
        getFacade().create(entity);
    }
}

FooEditHelper.java

public class FooEditHelper extends EditHelper<Foo> {
    @EJB
    private FooFacade fooFacade;

    //...

    protected AbstractFacade<T> getFacade() {
        return fooFacade;
    }

    @Override
    public void save() {
        getFacade().create(entity); //interceptor won't works !!!!!!!!!!!
        ((FooFacade)getFacade()).create(entity); //but here interceptor will work
    }
}

我不知道为什么 getFacade().create(entity); 不会发射拦截器。我会很高兴得到任何帮助。

4

1 回答 1

0

我的回答可能有点离题,但我正在从 JSF 托管 bean 迁移到 CDI 托管 bean,我刚刚确认我能够在后代 CDI bean 中成功使用super (使用“自定义”@后代限定符)“扩展”祖先 CDI bean(使用 @Default 限定符)。

带有 @Default 限定符的 CDI bean 祖先:

@Default
@Named("pf_pointOfContactController")
@SessionScoped
public class pf_PointOfContactController implements Serializable {

祖先 bean 具有以下特性:

@PostConstruct
protected void init() {

带有 @Descendant 限定符的 CDI bean 后代:

@Descendant
@Named("pf_orderCustomerPointOfContactController")
@SessionScoped
public class pf_OrderCustomerPointOfContactController extends pf_PointOfContactController {

后代bean具有以下内容:

@PostConstruct
public void init(){
    super.init();

我必须添加/使用 super.init(),因为祖先 CDI bean 中的方法引发 NullPointerException,因为祖先 bean 的 @PostConstruct 没有在 CDI @Descendant bean 中执行。

我已经看到/听到/读到建议在使用 CDI 时使用 @PostConstruct 而不是 Constructor 方法,因此祖先 bean 的构造函数具有“初始化”逻辑,并且在使用 JSF 托管 bean 时会自动调用/执行祖先 bean 的构造函数。

于 2012-11-21T07:53:10.223 回答