[Spring] 基于 Java 的配置

来源:互联网 发布:指绘软件 编辑:程序博客网 时间:2024/04/29 09:56

在对 Spring 进行显示配置的时候,有两种可选方案:Java 和 XML。Java 配置是更好的选择,因为它更强大,类型安全且对重构友好。因为它就是 Java 代码,就像程序中的其他 Java 代码一样。

同时,JavaConfig与其他的Java代码又有所区别,尽管它与其他的组件一样都使用相同的语言进行表述,但JavaConfig是 配置代码。这意味着它不应该包含任何业务逻辑,JavaConfig也不应该侵入到业务逻辑代码 之中。

接下来,让我们看一下如何通过JavaConfig显式配置Spring

基本概念:@Configuration 和 @Bean

@Configuration 被用于类上,指明这是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。@Bean 用于方法上,这个方法返回一个被装配的对象,方法体中包含了最终产生bean实例的逻辑。

看一个例子:

@Configurationpublic class AppConfig {    @Bean    public MyService myService() {        return new MyServiceImpl();    }}

上面的 AppConfig 类将和下面的 XML 配置有一样的效果

<beans>    <bean id="myService" class="com.acme.services.MyServiceImpl"/></beans>

默认情况下,bean 的 ID 与带有 @Bean 注解的方法名是一样的。在本例中,bean的名字将会是 myService。如果你想为其设置成一个不同的名字的话,那么可以重命名该方法,也可以通过 name 属性指定一个不同的名字:

@Bean(name = "hisService")public MyService myService() {    return new MyServiceImpl();}

开启自动装配也是很简单的

@Configuration@ComponentScan(basePackages = "com.acme")public class AppConfig  {    ...}

使用 @ComponentScan 注解即可,它等同于如下 XML 配置

<beans>    <context:component-scan base-package="com.acme"/></beans>

借助 JavaConfig 实现注入

我们前面所声明的 myService bean 是非常简单的,它自身没有其他的依赖。但现在,我 们需要声明 MyApp bean,它依赖于 myService 。在 JavaConfig 中,要如何将它们装配在一起呢?

在 JavaConfig 中装配 bean 的最简单方式就是引用创建 bean 的方法。例如,下面就是一种声明 myApp 的可行方案:

@Beanpublic MyApp myApp() {    return new MyApp(myService());}

可以看到,通过调用方法来引用 bean 的方式有点令人困惑。其实还有一种理解起来更为简单的方式:

@Beanpublic MyApp myApp(MyService myService) {    return new MyApp(myService);}

在这里,myApp() 方法请求一个 MyService 作为参数。当 Spring 调用myApp() 创建 MyApp bean 的时候,它会自动装配一个 MyService 到配置方法之中。然后,方法体就可以按照合适的方式来使用它。

通过这种方式引用其他的 bean 通常是最佳的选择,因为它不会要求将MyService 声明到 同一个配置类之中。在这里甚至没有要求MyService 必须要在 JavaConfig 中声明,实际上 它可以通过组件扫描功能自动发现或者通过 XML 来进行配置。

使用 JavaConfig 配置 Java Web

配置DispatcherServlet

DispatcherServlet 是 Spring MVC的核心。在这里请求会第一次接触到框架,它要负责将请求路由到其他的组件之中。

按照传统的方式,像 DispatcherServlet 这样的 Servlet 会配置在 web.xml 文件中,这个文件会放到应用的 WAR 包里面。当然,这是配置 DispatcherServlet 的方法之一。但是,借助于 Servlet 3 规范和 Spring 3.1的功能增强,这种方式已经不是唯一的方案了。

我们会使用 Java 将 DispatcherServlet 配置在 Servlet 容器中,而不会再使用 web.xml 文 件。如下的程序清单展示了所需的Java类。

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {    @Override    protected Class<?>[] getRootConfigClasses() {        return new Class<?>[] {AppConfig.class};    }    //指定配置类    @Override    protected Class<?>[] getServletConfigClasses() {        return new Class<?>[] {WebConfig.class};    }    //将 DispatcherServlet 映射到 "/"    @Override    protected String[] getServletMappings() {        return new String[] {"/"};    }}

要理解上面的程序清单是如何工作的,我们可能只需要知道扩 展AbstractAnnotationConfigDispatcherServletInitializer的任意类都会自 动地配置DispatcherServlet和Spring应用上下文,Spring的应用上下文会位于应用程序 的Servlet上下文之中。

尽管它的名字很长,但是 AbstractAnnotationConfigDispatcherServletInitializer 使用起来很简 便。在程序清单中,WebAppInitializer 重写了三个方法。

第一个方法是 getServletMappings(),它会将一个或多个路径映射 到DispatcherServlet上。在本例中,它映射的是“/”,这表示它会是应用的默认 Servlet。它会处理进入应用的所有请求。

为了理解其他的两个方法,我们首先要理解DispatcherServlet和一个Servlet监听器(也 就是ContextLoaderListener)的关系。

当 DispatcherServlet 启动的时候,它会创建 Spring 应用上下文,并加载配置文件或配置 类中所声明的bean。在程序清单的 getServletConfigClasses() 方法中,我们要求 DispatcherServlet 加载应用上下文时,使用定义在 WebConfig 配置类(使用Java配置)中的 bean。

但是在Spring Web应用中,通常还会有另外一个应用上下文。另外的这个应用上下文是 由ContextLoaderListener创建的。

getServletConfigClasses() 方法返回的带有 @Configuration 注解的类将会用来定义 DispatcherServlet 应用上下文中的 bean。getRootConfigClasses() 方法返回的带有 @Configuration 注解的类将会用来配置 ContextLoaderListener 创建的应用上下文中的bean。

在本例中,根配置定义在 AppConfig 中,DispatcherServlet 的配置声明在 WebConfig 中。

启用Spring MVC

我们有多种方式来配置 DispatcherServlet,与之类似,启用Spring MVC组件的方法也不仅一种。以前,Spring 是使用 XML 进行配置的,你可以使用 <mvc:annotationdriven> 启用注解驱动的Spring MVC。
我们所能创建的最简单的 Java Spring MVC 配置就是一个带有 @EnableWebMvc 注解的类

@Configuration@EnableWebMvcpublic class WebConfig {}

这可以运行起来,它的确能够启用Spring MVC,但还有不少问题要解决:

  • 没有配置视图解析器。如果这样的话,Spring 默认会使用 BeanNameViewResolver,这个视图解析器会查找 ID 与视图名称匹配的 bean,并且查找的 bean 要实现 View 接口,它以这样的方式来解析视图。
  • 没有启用组件扫描。这样的结果就是,Spring只能找到显式声明在配置类中的控制器。
  • 这样配置的话,DispatcherServlet 会映射为应用的默认 Servlet,所以它会处理所有的请求,包括对静态资源的请求,如图片和样式表(在大多数情况下,这可能并不是你想要的效果)。

因此,我们需要在 WebConfig 这个最小的 Spring MVC 配置上再加一些内容,从而让它变得真正有用。如下程序清单中的 WebConfig 解决了上面所述的问题。

@Configuration@EnableWebMvc //启用 Spring MVC@ComponentScan("com.web")  //启用组件扫描public class WebConfig extends WebMvcConfigurerAdapter {    //配置视图解析器    @Bean    public ViewResolver viewResolver() {        InternalResourceViewResolver resolver = new InternalResourceViewResolver();        resolver.setPrefix("/WEB-INF/views/");        resolver.setSuffix(".jsp");        resolver.setExposeContextBeansAsAttributes(true);        return resolver;    }    //配置静态资源处理    @Override    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {        configurer.enable();    }}
原创粉丝点击