Spring框架有几种配置方式?它们在技术上有何区别? (不是优点或缺点..)

Posted

技术标签:

【中文标题】Spring框架有几种配置方式?它们在技术上有何区别? (不是优点或缺点..)【英文标题】:How many ways are there to configure the Spring framework? What are the differences between them technically? (Not pros or cons..) 【发布时间】:2016-06-18 20:06:33 【问题描述】:

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

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

书中指出有3种配置Spring Container的方法


基于 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都有Annotations,例如:

@Component, @Service

等等。

并且所有的依赖都有注解:

@Autowired

这样可以注入bean。

该配置方式中Spring框架的自举方式如下:

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

这是我的问题:

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

书中解释的Java Based Configuration似乎应该叫做Annotation Based Configuration。?

书中解释的基于注释的配置方式在我看来实际上类似于:使用自动装配 bean 的基于 XML 的配置。它甚至没有“基于 Java 的配置”所具有的 @Configuration 注释。

Spring框架有几种配置方式?

【问题讨论】:

一本书中说有三种方式的陈述如何导致一个关于有多少种方式的问题? 典型的方法是 XML、注释、Grails DSL 和手动。都有其优点和缺点。目前,注释是首选方式,但大多数使用库的示例仍将通过 XML。我见过至少一种情况,Grails DSL 解决了基于注释的配置在大型系统中耗时过长的问题。我喜欢 Grails DSL,但如果您对 Spring 和 Groovy 不太了解,可能会感到困惑。手动更多的是示例代码。 正如我在上面看到的那样?我在您的问题中看不到任何与有多少种方式有关的内容。我看到了一些问题,即为什么特定的方法会以它们的方式实现,应该向实现者提出,并且与实际存在多少种方法无关。不清楚你在问什么。 【参考方案1】:

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

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

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

1) XML bean 2)注解方式

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

@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 有 2 个弹簧容器:

1) 豆工厂 2) 应用上下文

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

希望对你有帮助。

【讨论】:

【参考方案2】:

让我先展示一下编码的不同:

    XML:你必须使用&lt;bean/&gt;在xml上下文文件中注册你的spring bean

    Java 配置:您必须使用@Configuration@Bean 在上下文中注册您的spring bean。

    注解:通过使用@Component和它的朋友其实很常见可以和其他2个使用一起使用:

      在xml中使用&lt;context:component-scan/&gt; 在java配置中使用@ComponentScan

为什么用ClassPathXmlApplicationContext,因为他用xml配置组件扫描,但如果他用@ComponentScan那肯定用AnnotationConfigApplicationContext

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

【讨论】:

【参考方案3】:

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

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

它们都可以用于:

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

最后但同样重要的是:

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

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

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


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

xml配置文件 java 注释

它们可以混合使用

但每个 bean 都可以通过 3 种方式声明:

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

现在回答您的具体问题:

为什么(所谓的)Annotation Based Configuration 实际使用的是 ClassPathXmlApplicationContext 而不是上面的 AnnotationConfigApplicationContext?

因为 ApplicationContext 首先是从一个 xml 配置文件初始化的。稍后在&lt;context:scan ...&gt; 标签的帮助下进行包扫描。如果您直接从配置类或通过包扫描初始化它,则使用AnnotationConfigApplicationContext

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

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

【讨论】:

【参考方案4】:

了解这一点的最简单方法是查看框架的悠久历史是如何开发的。

基于 XML 的配置 - 从一开始就存在 - 版本 1 - 请参阅 javadoc for ClassPathXmlApplicationContext。那是在 2004 年 3 月左右,J2EE 1.4 的时候,它有大量的 xml 配置,Spring 进行了很大的简化(XML 也是如此,但更简单)。这对所有内容都使用了 XML,包括指定自动装配,或直接去哪里的依赖项(您的 ref="accoundDao" 示例)。

1234563被扫描,其余部分是根据注释自动完成的——因此得名。

基于 Java 的配置随 Spring 3 一起提供,在以后的版本中得到了改进。这是在 AnnotationConfigApplicationContext 和 Configuration 注释被引入的时候 - 你可能会完全删除 XML -> 基于 java 的配置。虽然这只是在版本 4+ 之后才变得实用,因为 aop、jdbc 等的大量 xml 辅助标记。

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

看看ApplicationContext接口的所有实现类 SpringJUnit4ClassRunner 用于 junit 测试 我敢打赌还有其他我不知道的方法

【讨论】:

很好的解释谢谢。 历史视图是一个不错的视图,尤其是对于 Spring 的新手【参考方案5】:

为避免混淆,我们应该理解,配置定义bean定义是两个不同的东西。 Spring 4默认提供三种定义配置的方式:

基于xml的配置,当你在xml文件中描述配置时; 基于java的配置,当配置为Java类时,用具体的注解标注; 基于groovy的配置,当配置是带有Groovy代码的文件时;

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

内部配置 bean 定义,当您在配置中通过声明手动添加 bean 时。

在这种情况下,定义将基于配置类型。对于 xml-config,它将是 &lt;bean/&gt; 标签,对于基于 java 的配置 - 带有 @Bean 注释的方法和对于 Groovy 的 beans ... 构造。

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

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

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

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

现在基于这个观点让我们试着回答你的问题:

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

本书的作者混淆了概念。实际上,这是一个基于 xml 的配置,带有基于注解的 bean 定义。

书中解释的基于 Java 的配置看起来像 应该叫 Annotation Based Configuration。?

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

Spring框架有几种配置方式?

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

【讨论】:

还有 让一切变得更加混乱,对吧? yml 的一种配置方式吗? @JasonS No. yml 文件如properties 文件用于外部化某些应用程序属性。但是你不能在yml中声明bean。 @KenBekov 我在文档中遇到了这个短语“spring-context 是一种以类似于 JNDI 注册表的框架样式方式访问对象的方法。”这是什么意思? @Rushino 这完全取决于你。但是查看官方文档,根据我这些天的经验,大多数开发人员选择基于 Java 的配置来进行 Spring 应用程序。【参考方案6】:

首先,我要感谢 Ken Bekov 提供了更足智多谋的回答。我试图即兴回答他,以便任何人都可以了解这方面的更多信息。

配置定义:

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

注释的优点:

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

    类变化时,no need to modify the xml file

    在重构应用程序代码时,通常认为注解更加直观和健壮。他们还受益于 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 运行得更快。

xml文件的优点:

    POJO 与其行为之间的明确区分

    当你不知道哪个 POJO 对行为负责时,更容易找到那个 POJO(在文件的子集而不是所有源代码中搜索)

    XML 具有声明式风格的唯一好处,这种风格的定义与应用程序代码本身明确分离。这与 DI 问题无关。缺点是verbositypoor re-factoringrobustnessa general runtime failure 行为。与 IDE 支持相比,只有一个通用 (XML) 工具支持几乎没有好处,例如爪哇。此外,此 XML 会带来性能开销,因此通常为 slower than code solutions

基于 XML 和注释的链接:

    http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-annotation-config Annotations vs XML, advantages and disadvantages Java Dependency injection: XML or annotations Spring annotation-based DI vs xml configuration? Xml configuration versus Annotation based configuration

基于 Groovy 的链接:

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

Bean 定义:

bean定义有2种方式:

扫描类路径:

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

依赖注入:

在基于 xml 的配置中,dependency injection 可以在 xml 中手动完成,或者通过使用 annotations(@Autowire、@Required 等)来完成。这种情况下需要定义&lt;context:annotation-config/&gt;

问答:

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

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

应用程序上下文:

    http://docs.spring.io/spring/docs/4.2.0.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html

AnnotationConfigApplicationContext:

1.AnnotationConfigApplicationContext and parent context

ClassPathXmlApplicationContext:

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

Q2:书中解释的基于Java的配置,看起来应该叫Annotation Based Configuration。?

回答:你说得对。基于 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 还添加了对 JSR-250 注释的支持,例如 @PostConstruct@PreDestroy

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

Q3:Spring框架有几种配置方式?

回答:

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

But Actually,一句话,我们可以使用XML或者annotations来配置spring框架。

【讨论】:

我很高兴你复制了我的答案)【参考方案7】:

三种配置spring框架的方式根本不是相互排斥的。实际上,我的猜测是,平均而言,您会发现其中至少有两个一起使用。

基于注释的配置最不可能独立使用,因为它依赖于固有地分散在整个源代码中的元数据。

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

虽然这与在 XML 或 Java 配置中静态列出 bean 几乎相同,但是当您构建应用程序上下文本身时需要在代码中执行此操作这一事实使其不太有用,因为您不能自动启动应用程序上下文(在 Web 上下文等中)的各种巧妙方法的好处。

这就是为什么您可能希望能够一次性组装完整的对象图元数据,而这只能通过基于 XML 或 Java 的配置来实现,它们依赖于“集中”描述整个对象图的元数据。

对于基于 XML 和 Java 的方法,这种“集中式元数据”(&lt;beans&gt;@Configuration)可以静态定义(使用显式 &lt;bean&gt;@Bean 定义)或动态定义(使用 &lt;component-scan&gt;@ComponentScan)。因此可以合理地说,这两种方法只是不同的格式,具有几乎相同的功能,它们都可以受益于基于注释的配置来收集“去中心化”元数据。

【讨论】:

以上是关于Spring框架有几种配置方式?它们在技术上有何区别? (不是优点或缺点..)的主要内容,如果未能解决你的问题,请参考以下文章

XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

spring管理java类有几种方式

Spring 创建Bean的几种形式

spring装配bean有几种方式?

12、注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。

spring自动装配有几种方式