[Spring] 基于 Java 的配置

本文介绍了Spring框架中的Java配置方式,对比XML配置,JavaConfig提供了更强大的类型安全和重构支持。文章详细讲解了@Configuration和@Bean注解的使用方法,并演示了如何通过JavaConfig实现bean的注入。此外,还介绍了如何使用JavaConfig配置Spring Web应用,包括DispatcherServlet的配置及Spring MVC的启用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

基本概念:@Configuration 和 @Bean

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

看一个例子:

@Configuration
public 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 的可行方案:

@Bean
public MyApp myApp() {
    return new MyApp(myService());
}

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

@Bean
public 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
@EnableWebMvc
public 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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值