我正在学习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框架?
答案 0 :(得分:40)
为避免混淆,我们应该了解,配置定义和 bean定义是两个不同的东西。有三种定义配置的方法,默认情况下在Spring 4中可用:
有两种方法可以将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种定义其配置的方法。他们是
注释的优点:
所有information is in a single file
(无需打开两个文件来配置给定的行为)
课程发生变化时,no need to modify the xml file
在重新分解应用程序代码时,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运行得更快。
xml文件的优点:
明确区分POJO及其行为
当您不知道哪个POJO负责该行为时,更容易找到POJO(搜索文件的子集而不是所有源代码)
XML具有声明式风格的唯一优点,它与应用程序代码本身明确分开。这与DI问题无关。缺点是verbosity
,poor re-factoring
robustness
和a general runtime failure
行为。与IDE支持相比,只有一般的(XML)工具支持几乎没有什么好处。 Java的。除此之外,XML还带有性能开销,因此通常为slower than code solutions
。
基于XML和注释的链接:
基于Groovy的链接:
Bean定义:
扫描类路径:
对于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定义。
申请背景:
<强> AnnotationConfigApplicationContext:强>
1。AnnotationConfigApplicationContext and parent context
<强>的ClassPathXmlApplicationContext:强>
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,
在一个单词中,我们可以使用XML
或annotations
来配置spring框架。
答案 3 :(得分:3)
不完全是。配置Spring框架只有两种方法。 Spring框架的两个基本配置工具是:
它们都可以用于:
web.xml
vs使用实现WebApplicationInitializer
的类最后但并非最不重要:
<context:component-scan/>
@import
您书中第二种称为<基于Java的配置的方式是一个特定的注释@Configuration
。用它注释的类通常是应用程序上下文中的bean,但它也可以在一个方法上声明具有@Bean
注释的其他bean。这就是为什么通常直接加载这些类而不是扫描bean的原因。
第三种称为基于注释的配置的方式,只是两种模式的混合,您可以在更高级别使用xml配置,只扫描其他bean的包。
TL / DR:在spring框架中只有两种方法来配置应用程序上下文:
他们可以混合
但是每个bean都可以用3种方式声明:
@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)
首先让我先说明编码的不同之处:
<bean/>
Java配置:您必须使用@Configuration
和@Bean
在上下文中注册spring bean。
注释:通过使用@Component
和其朋友实际上常见的可以与其他2使用:
<context:component-scan/>
@ComponentScan
为什么使用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;元数据。