版本约定
本文内容若没做特殊说明,均基于以下版本:
- JDK:1.8
- Spring Framework:5.2.2.RELEASE
正文
最初的Spring只支持xml方式配置Bean,从Spring 3.0起支持了一种更优的方式:基于Java类的配置方式,这一下子让我们Javaer可以从标签语法里解放了出来。毕竟作为Java程序员,我们擅长的是写Java类,而非用标签语言去写xml文件。
我对Spring配置的Full/Lite模式的关注和记忆深刻,源自于一个小小故事:某一年我在看公司的项目时发现,数据源配置类里有如下一段配置代码:
@Configuration public class DataSourceConfig { ... @Bean public DataSource dataSource() { ... return dataSource; } @Bean(name = "transactionManager") public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } ... }
作为当时还是Java萌新的我,非常的费解。自然的对此段代码产生了较大的好奇(其实是质疑):在准备DataSourceTransactionManager这个Bean时调用了dataSource()方法,根据我“非常扎实”的JavaSE基础知识,它肯定会重新走一遍dataSource()方法,从而产生一个新的数据源实例,那么你的事务管理器管理的不就是一个“全新数据源”麽?谈何事务呢?
为了验证我的猜想,我把断点打到dataSource()方法内部开始调试,但让我“失望”的是:此方法并没有执行两次。这在当时是震惊了我的,甚至一度怀疑自己引以为豪的Java基础了。所以我四处询问,希望得到一个“解释”,但奈何,问了好几圈,那会没有一人能给我一个合理的说法,只知道那么用是没有问题的。
基本概念
关于配置类的核心概念,在这里先予以解释。
@Configuration和@Bean
Spring新的配置体系中最为重要的构件是:@Configuration
标注的类,@Bean
标注的方法。
// @since 3.0 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor(annotation = Component.class) String value() default ""; // @since 5.2 boolean proxyBeanMethods() default true; }
用@Configuration
注解标注的类表明其主要目的是作为bean定义的源。此外,@Configuration
类允许通过调用同一类中的其他@Bean
method方法来定义bean之间的依赖关系(下有详解)。
// @since 3.0 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Bean { @AliasFor("name") String[] value() default {}; @AliasFor("value") String[] name() default {}; @Deprecated Autowire autowire() default Autowire.NO; // @since 5.1 boolean autowireCandidate() default true; String initMethod() default ""; String destroyMethod() default AbstractBeanDefinition.INFER_METHOD; }
@Bean注解标注在方法上,用于指示方法实例化、配置和初始化要由Spring IoC容器管理的新对象。对于熟悉Spring的<beans/>XML配置的人来说,@Bean注解的作用与<bean/>元素相同。您可以对任何Spring的@Component组件使用@Bean注释的方法代替(注意:这是理论上,实际上比如使用@Controller标注的组件就不能直接使用它代替)。
需要注意的是,通常来说,我们均会把@Bean标注的方法写在@Configuration标注的类里面来配合使用。
简单粗暴理解:@Configuration标注的类等同于一个xml文件,@Bean标注的方法等同于xml文件里的一个<bean/>标签