序言
Spring @Configuration是一个类级别的注解,用于声明一个Java类为Spring容器所管理的配置类,并在类中声明和定义一个或多个Bean方法。与此同时,@Configuration还可以与其他类级别的注解搭配使用,例如:
- @PropertySource: 将属性配置源添加到Spring的应用环境中
- @Profile:根据不同条件启用特定的配置类
- @EnableScheduling: 启用Spring的定时任务
- @ImportResource: 导入一个或多个配置Bean的资源文件
- @Import: 导入一个或多个配置类
- @ComponentScan: 配置组件扫描指令
- @EnableWebMvc: 提供SPring MVC配置
- @EnableWebSecurity: 提供Spring Security配置
本节内容
- 使用@Configuration注解
- @Configuration和@Autowired
- @Configuration和@PropertySource
- @Configuration和@Profile
- @Configuration和@EnableScheduling
- @Configuration和@ImportResource
- @Configuration和@Import
- @Configuration和@ComponentScan
1.使用@Configuration注解
与往常一样,创建一个AppConfig类,使用@Configuration进行注解,并在类内部使用@Bean注解一个bean方法。
AppConfig.java
@Configurationpublic class AppConfig { @Bean("user") public UserBean userBean(){ return new UserBean("树下魅狐"); }}
接下来,创建一个名为UserBean的Java类,并在main()方法中通过AnnotationConfigApplicationContext获取userBean。
UserBean.java
public class UserBean { private String username; public UserBean(String username){ this.username = username; System.out.println("Initializing UserBean and username is :"+this.username); } public String getUsername(){ return this.username; }}
ConfigurationAnnotationApplication.java
@SpringBootApplicationpublic class ConfigurationAnnotationApplication { public static void main(String[] args) { SpringApplication.run(ConfigurationAnnotationApplication.class, args); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserBean user = (UserBean) context.getBean("user"); System.out.println("user`s username = "+user.getUsername()); }}
Output
Initializing UserBean and username is :树下魅狐user`s username = 树下魅狐
2. @Configuration和@Autowired
在@Configuration注解的类中,可以使用@Autowired注解将外部化的值或者其他的Bean注入其中。例如,我们可以使用@Autowired将Spring的Environment注入到配置类中。
AppConfig.java
@Configurationpublic class AppConfig { @Autowired private Environment environment; @Bean("user") public UserBean userBean(){ System.out.println(environment.getProperty("java.home")); return new UserBean("树下魅狐"); }}
在代码中,通过environment获得java的home路径。
Output
C:Program FilesJavajdk1.8.0_221jreInitializing UserBean and username is :树下魅狐user`s username = 树下魅狐
3. @Configuration和@PropertySource
@PropertySource注解为我们提供了一种便捷的方式将外部的配置文件属性值配置到Spring的环境中。我们可以在@Configuration注解的类上使用@PropertySource读取配置文件,并在类中使用@Value获得配置文件中属性值。首先,在类路径下创建一个名为app.properties的配置文件内容如下:
app.properties
author.email=ramostear@163.comauthor.site=https://www.ramostear.com
接下来,修改AppConfig.java文件,使用@PropertySource加载application.properties文件,并在类中使用@Value读取配置项的值。
AppConfig.java
@Configuration@PropertySource(value = "classpath:app.properties")public class AppConfig { @Value("${author.email}") private String email; @Value("${author.site}") private String site; @Autowired private Environment environment; @Bean("user") public UserBean userBean(){ System.out.println(environment.getProperty("java.home")); System.out.println("Author email:"+email); System.out.println("Author site:"+site); return new UserBean("树下魅狐"); }}
再次运行main()方法,观察控制台输出。
Output
C:Program FilesJavajdk1.8.0_221jreAuthor email:ramostear@163.comAuthor site:https://www.ramostear.comInitializing UserBean and username is :树下魅狐user`s username = 树下魅狐
4 @Configuration和@Profile
@Profile是一个很有用的注解,它允许我们根据Spring ActiveProfile的值注册不同的配置文件。例如,在软件开发过程中,我们可以根据项目进展情况,为项目定义不同的配置,如开发用的配置,测试用的配置以及生产环境用的配置等等。在此例子中,我们通过@Profile新增两个配置类DevAppConfig.java和TestAppConfig.java,并在AppConfig.java类上加入@Profile注解。
DevAppConfig.java
@Profile("dev")@Configurationpublic class DevAppConfig { @Bean public UserBean userBean(){ return new UserBean("谭朝红"); }}
TestAppConfig.java
@Profile("test")@Configurationpublic class TestAppConfig { @Bean public UserBean userBean(){ return new UserBean("ramostear"); }}
AppConfig.java
@Profile("prod")@Configuration@PropertySource(value = "classpath:app.properties")public class AppConfig { //...}
接下来,修改main()中的代码,并启用dev的配置。
main()
public static void main(String[] args) { SpringApplication.run(ConfigurationAnnotationApplication.class, args); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //不指定配置类 context.getEnvironment().setActiveProfiles("dev"); //通过profile切换 context.scan("com.ramostear.configuration.annotation"); context.refresh(); UserBean user = context.getBean(UserBean.class); System.out.println(user.getUsername()); context.close(); }
Output
Initializing UserBean and username is :谭朝红谭朝红
现在,将profile切换到test,观察控制台输出。
main()
context.getEnvironment().setActiveProfiles("test");
Output
Initializing UserBean and username is :ramostearramostear
最后,将profile切回到prod。
main()
context.getEnvironment().setActiveProfiles("prod");
Output
C:Program FilesJavajdk1.8.0_221jreAuthor email:ramostear@163.comAuthor site:https://www.ramostear.comInitializing UserBean and username is :树下魅狐树下魅狐
补充
除了上述的方法外,还可以使用System.setProperty()方法设置profile。代码如下:
System.setProperty("spring.profiles.active","prod");
5. @Configuration和@EnableScheduling
在Spring中,@Configuration和@EnableScheduling注解搭配,可以开启Spring的定时任务功能,并使用@Scheduled注解定义定时任务。请看下面的例子:
DemoTask.java
public class DemoTask { private int num = 0; private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Scheduled(fixedRate = 1000) public void task(){ System.out.println(sdf.format(new Date())+": number = "+(++num)); }}
DemoTask.java任务比较简单,每个一秒输出当前时间和num累加的结果。接下来,在AppConfig.java中开启定时任务,并配置DemoTask bean。
AppConfig.java
@Profile("prod")@Configuration@PropertySource(value = "classpath:app.properties")@EnableSchedulingpublic class AppConfig { //省略其他... @Bean public DemoTask demoTask(){ return new DemoTask(); }}
Output
2020-03-27 06:12:53.048 INFO 7652 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler'2020-03-27 06:12:53: number = 12020-03-27 06:12:54: number = 22020-03-27 06:12:55: number = 32020-03-27 06:12:56: number = 42020-03-27 06:12:57: number = 52020-03-27 06:12:58: number = 62020-03-27 06:12:59: number = 72020-03-27 06:13:00: number = 82020-03-27 06:13:01: number = 92020-03-27 06:13:02: number = 10
6.@Configuration 和 @ImportResource
Spring允许我们使用@ImportResource注解导入Spring的XML配置文件。Spring现在推荐使用Java代码的配置方式,但还是给喜好使用XML配置文件的开发者提供了通道。请看示例:
app.xml
<?xml version="1.0" encoding="UTF-8"?>
接下来,在AppConfig.java文件中使用@ImportResource注解导入app.xml配置。
AppConfig.java
@Profile("prod")@Configuration@PropertySource(value = "classpath:app.properties")@EnableScheduling@ImportResource(value = "classpath:app.xml")public class AppConfig { //省略...}
在main()方法中获取unaBoot 并打印username的值。
main()
public static void main(String[] args) { SpringApplication.run(ConfigurationAnnotationApplication.class, args); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("prod"); context.scan("com.ramostear.configuration.annotation"); context.refresh(); UserBean unaBoot = (UserBean) context.getBean("unaBoot"); System.out.println("app.xml config bean :"+ unaBoot.getUsername()); }
Output
Initializing UserBean and username is :unaBootunaBootapp.xml config bean :unaBoot
7. @Configuration 和 @Import
我们可以使用@Import将一个或多个被@Configuration注解的配置类导入了一个类当中。这是个不错的操作,可以将多个配置类聚合到一个类中。请看示例:
OtherAppConfig.java
@Configurationpublic class OtherAppConfig { @Bean public OtherBean otherBean(){ return new OtherBean(); }}
在AppConfig.java文件导入OtherAppConfig配置,main()方法中的代码保持不变,内容如下:
@Profile("prod")@Configuration@PropertySource(value = "classpath:app.properties")@EnableScheduling@ImportResource(value = "classpath:app.xml")@Import(OtherAppConfig.class)public class AppConfig { //省略其他...}
OtherBean.java
public class OtherBean { public OtherBean(){ System.out.println("Initializing other bean ...."); }}
Output
Initializing other bean ....
8. @Configuration 和@ComponentScan
@ComponentScan注解的作用是根据指定的包路径或者类,对组件进行扫描并完成自动装配工作。在前面的章节中已有介绍,在此不再赘述。
本章节通过七个详细的案例,介绍了Spring @Configuration注解的使用,如需文中完整的案例代码,你可以点击下面的地址访问github仓库进行下载。