1

我在依赖注入方面遇到了一些麻烦,因为我对 Seam 真的很陌生,我可能会以错误的方式做某事!

我需要在从控制器内触发的新线程上注入依赖项 - 我没有例外,但它们只是来了nulld1首先,我尝试在线程中简单地重用(见下文),但它是null,然后我有了这个想法,再次注释这个对象@In......不幸的是,同样的事情发生了(得到空)!!!

@Scope(ScopeType.CONVERSATION)
@Name("myController")
public class MyController{
    @In(create = true)
    private Dependency1 d1; //ok, gets injected with no problems!

    public void importantMethod(){
        //this part of the method is important and is fast
        //but below comes an expensive part that takes some minutes

        new Thread(new Runnable(){
            @In(create = true)
            private Dependency1 anotherD1;  //I still need d1 here!!!       

            @Override
            public void run(){
                //I want to run expensive code here.
                //A new thread is required in order to leave
                //the visitor free to go else where on the web site

                //First trial was to make d1 final and simply use it here!
                //d1.doExpensiveStuff();
            };
        }).start();
    }
}

有谁知道为什么会这样?使用 DI/Seam/Threading 时有什么好的做法吗?

4

1 回答 1

5

注入仅发生:

  1. 在 Seam 组件中(在您的示例中,MyController是组件,Runnable您在内部创建的匿名不是组件)。
  2. 在 Seam 生命周期内。生命周期可以由 JSF 请求、异步执行或您自己手动启动。

所以,你不能@In在你的线程中使用,因为它不是一个组件,Seam 不会拦截对它的调用。要在异步线程中获取组件,您需要使用 Seam API 来启动生命周期并获取您需要的组件:

@Scope(ScopeType.CONVERSATION)
@Name("myController")
public class MyController {

    @In(create = true)
    private transient Dependency1 d1;

    public void importantMethod() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                LifeCycle.beginCall(); // Start the Seam lifecycle
                Dependency1 d1 = (Dependency1) Component.getInstance("dependency1");
                d1.doExpensiveStuff();
                LifeCycle.endCall();   // Dispose the lifecycle
            }
        }).start();
    }
}

Seam 提供的@Asynchronous注解正是您想要的。如果在 Seam 组件的方法中使用此注解,则该方法将在后台线程中执行(取自 Seam 拥有的线程池)。请注意,异步方法将能够像使用普通的 Seam 调用一样使用注入的依赖项:

@Name("myBackgroundWork")
public class MyBackgroundWork {
    @In private transient Dependency1 d1;

    @Asynchronous
    public void runInBackground() {
         d1.doExpensiveStuff();
    }
}

然后MyController您可以调用异步方法,该方法将启动后台工作并立即返回:

@Scope(ScopeType.CONVERSATION)
@Name("myController")
public class MyController {
    @In(create = true)
    private MyBackgroundWork myBackgroundWork;

    public void importantMethod() {
        // Execution will return immediately and thread will start
        myBackgroundWork.runInBackground();
    }
}

更多信息在这里:

http://docs.jboss.org/seam/2.2.2.Final/reference/en-US/html/jms.html#d0e21609

于 2012-10-05T10:31:00.257 回答