有多少种方法可以配置Spring框架? 技术上它们之间有什么区别? (不是利弊……)
我正在研究这本书(我强烈推荐),我很困惑作者如何解释Spring框架的配置方式。
您可以在此处查看本书中使用的一些代码示例。 (任何人都可以使用它们。)如果您想查看,我所指的代码将是第2章的代码。
无论如何,本书指出有三种配置Spring容器的方法 。
基于XML的配置
这将需要一个类似于下面的xml文件:
然后为了引导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的Annotation …
基于注释的配置
书中解释的最后一种配置方法是基于注释的配置 。
有一个xml文件,就像我们在基于XML的配置中一样,但是要小得多:
所有bean都有注释,例如:
@Component, @Service
等等..
并且所有依赖项都有注释:
@Autowired
这样可以注入豆类。
Spring框架在此配置方法中引导的方式如下:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/ch2-beans.xml");
这是我的问题:
为什么(所谓的) 基于注释的配置实际上使用的是ClassPathXmlApplicationContext而不是AnnotationConfigApplicationContext ? 后者似乎更适合在配置中使用,其中包含“基于注释”的字样,不是吗?
书中解释的基于Java的配置似乎应该称为基于注释的配置 。
在本书中解释的基于注释的配置实际上似乎是这样的:基于XML的配置与Autowired bean。 它甚至没有@Configuration注释,“基于Java的配置”具有…
有多少种方法可以配置Spring框架?
为避免混淆,我们应该理解, 配置定义和bean定义是两回事 。 定义配置有三种方法,默认情况下在Spring 4中可用:
- 基于xml的配置,在xml文件中描述配置时;
- 基于java的配置,当配置为Java类时,标记有特定的注释;
- 基于groovy的配置,当配置是带有Groovy代码的文件时;
有两种方法可以将bean定义添加到应用程序中:
-
在 bean定义中配置 ,当您通过配置中的声明手动添加bean时。
在这种情况下,定义将基于配置类型。 对于xml-config,它将是
标记,对于基于java的配置 – 带有@Bean
注释的方法和用于Groovy的beans {...}
构造。 -
基于注释的 bean定义,当您使用特定注释标记bean类时(如
@Component
,@Service
@Controller
,@Service
@Controller
等)。 这种类型的配置使用类路径扫描 。在这种情况下,您必须指定扫描类路径的指令。 对于xml-config,它将是
,用于java-config –@ComponentScan
注释,用于Groovyctx.'component-scan'(...)
调用。
如您所见,您可以使用不同组合的配置和bean定义。
请注意,如果使用基于xml的配置,则可以选择驱动依赖项注入的方法:手动在xml中,或使用注释(@ @Autowire
, @Required
等)。 在最后的情况下,您必须定义
。 但是不要混淆bean定义和dependency injection控制。
现在基于这个观点,我们可以尝试回答你的问题:
为什么(所谓的)基于注释的配置实际上使用的是ClassPathXmlApplicationContext而不是AnnotationConfigApplicationContext?
本书的作者混淆了概念。 实际上,这是一个基于xml的配置,带有基于注释的bean定义。
书中解释的基于Java的配置似乎应该称为基于注释的配置。
你是对的 – 基于Java的配置确实主动使用注释,可以称为基于注释。 但注释是Java的一部分。 此外,这是一个传统术语, 在文档中指定 。
有多少种方法可以配置Spring框架?
因此,默认情况下,我们有三种方式来描述配置,以及两种定义bean的方法。 这有六种方式来配置Spring框架(默认情况下)。 但是,当然,所有这些方式都可以相互结合使用。
理解这一点的最简单方法是研究框架的长期历史。
-
基于XML的配置 – 从头开始 – 版本1 – 请参阅ClassPathXmlApplicationContext的javadoc 。 这是在2004年3月左右,J2EE 1.4的时候,它有巨大的xml配置,Spring是大简化(XML也是,但更简单)。 这会将XML用于所有内容,包括指定自动assembly或直接依赖于哪些依赖项(您的ref =“accoundDao”示例)。
-
基于注释的配置 – 在Spring 2.5中 – 这是对Java EE 5的反应,引入了像@Autowired这样的新语言,在XML文件中仍然存在一些上下文配置 – 通常你会定义要扫描哪些包以及其余部分是基于注释自动完成的 – 因此得名。
-
Spring 3中提供了基于Java的配置,在以后的版本中进行了改进。 这是在引入AnnotationConfigApplicationContext和Configuration注释时 – 您可能完全删除XML – >基于java的配置。 虽然这只是后来版本4+才变得实用,因为aop,jdbc等有大量的xml帮助器标签。
除了这3个(实际上2个和2个使用相同的ApplicationContext类)之外,还有其他创建上下文的方法:
- 看看ApplicationContext接口的所有实现类
- 用于junit测试的SpringJUnit4ClassRunner
- 我打赌还有其他我不知道的方法
不完全是。 配置Spring框架只有两种方法。 Spring框架的两个基本配置工具是:
- XML文件(java文件外)
- 基于Java(5 +)的注释(在java文件中)
它们都可以用于:
- 配置应用程序上下文(意味着添加bean) – 具体应用程序上下文的构造函数接受xml文件,要扫描的包或直接命名的类以加载
- 在Web应用程序的情况下引导应用程序上下文 – 使用
web.xml
与使用实现WebApplicationInitializer
的类
最后但并非最不重要:
- 您可以使用
从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
@Controller
等)
现在为您提出准确的问题:
为什么(所谓的)基于注释的配置实际上使用的是ClassPathXmlApplicationContext而不是AnnotationConfigApplicationContext?
因为ApplicationContext首先从xml配置文件初始化。 稍后在
标签的帮助下进行包扫描。 如果直接从配置类或通过包扫描初始化它,则使用AnnotationConfigApplicationContext
。
书中解释的基于Java的配置似乎应该称为基于注释的配置。
他们称之为Java Based,因为它不需要xml,因此配置只使用Java
首先,我想感谢肯贝科夫提供的更有说服力的答案。 我试图即兴发表他的回答,这样任何人都可以在这方面了解更多。
配置定义:
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 (eg robot legs problem).
此外,它们不允许像处理自己的源一样处理外部类(库代码)。 因此,它们被认为比XML运行得更快。
xml文件的优点:
-
POJO与其行为之间的明确分离
-
当您不知道哪个POJO负责该行为时,更容易找到POJO(搜索文件的子集而不是所有源代码)
-
XML具有声明式样式的唯一优点,它与应用程序代码本身明确分开。 这与DI问题无关。 缺点是
verbosity
,poor re-factoring
robustness
poor re-factoring
和a general runtime failure
行为。 与IDE支持例如Java相比,只有一般的(XML)工具支持几乎没有什么好处。 除此之外,XML还带有性能开销,因此通常slower than code solutions
。
基于XML和注释的链接:
- http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-annotation-config
- 注释与XML,优点和缺点
- Javadependency injection:XML或注释
- 基于Spring注释的DI vs xml配置?
- Xml配置与基于注释的配置
基于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定义有两种方法:
扫描类路径:
对于xml-config ,它将是
, 用于java-config – @ComponentScan
注释,用于Groovy ctx.'component-scan'(...)
调用。
dependency injection:
在基于xml的配置中, dependency injection
可以在xml
手动完成,也可以使用annotations
(@Autowire,@ Required等)完成。 在这种情况下,需要定义
问与答:
Q1:为什么(所谓的)基于注释的配置实际上使用的是ClassPathXmlApplicationContext而不是AnnotationConfigApplicationContext?
Ans:它是一个基于xml的配置,带有基于注释的bean定义。
应用背景:
AnnotationConfigApplicationContext:
1. AnnotationConfigApplicationContext和父上下文
ClassPathXmlApplicationContext的:
- http://www.tutorialspoint.com/spring/spring_applicationcontext_container.htm
- http://www.mkyong.com/spring3/spring-3-hello-world-example/
Q2:书中解释的基于Java的配置似乎应该称为基于注释的配置。
答:你对那个案子说得对。 基于Java的配置使用注释,并称为基于注释的配置。 但注释是Java的一个部分,没有别的。
但是,我们需要详细了解这个层次结构是如何从基于xml到注释以及最后基于groovy的?
基于注释的配置提供了XML设置的替代方案,该配置依赖于字节码元数据来连接组件而不是角括号声明。 开发人员不是使用XML来描述bean连接,而是通过在相关的类,方法或字段声明上使用注释将配置移动到组件类本身。 正如在“示例:RequiredAnnotationBeanPostProcessor”一节中所提到的,将 BeanPostProcessor与注释结合使用是扩展Spring IoC容器的常用方法。 例如, Spring 2.0引入了使用@Required
注释强制执行所需属性的可能性。
Spring 2.5使得有可能采用相同的通用方法来驱动Spring的dependency injection。 从本质上讲,@ @Autowired
注释提供的function与第6.4.5节“自动assembly协作者”中描述的function相同,但具有更细粒度的控制和更广泛的适用性。
Spring 2.5还增加了对JSR-250注释的支持,例如@ @PostConstruct
和@PreDestroy
。
Spring 3.0增加了对javax.inject包中包含的JSR-330(Java的dependency injection)注释的支持,例如@Inject
和@Named
。 有关这些注释的详细信息,请参阅相关章节。
问题3:配置Spring框架有多少种方法?
答:
Theoretically,
3种描述配置的方法,以及2种定义bean的方法。 它变为3 * 2 = 6种方式来配置Spring框架(默认情况下)。 所有这些方式都可以相互结合使用。
But Actually,
简而言之,我们可以使用XML
或annotations
来配置spring框架。
我没有看过这本书,但你的假设实际上是正确的。
要启动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有2个弹簧容器:
1)BeanFactory 2)ApplicationContext
BeanFactory是最简单的容器,只接受一个配置文件。 ApplicationContext是最先进的Spring容器,用于企业应用程序,因为它接受一组配置文件,具有JNDI集成,EJB集成并支持消息的国际化。
我希望有所帮助。
首先让我先说明不同的编码:
- XML:您必须使用
在xml上下文文件中注册spring bean -
Java配置:您必须使用
@Configuration
和@Bean
在上下文中注册spring bean。 -
注释:通过使用
@Component
和它的朋友实际上常见的可以与其他2使用:- 在xml中使用
- 在java配置中使用
@ComponentScan
- 在xml中使用
为什么使用ClassPathXmlApplicationContext
因为他使用xml来配置组件扫描,但如果他使用@ComponentScan
那么肯定会使用AnnotationConfigApplicationContext
所以对我来说,我认为它是两种初始化spring context xml或java配置的方法,而Annotation is option可以被其中任何一个使用或根本不使用。
配置弹簧框架的三种方式根本不是互斥的。 实际上,我的猜测是,平均而言,你会发现它们中至少有两个一起使用。
基于注释的配置最不可能单独使用,仅仅因为它依赖于本质上分散在整个源代码中的元数据。
AnnotationConfigApplicationContext
可用于启动基于纯注释的上下文 ,但您需要传入所有注释为@Component
或派生@Component
,而不是传入一个(或几个) @Configuration
-annotated类( es) – 这通常是不实际的。
虽然这与在XML或Java配置中静态列出bean几乎相同,但是当您构建应用程序上下文时,您需要在代码中执行此操作,这使得它不太有用,因为您无法从中受益各种聪明的方法来自动启动应用程序上下文(在Web上下文等)。
这就是为什么你可能希望能够一次性组装完整的对象图元数据,而这只能通过XML或基于Java的配置来实现 ,这些配置依赖于描述整个对象图的“集中式”元数据。
对于基于XML和Java的方法,可以静态(使用显式
或@Bean
定义)或动态(使用
或@ComponentScan
)定义此“集中式元数据”(
或@Configuration
) 。 因此可以合理地说,这两种方法只是不同的格式,具有几乎相同的function,这些function都可以从基于注释的配置中受益,以收集“分散的”元数据。