为什么我不能在我的控制器内的新线程中使用@In(使用jboss seam)注入依赖项?

时间:2012-10-04 20:57:59

标签: java dependency-injection seam

我对依赖注入的东西有些麻烦,因为我对Seam很新,我可能会以错误的方式做某事!

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

@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时有什么好的做法吗?

1 个答案:

答案 0 :(得分:5)

仅发生注射:

  1. 在Seam组件中(在您的示例中,MyController是一个组件,您在其中创建的匿名Runnable不是组件)。
  2. 在Seam生命周期内。生命周期由JSF请求启动,异步执行或由您自己手动启动。
  3. 因此,你不能在你的线程中使用@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