有多少种方法可以配置Spring框架?技术上它们之间有什么区别? (不是利弊......)

时间:2016-03-04 22:13:38

标签: java xml spring

我正在学习this书(我强烈推荐),我对作者如何解释Spring框架的配置方式感到困惑。

您可以看到本书here中使用的一些代码示例。 (任何人都可以使用它们。)如果你想看一下,我所指的代码将是第2章的代码。

无论如何,本书指出有 3种配置Spring容器的方法

基于XML的配置

这将需要一个类似于以下内容的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ...>

    <bean id="accountService" class="com.wiley.beginningspring.ch2.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>

    <bean id="accountDao" class="com.wiley.beginningspring.ch2.AccountDaoInMemoryImpl">
    </bean>

</beans>

然后为了引导Spring,将使用的代码是:

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/com/wiley/beginningspring/ch2/ch2-beans.xml");

此刻我没有任何困惑。

基于Java的配置

在此Configuration方法中,将有一个配置类,如下所示:

@Configuration
public class Ch2BeanConfiguration {

    @Bean
    public AccountService accountService() {
        AccountServiceImpl bean = new AccountServiceImpl();
        bean.setAccountDao(accountDao());
        return bean;
    }

    @Bean
    public AccountDao accountDao() {
        AccountDaoInMemoryImpl bean = new AccountDaoInMemoryImpl();
        return bean;
    }
}

并且负责引导Spring的代码如下:

ApplicationContext applicationContext
            = new AnnotationConfigApplicationContext(Ch2BeanConfiguration.class);

所以到这里,对我来说一切都很清楚。 (有点......)我还要注意,这里我们实际上有一个名为@Configuration的注释......

基于注释的配置

本书中介绍的最后一种配置方法是基于注释的配置

有一个xml文件就像我们在基于XML的配置中一样,但是要小得多:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ...>
    <context:component-scan base-package="com.wiley.beginningspring.ch2"/>
</beans>

所有bean都有注释,例如:

@Component, @Service

等。

所有依赖项都有注释:

@Autowired

以便可以注入豆类。

Spring框架在此配置方法中引导的方式如下:

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/ch2-beans.xml");

以下是我的问题:

为什么(所谓的)基于注释的配置实际上使用 ClassPathXmlApplicationContext 而不是上面的 AnnotationConfigApplicationContext ?后者似乎更适合用于其中包含“基于注释”字样的配置,不是吗?

本书中解释的基于Java的配置似乎应该称为基于注释的配置。?

本书中解释的基于注释的配置实际上似乎是这样的:基于XML的配置与Autowired bean。它甚至没有@Configuration注释,“Java Based Configuration”具有..

有多少种方法可以配置Spring框架?

7 个答案:

答案 0 :(得分:40)

为避免混淆,我们应该了解,配置定义 bean定义是两个不同的东西。有三种定义配置的方法,默认情况下在Spring 4中可用:

  • 基于xml的配置,在xml文件中描述配置时;
  • 基于java的配置,当配置为Java类时,标有特定注释;
  • 基于groovy的配置,当配置为包含Groovy代码的文件时;

有两种方法可以将bean定义添加到应用程序中:

  • 配置 bean定义中的配置,当您通过配置中的声明手动添加bean时。

    在这种情况下,定义将基于配置类型。对于xml-config,它将是<bean/>标记,用于基于java的配置 - 带有@Bean注释的方法和用于Groovy的beans {...}构造。

  • 当您使用特定注释(例如@Component@Service@Controller等)标记bean类时,
  • 基于注释的 bean定义。此类配置使用classpath scanning

    在这种情况下,您必须指定扫描类路径的指令。对于xml-config,对于Groovy <context:component-scan base-package="..."/>调用,对于java-config - @ComponentScan注释,它将是ctx.'component-scan'(...)

如您所见,您可以使用不同组合的配置和bean定义。

请注意,如果您使用基于xml的配置,则可以选择驱动依赖项注入的方法:手动在xml中,或使用注释(@Autowire@Required等)。在最后的情况下,您必须定义<context:annotation-config/>。但是不要混淆bean定义和依赖注入控制。

现在基于这个观点,我们可以尝试回答你的问题:

  

为什么(所谓的)基于注释的配置实际使用   ClassPathXmlApplicationContext但不是   上面的AnnotationConfigApplicationContext?

Book&#39>作者将概念混为一谈。实际上,这是一个基于xml的配置,带有基于注释的bean定义。

  

书中解释的基于Java的配置似乎是什么   应该称为基于注释的配置。?

你是对的 - 基于Java的配置确实主动使用注释,可以称为基于注释。但是注释是Java的一部分。此外,这是一个传统术语specified in documentation

  

有多少种方法可以配置Spring框架?

因此,默认情况下,我们有三种方式来描述配置,以及两种定义bean的方法。这有六种方式来配置Spring框架(默认情况下)。但是,当然,所有这些方式都可以相互结合使用。

答案 1 :(得分:9)

理解这一点的最简单方法是研究框架的长期历史。

  • 基于XML的配置 - 从头开始​​ - 版本1 - 请参阅javadoc for ClassPathXmlApplicationContext。这是在2004年3月左右,J2EE 1.4的时候,它有巨大的xml配置,Spring是大简化(XML也是,但更简单)。这会将XML用于所有内容,包括指定自动装配,或直接在哪里使用依赖项(您的ref =&#34; accoundDao&#34;示例)。

  • 基于注释的配置 - 在Spring 2.5中 - 这是对Java EE 5的反应,引入了诸如@Autowired之类的新语言,在XML文件中仍然存在一些上下文配置 - 通常你会定义哪个软件包将被扫描,其余部分将根据注释自动完成 - 因此得名。

  • 基于Java的配置随Spring 3一起提供,在以后的版本中得到了改进。这是在引入AnnotationConfigApplicationContext和配置注释时 - 您可能完全删除XML - &gt;基于java的配置。虽然这只是后来版本4+才变得实用,因为aop,jdbc等的大量xml帮助器标签。

除了这3个(实际上2个和2个使用相同的ApplicationContext类)之外,还有其他创建上下文的方法:

答案 2 :(得分:4)

首先,我要感谢 Ken Bekov ,感谢他提供了更加智慧的答案。我试图即兴发表他的回答,这样任何人都可以在这方面了解更多。

  

配置定义:

Spring 4包含3种定义其配置的方法。他们是

enter image description here

注释的优点:

  1. 所有information is in a single file(无需打开两个文件来配置给定的行为)

  2. 课程发生变化时,no need to modify the xml file

  3. 在重新分解应用程序代码时,Annoations通常被认为更直观,更健壮。他们也受益于像guise提供的更好的IDE指导。但他们将应用程序代码与DI问题混在一起应用程序依赖于框架。清除分离几乎是不可能的。 Annotations are also limited when describing different injection behaviour at the same place (constructor, field) dependent on other circumstances (e.g. robot legs problem).此外,他们不允许像对待自己的来源一样对待外部类(库代码)。因此,它们被认为比XML运行得更快。

  4. xml文件的优点:

    1. 明确区分POJO及其行为

    2. 当您不知道哪个POJO负责该行为时,更容易找到POJO(搜索文件的子集而不是所有源代码)

    3. XML具有声明式风格的唯一优点,它与应用程序代码本身明确分开。这与DI问题无关。缺点是verbositypoor re-factoring robustnessa general runtime failure行为。与IDE支持相比,只有一般的(XML)工具支持几乎没有什么好处。 Java的。除此之外,XML还带有性能开销,因此通常为slower than code solutions

    4. 基于XML和注释的链接:

      1. http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-annotation-config
      2. Annotations vs XML, advantages and disadvantages
      3. Java Dependency injection: XML or annotations
      4. Spring annotation-based DI vs xml configuration?
      5. Xml configuration versus Annotation based configuration
      6. 基于Groovy的链接:

        1. https://objectpartners.com/2016/01/12/using-groovy-based-spring-configuration/
        2. http://blog.andresteingress.com/2014/02/14/grails-java-based-spring-config/
        3.   

          Bean定义:

          bean定义有两种方法: enter image description here

          扫描类路径:

          对于xml-config ,对于Groovy <context:component-scan base-package="..."/>调用,它将是@ComponentScan用于java-config - ctx.'component-scan'(...)注释

          依赖注入:

          在基于xml的配置中,dependency injection可以在xml中手动完成,也可以使用annotations(@Autowire,@ Required等)完成。在这种情况下,需要定义<context:annotation-config/>

          问题&amp;回答:

            

          Q1:为什么(所谓的)基于注释的配置实际上使用了ClassPathXmlApplicationContext但没有   上面的AnnotationConfigApplicationContext?

          Ans:这是一个基于xml的配置,带有基于注释的bean定义。

          申请背景:

          1. http://docs.spring.io/spring/docs/4.2.0.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html
          2. <强> AnnotationConfigApplicationContext:

            1。AnnotationConfigApplicationContext and parent context

            <强>的ClassPathXmlApplicationContext:

            1. http://www.tutorialspoint.com/spring/spring_applicationcontext_container.htm
            2. http://www.mkyong.com/spring3/spring-3-hello-world-example/
            3.   

              Q2:本书中解释的基于Java的配置似乎应该称为基于注释的配置。

              答案:你是对的。基于Java的配置使用注释,并称为基于注释的配置。但注释是Java的一个部分,没有别的。

              但是我们需要详细了解这个层次结构是如何从xml到基于注释的,最后是基于Groovy的?

              基于注释的配置提供了XML设置的替代方案,该配置依赖于字节码元数据来连接组件而不是角括号声明。开发人员不是使用XML来描述bean连接,而是通过在相关的类,方法或字段声明上使用注释将配置移动到组件类本身。 As mentioned in the section called “Example: The RequiredAnnotationBeanPostProcessor”,将BeanPostProcessor与注释结合使用是扩展Spring IoC容器的常用方法。 例如, Spring 2.0 引入了使用@Required注释强制执行所需属性的可能性。

              Spring 2.5 使得有可能采用相同的通用方法来驱动Spring的依赖注入。从本质上讲,@Autowired注释提供了与Section 6.4.5, “Autowiring collaborators”中描述的相同的功能,但具有更细粒度的控制和更广泛的适用性。

              Spring 2.5 还添加了对@PostConstruct@PreDestroy等JSR-250注释的支持。

              Spring 3.0 添加了对javax.inject包中包含的JSR-330(Java的依赖注入)注释的支持,例如@Inject@Named。有关这些注释的详细信息,请参阅relevant section.

                

              问题3:配置Spring框架的方式有多少?

              答案

              Theoretically, 3种描述配置的方法,以及2种定义bean的方法。它变为3 * 2 = 6种方式来配置Spring框架(默认情况下)。所有这些方法都可以相互结合使用。

              But Actually,在一个单词中,我们可以使用XMLannotations来配置spring框架。

答案 3 :(得分:3)

不完全是。配置Spring框架只有两种方法。 Spring框架的两个基本配置工具是:

  • XML文件(java文件外)
  • 基于Java(5 +)的注释(在java文件中)

它们都可以用于:

  • 配置应用程序上下文(意味着添加bean) - 具体应用程序上下文的构造函数接受xml文件,要扫描的包或直接命名要加载的类
  • 在Web应用程序的情况下引导应用程序上下文 - 使用web.xml vs使用实现WebApplicationInitializer的类

最后但并非最不重要:

  • 您可以使用<context:component-scan/>
  • 从xml配置文件中扫描注释
  • 您可以使用@import
  • 从带注释的配置bean加载xml文件

您书中第二种称为<基于Java的配置的方式是一个特定的注释@Configuration。用它注释的类通常是应用程序上下文中的bean,但它也可以在一个方法上声明具有@Bean注释的其他bean。这就是为什么通常直接加载这些类而不是扫描bean的原因。

第三种称为基于注释的配置的方式,只是两种模式的混合,您可以在更高级别使用xml配置,只扫描其他bean的包。

TL / DR:在spring框架中只有两种方法来配置应用程序上下文:

  • xml配置文件
  • java annotations

他们可以混合

但是每个bean都可以用3种方式声明:

  • 来自xml文件
  • @Bean带注释的bean
  • 中包含@Configuration注释
  • 直接使用@Component(或任何专业注释@Controller@Service等)

现在提出您的确切问题:

  

为什么(所谓的)基于注释的配置实际上使用了ClassPathXmlApplicationContext而不是上面的AnnotationConfigApplicationContext?

因为ApplicationContext首先从xml配置文件初始化。稍后在<context:scan ...>标记的帮助下进行包扫描。如果直接从配置类或通过包扫描初始化它,则使用AnnotationConfigApplicationContext

  

本书中解释的基于Java的配置似乎应该称为基于注释的配置。?

他们称之为基于Java 因为它不需要xml所以配置只使用Java

答案 4 :(得分:1)

我没有看过这本书,但你的假设实际上是正确的。

要启动Spring应用程序并使用XML配置的bean实现框架实例化的所有bean,必须使用ClassPathXmlApplicationContext。

在Spring中有两种配置bean的方法:

1)XML bean 2)注释方法

基本上,Spring bean在Spring 2.5-3中使用,而Annotations方法在Spring 4中使用得更多。

@Bean // is a way to create a bean. It is the equalivant of the beans tag in XML.

@Configuration // is a way to tell the Spring container that this class is a list of configuration beans

Spring有两个弹簧容器:

1)BeanFactory 2)ApplicationContext

BeanFactory是最简单的容器,只接受一个配置文件。 ApplicationContext是最先进的Spring容器,用于企业应用程序,因为它接受一组配置文件,具有JNDI集成,EJB集成并支持消息的国际化。

我希望有所帮助。

答案 5 :(得分:1)

首先让我先说明编码的不同之处:

  1. XML:您必须使用<bean/>
  2. 在xml上下文文件中注册spring bean
  3. Java配置:您必须使用@Configuration@Bean在上下文中注册spring bean。

  4. 注释:通过使用@Component和其朋友实际上常见的可以与其他2使用:

    1. 在xml中使用<context:component-scan/>
    2. 在java配置中使用@ComponentScan
  5. 为什么使用ClassPathXmlApplicationContext因为他使用xml来配置组件扫描,但是如果他使用@ComponentScan那么肯定会使用AnnotationConfigApplicationContext

    所以对我来说,我认为它是初始化spring context xml或java配置的两种方法,而Annotation is option可以被其中任何一个使用或根本不使用。

答案 6 :(得分:1)

配置弹簧框架的三种方式根本不是互斥的。实际上,我的猜测是,你会发现至少有两个一起使用。

基于注释的配置最不可能单独使用,仅仅因为它依赖于本质上分散在整个源代码中的元数据。

AnnotationConfigApplicationContext 可用于启动基于注释的上下文,但您需要传入所有类< / em>注释为@Component或衍生词,而不是传入一个(或几个)@Configuration - 带注释的类 - 这通常是不实际的。

虽然这与静态列出XML或Java配置中的bean几乎相同,但是当您构建应用程序上下文时,您需要在代码中执行此操作这一事实使得它不那么有用,因为您可以& #39;自动启动应用程序上下文的各种聪明方法的好处(在Web上下文等)。

这就是为什么你可能希望能够一次性组装完整的对象图元数据,以及只能通过XML或基于Java的配置实现的,这依赖于&#34;集中化&#34;描述整个对象图的元数据。

对于基于XML和Java的方法,这个&#34;集中式元数据&#34; (<beans>@Configuration)可以静态定义(使用明确的<bean>@Bean定义)或动态定义(使用<component-scan>@ComponentScan)。因此,可以合理地说这两种方法只是不同的格式,具有几乎相同的功能,这些功能都可以从基于注释的配置中受益,以便收集&#34;去集中化&#34;元数据。