众所周知,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中国
作者
相关推荐
-
内存数据网格提供商一头扎进Java
10年的时间里,应用性能解决方案提供商Alachisoft一直在用NCache(针对N-Tier和网格计算.NET应用的内存计算和数据网格产品)为.NET社区服务。
-
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高, 直到把内存吃完应用崩溃,但是这个wrapper
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高 […]
-
Google App Engine for Java 对于目前中国需要学习吗?
-
前无古人后无来者的Java平台
开发人员一直在致力于保持Java的活力,经过20年后,我们感觉从来没有更好的、更令人激动的时刻如同Java社区一样。