如何使用Java配置进行Spring bean管理?

日期: 2011-08-23 作者:Rajeev Hathi 来源:TechTarget中国 英文

  众所周知,Spring框架是控制反转(IOC)或依赖性注入(DI)模式的推动因素,而这种推动是通过基于容器的配置实现的。过去,Spring允许开发人员使用基于XML的配置,通过利用应用程序上下文XML文件来管理bean依赖性。此文件处于应用程序的外部,包含bean及其与该应用程序的依赖项的定义。尽管使用XML配置较为简单和便捷,但仍有另外一种方法可定义bean及其依赖项。这种方法也称为基于Java的配置。不同于XML,基于Java的配置使您能够以编程方式管理bean。这可通过运用多种注释来实现。 这篇文章将演示Java配置示例,并将其与传统XML配置方法相对比。本文将按照如下步骤演示基于Java的配置的基本用法:

  • 理解@Configuration和@Bean注释
  • 使用AnnotationConfigApplicationContext注册配置类
  • 配置Web应用程序
  • 实现bean生命周期回调和范围

  我们将使用一所在线大学的创建课程用例。在创建课程的过程中,还会创建主题或者模块,而各主题可能又有着不同的作业。因此,我们要创建三个bean,分别为Course、Module和Assignment。Course bean将包含一个对Module bean的引用,后者包含对Assignment bean的引用。

  理解@Configuration和@Bean注释

  在理想的场景中,您可以在表示应用程序上下文的XML中定义bean。以下代码展示了创建课程 用例中的上下文XML及bean定义:

  清单 1. XML与bean定义
    

以下是引用片段:
<beans>
 <bean id=”course” class=”demo.Course”>
  <property name=”module” ref=”module”/>
   </bean>
 
 <bean id=”module” class=”demo.Module”>
  <property name=”assignment” ref=”assignment”/>
   </bean>
 
 <bean id=”assignment” class=”demo.Assignment” />
</beans>

  以上XML就是您在使用Spring配置bean时通常会编写的代码。这段XML代码定义了Course bean,它引用Module bean。Module bean有一个Assignment bean的引用。您现在要删除这段XML,编写同等效果的Java代码。您将使用基于Java 的配置定义上面指定的bean。我们会将XML替换为Java类,这个Java类现在将用作bean配置的平台。我们将这个类命名为AppContext.java。以下代码展示了AppContext类。

  清单 2. 包含bean定义的AppContext配置类
    

以下是引用片段:
@Configuration
public class AppContext {
 @Bean
 public Course course() {
  Course course = new Course();
  course.setModule(module());
  return course;
 }
 @Bean
 public Module module() {
  Module module = new Module();
  module.setAssignment(assignment());
  return module;
 }
 @Bean
 public Assignment assignment() {
  return new Assignment();
 }
}

  正如您通过以上代码所看到的那样,现在可以以编程的方式将bean定义为基于Java的配置的一部分。AppContext类现在就像XML一样表示配置类。这是通过利用@Configuration注释实现的。@Configuration注释位于类的顶端。它告知 Spring 容器这个类是一个拥有bean定义和依赖项的配置类。@Bean注释用于定义bean。上述注释位于实例化bean并设置依赖项的方法上方。方法名称与bean id或默认名称相同。该方法的返回类型是向Spring应用程序上下文注册的bean。您可使用bean的setter方法来设置依赖项,容器将调用它们来连接相关项。基于Java的配置也被视为基于注释的配置。

  使用AnnotationConfigApplicationContext注册配置类

  在传统XML方法中,您可使用ClassPathXmlApplicationContext类来加载外部XML上下文文件。但在使用基于Java的配置时,有一个AnnotationConfigApplicationContext类。AnnotationConfigApplicationContext类是ApplicationContext接口的一个实现,使您能够注册所注释的配置类。此处的配置类是使用 @Configuration 注释声明的AppContext。在注册了所述类之后,@Bean注释的方法返回的所有bean类型也会得到注册。以下代码演示了AnnotationConfigApplicationContext类的使用:

  清单 3. 使用AnnotationConfigApplicationContext注册AppContext类
    

以下是引用片段:
public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class);
  Course course = ctx.getBean(Course.class);
  course.getName();
}

  正如以上代码所示,AppContext配置类的注册方式是将其传递给AnnotationConfigApplicationContext构造函数。此外,您还可以使用所述上下文类的register方法来注册配置类。以下代码展示了另外一种方法。


  清单 4. 注册AppContext类:另外一种方法
    

以下是引用片段:
public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppContext.class)
}

  注册配置类将自动注册@Bean注释的方法名称,因而其对应的bean就是Course、Module和Assignment。随后您可以使用getBean方法来获取相关的bean,并调用其业务方法。如您所见,编写Java的配置类并将其注册到Spring上下文非常简单。下一节将讨论如何将基于Java的配置与Web应用程序配合使用。

  配置Web应用程序

  过去,您通常要利用XmlWebApplicationContext上下文来配置Spring Web应用程序,即在Web部署描述符文件web.xml中指定外部XML上下文文件的路径。XMLWebApplicationContext是Web应用程序使用的默认上下文类。以下代码描述了web.xml中指向将由ContextLoaderListener监听器类载入的外部XML上下文文件的元素。

  清单 5. 使用外部XML上下文文件的web.xml
    

以下是引用片段:
<web-app>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>
 <servlet>
 <servlet-name>sampleServlet</servlet-name>
 <servlet-class>
  org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 </servlet>

</web-app>

  现在,您要将web.xml中的上述代码更改为使用AnnotationConfigApplicationContext类。切记,XmlWebApplicationContext是Spring为Web应用程序使用的默认上下文实现,因此您永远不必在您的web.xml文件中显式指定这个上下文类。现在,您将使用基于Java的配置,因此在配置Web应用程序时,需要在web.xml文件中指定AnnotationConfigApplicationContext类。上述代码将修改如下:

  清单 6. 修改后的使用AnnotationConfigApplicationContext的web.xml
    

以下是引用片段:
<web-app>
 <context-param>
  <param-name>contextClass</param-name>
  <param-value>
   org.springframework.web.context.
   support.AnnotationConfigWebApplicationContext
  </param-value>
 </context-param>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   demo.AppContext
  </param-value>
 </context-param>
 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>
 <servlet>
 <servlet-name>sampleServlet</servlet-name>
 <servlet-class>
  org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <init-param>
  <param-name>contextClass</param-name>
  <param-value>
   org.springframework.web.context.
   support.AnnotationConfigWebApplicationContext
  </param-value>
 </init-param>
 </servlet>

</web-app>

  以上修改后的web.xml现在定义了AnnotationConfigWebApplicationContext上下文类,并将其作为上下文参数和servlet元素的一部分。上下文配置位置现在指向AppContext配置类。这非常简单。下一节将演示bean的生命周期回调和范围的实现。

  实现bean生命周期回调和范围

  生命周期回调

  您还可以使用基于Java的配置来管理bean的生命周期。@Bean支持两种属性,即initMethod和destroyMethod,这些属性可用于定义生命周期方法。在实例化bean或即将销毁它时,容器便可调用生命周期方法。生命周期方法也称为回调方法,因为它将由容器调用。使用@Bean注释注册的bean也支持JSR-250规定的标准@PostConstruct和@PreDestroy注释。如果您正在使用XML方法来定义bean,那么就应该使用bean元素来定义生命周期回调方法。以下代码显示了在XML配置中通常使用bean元素定义回调的方法。

  清单 7. 使用XML方法实现生命周期回调
    

以下是引用片段:
<bean id=”course” class=”demo.Course” init-method=”setup” destroy-method=”cleanup” >
 <property name=”module” ref=”module”/>
</bean>

  以下代码演示了使用Java配置的生命周期方法

  清单 8. 使用AppContext配置类实现bean生命周期方法
    

以下是引用片段:
@Configuration
public class AppContext {
 @Bean(initMethod = “setup”, destroyMethod = “cleanup”)
 public Course course() {
  Course course = new Course();
  course.setModule(module());
  return course;
 }
 @Bean(initMethod = “setup”, destroyMethod = “cleanup”)
 public Module module() {
  Module module = new Module();
  module.setAssignment(assignment());
  return module;
 }
 
 …
}  
public class Course {
 private Module module;
 private String name;
 
 public Course() {
 }
 
 public void setup() {
  this.name = “M100 Pythagoras Theorems”
 }
 
 public void setModule(Module module) {
  this.module = module;
 }
 
 public void cleanup() {
  module = null;
 }
}

  上面的代码重新访问了AppContext配置类。@Bean注释现在有两个额外的属性,即initMethod和destroyMethod。它们定义了生命周期方法的设置和清除。这些方法是在已经注册的bean中实现的,最终由容器在bean初始化及其销毁之前调用它。这里以Course bean为例,提供了生命周期方法实现。所实现的方法是setup和cleanup。同样,您还可以在Module和Assignment bean中实现这些方法。

  Bean范围

  bean的方法是使用@Scope注释定义的。XML中实现这一目标的方法是指定bean元素中的scope属性。

  清单 9. 使用XML方法定义bean范围
    

以下是引用片段:
<bean id=”course” class=”demo.Course” scope=”prototype” >
 <property name=”module” ref=”module”/>
</bean>

  以下代码展示了使用Java配置的bean范围定义:

  清单 10. 使用AppContext配置类定义bean范围
    

以下是引用片段:
@Configuration
public class AppContext {
 @Bean(initMethod = “setup”, destroyMethod = “cleanup”)
 @Scope(“prototype”)
 public Course course() {
  Course course = new Course();
  course.setModule(module());
  return course;
 }
 …
}

   
  正如您在上面的代码中所看到的那样,在Java配置类中定义bean的范围非常简单。上面的AppContext配置类使用@Scope注释为Course bean定义了一个prototype范围。默认范围是singleton。

  利用Java配置可以做许多事情。本文只触及了一些基础内容。使用Java配置并无显著优势,它仅仅是Spring提供的XML配置的替代方法。对于不喜欢在框架中使用XML的人来说,这是实现配置的一种出色方法。但缺点也是显而易见的,如果您对Java类中的配置做出了任何更改,就必须重新编译应用程序。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐