从基类引用调用时,扩展类中的CDI拦截器不起作用

时间:2012-11-20 23:54:47

标签: java java-ee cdi interceptor extends

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

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();
    }
}

的beans.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);
    }
}

好的,这是在战争中:

EditHelper.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);不会发射拦截器。我会很高兴得到任何帮助。

1 个答案:

答案 0 :(得分:0)

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

使用@Default限定符的CDI bean祖先:

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

Ancestor 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的构造函数托管豆。