六指琴魔电影歌曲:Spring的集成

来源:百度文库 编辑:中财网 时间:2024/05/07 15:28:47

原文地址:

                  http://cometd.org/documentation/cometd-java/server/services/integration-spring

      

 

Spring的集成

 

 

sbordet 提交于星期二,2009/11/17-15:39

 

 

Bayeux 服务与Spring集成

 

 

CometD 服务与Spring的集成尤其有趣,因为大多时候你的 Bayeux 服务将需要其他 bean 来执行他们的服务。

并不是所有的 Bayeux 服务都像EchoService这样简单,加入Spring的依赖注入 (和其他框架一样) 集成将大大简化开发过程。

 

 

下面您可以找到 3 种建议的方法集成Spring

 

 

Late Spring初始化

 

 

这种方法是延迟Spring初始化,直到 CometD servlet 初始化完成。

这种方法在这些情况下适用:要求Spring beans可以被延迟初始化,因为没有其他服务或框架需要预先进行Spring的初始化。

 

 

这种方法要求Spring Bayeux 服务的一些代码粘合在一起。

要求一些代码粘合在一起的原因有两个:

Bayeux 对象不是由Spring创建(是 CometD servlet),所以任何用于Bayeux对象的bean必须在CometD servlet初始化后才初始化。

web.xml中的servlets listeners的初始化顺序在现有的Servlet 规范中不能被指定 (只有在servlet 3.0 中能完全指定顺序)

 

 

所以,为了保证方便初始化,这段粘合的代码是必需的。

 

 

下面您可以找到配置文件和集成Spring所需的代码。

 

 

首先,web.xml 文件:

 

 

 

 

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

         version="2.5">

 

   

       cometd

       org.cometd.server.continuation.ContinuationCometdServlet

       1

   

   

       cometd

       /cometd/*

   

 

   

       com.acme.cometd.spring.LateSpringBayeuxInitializer

   

 

 

请注意我们是使用listener初始化Spring的。此listener完全取代了Spirng org.springframework.web.context.ContextLoaderListener,但它是基于相同的类的,这个类是用来执行web 应用程序启动时上下文初始化的。

这意味着:

LateSpringBayeuxInitializer会装载位于 /WEB-INF/applicationContext.xml中的Spring bean,或装载在 servlet上下文的初始化参数contextConfigLocation,和每一个通常Spring需要的配置。

 

 

其次, Spring applicationContext.xml 文件中,定义我们先前写好的 EchoService

 

 

 

 

 

 

 

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 

   

       

   

 

 

请注意这里我们引用的是"bayeux"bean,这在Spring xml文件中是没有定义的,他是在 LateSpringBayeuxInitializer 中定义的,见下文。

 

最后,在 web.xml的 LateSpringBayeuxInitializer中像下面这样编写代码以整合Spring:

 

public class LateSpringBayeuxInitializerimplements ServletContextListener, ServletContextAttributeListener

{

   private volatile ContextLoader loader;

 

   public void contextInitialized(ServletContextEvent event)

   {

   }

 

   public void contextDestroyed(ServletContextEvent event)

   {

       ContextLoader loader = this.loader;

       if (loader != null)

           loader.closeWebApplicationContext(event.getServletContext());

   }

 

   public void attributeAdded(ServletContextAttributeEvent event)

   {

       if (Bayeux.ATTRIBUTE.equals(event.getName()))

       {

           Bayeux bayeux = (Bayeux) event.getValue();

 

           StaticListableBeanFactory factory = new StaticListableBeanFactory();

           factory.addBean("bayeux", bayeux);

           GenericApplicationContext bayeuxApplicationContext = newGenericApplicationContext(new DefaultListableBeanFactory(factory));

           bayeuxApplicationContext.refresh();

 

           loader = new BayeuxContextLoader(bayeuxApplicationContext);

           ApplicationContext applicationContext =loader.initWebApplicationContext(event.getServletContext());

 

           customizeBayeux(bayeux, applicationContext);

       }

   }

 

   public void attributeRemoved(ServletContextAttributeEvent event)

   {

   }

 

   public void attributeReplaced(ServletContextAttributeEvent event)

   {

   }

 

   protected void customizeBayeux(Bayeux bayeux, ApplicationContextapplicationContext)

   {

   }

 

   private static class BayeuxContextLoader extends ContextLoader

   {

       private final ApplicationContext parentApplicationContext;

 

       public BayeuxContextLoader(ApplicationContext parentApplicationContext)

       {

           this.parentApplicationContext = parentApplicationContext;

       }

 

       @Override

       protected ApplicationContext loadParentContext(ServletContextservletContext) throws BeansException

       {

           return parentApplicationContext;

       }

   }

}

 

 

请注意这里可以重写 customizeBayeux() 方法和进一步自定义 Bayeux 对象,例如,从Spring的应用程序上下文中查找一个 org.cometd.SecurityPolicy 对象并把它设置在 Bayeux 对象上。或者,用相同的方式,向 Bayeux 对象添加您Spring配置的 Bayeux 扩展。

 

 

Lazy Spring 初始化

 

 

这种方法允许正常初始化Spirng,但需要 Bayeux 服务标记成Lazy(懒加载) (且所有其他的bean或服务都要依赖于 Bayeux 服务),当然,也同样需要 CometD servlet正确初始化。

这种方法在这些情况下适用:有其他框架 (例如,Struts2) 需要预先进行Spring初始化。

 

 

这种方法需要编写一些代码从Spring配置文件中访问 Bayeux 对象。

 

 

首先,web.xml 文件:

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

        version="2.5">

 

   

       cometd

       org.cometd.server.continuation.ContinuationCometdServlet

       1

   

   

       cometd

       /cometd/*

   

 

   

       org.springframework.web.context.ContextLoaderListener

   

   

       com.acme.cometd.spring.LazySpringBayeuxInitializer

   

 

 

 

请注意我们使用的是普通的spring侦听器(ContextLoaderListener)进行Spring的初始化,但我们还添加了另一个侦听器,LazySpringBayeuxInitializer

LazySpringBayeuxInitializer是我们需要从Spring配置文件中访问 Bayeux 对象所编写的代码:

 

public classLazySpringBayeuxInitializer implements ServletContextAttributeListener

{

    public voidattributeAdded(ServletContextAttributeEvent event)

    {

        if(Bayeux.ATTRIBUTE.equals(event.getName()))

        {

            Bayeux bayeux = (Bayeux)event.getValue();

            BayeuxHolder.setBayeux(bayeux);

        }

    }

 

    public voidattributeRemoved(ServletContextAttributeEvent event)

    {

    }

 

    public voidattributeReplaced(ServletContextAttributeEvent event)

    {

    }

}

 

LazySpringBayeuxInitializer类用到的 BayeuxHolder 类, 其实是非常简单的:

 

 

 

 

 

 

 

 

public classBayeuxHolder

{

    private static volatile Bayeux bayeux;

 

    public static void setBayeux(Bayeux bayeux)

    {

        BayeuxHolder.bayeux = bayeux;

    }

 

    public static Bayeux getBayeux()

    {

        return bayeux;

    }

}

 

到此,我们需要在Spring的配置文件 applicationContext.xml 中做如下配置:

 

 

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 

   

 

   

 

   

       

       

   

 

 

 

请注意Spring的配置文件中可以有正常的bean (如 nonLazyService),这些bean可以被注入这些lazy(懒加载的) bean中,如: EchoService

另外,请注意这里使用的 BayeuxHolder,是lazy(懒加载)初始化的,以便检索在 CometD servlet 初始化完成后被LazySpringBayeuxInitializer存储的 Bayeux 对象。

 

 

请注意EchoService是非常重要的,它也是懒加载的,这样它才能被注入到其他懒加载初始化的bean,或非单例bean (如原型范围的bean 如果被注入到单例且非懒加载的bean中,因为他还没初始化(CometD servlet还没初始化),所以你会得到一个错误。

 

 

Full Spring初始化

 

 

这种方法是在Spring配置文件中直接初始化 Bayeux 对象,并注入 servlet 上下文中,这上下文是 CometD servlet 创建的。

这种方法更多地有点依赖于 CometD 实现,且如果CometD 实现更改了,它也要跟着改。

它可能需要或可能不需要中间代码,取决于正在开发的应用程序的其他细节(参见下文)。

它也需要一点规范,因为现在的Bayeux 对象可以在这两个位置: Spring配置文件和 web.xml 文件,而您不想将Bayeux 的配置拆分在不同的地方。

 

 

Web.xml 文件,如下所示:

 

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

         version="2.5">

 

   

       cometd

       org.cometd.server.continuation.ContinuationCometdServlet

       1

   

   

       cometd

        /cometd/*

   

 

   

       org.springframework.web.context.ContextLoaderListener

   

 

 

Spring的配置文件 applicationContext.xml 如下所示:

 

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 

   

 

    

       

   

 

   

       

           

               

                   

               

           

       

   

 

   

       

       

   

 

 

 

注意这里的Bayeux 对象是在applicationContext.xml文件中引用的,并且,这个Bayeux对象是通过springServletContextAttributeExporter访问的。

 

 

 

这里只是创建一个没有初始化的Bayeux对象,只有在CometD servlet初始化后Bayeux对象才能够使用;正因为如此,懒加载的echoService(任何的Bayeux服务,引用到的服务,其他的依赖服务)才很重要。

 

因为echoService是懒加载的,当应用程序第一次用到它,就必须要告诉spring去实例化和初始化它。

 

如果你使用的其他框架需要用到spring的依赖注入,那么这个步骤应该由这个框架来完成。例如:你用spring配合structs2,你不需要告诉spring实例化和初始化你的CometD服务,因为structs2能识别有需要注入的CometD服务(如:在structs2action中),所以structs2要求spring提供。

 

因此,上述的配置就完全足够了。

 

不管怎样,如果你不需要其他框架,你就要手动告诉spring实例化和初始化你的CometD服务。

 

这样做有点类似于非spring服务集成的描述:用一个servlet或侦听器来配置你的懒加载CometD服务。

见下面的例子:

 

public classConfigurationServlet extends GenericServlet

{

    public void init() throws ServletException

    {

        // Grab Spring's ApplicationContent

        ApplicationContext context =WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());

 

        // Trigger CometD serviceinitialization

       context.getBean("echoService");

    }

   

    public void service(ServletRequest request,ServletResponse response) throws ServletException, IOException

    {

        throw new ServletException();

    }

}

 

 

 

 

web.xml的这个servlet中必须给load-on-startup标签元素设置一个高的值。

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

         version="2.5">

 

   

       cometd

       org.cometd.server.continuation.ContinuationCometdServlet

       1

   

   

       cometd

       /cometd/*

   

 

   

        configuration

       com.acme.cometd.ConfigurationServlet

       2

   

 

   

       org.springframework.web.context.ContextLoaderListener