前面说了@ConfigurationProperties和@Value的一些区别和用法,我们再来说两个注解,一个叫PropertySource,一个叫
@ImportResource,第一个PropertySource,他的作用是什么呢,加载指定的配置文件,咱们以Person为例,我们Person是要
绑定到全局配置文件中,跟Person相关的所有值,我们用@ConfigurationProperties,但是他有一个要求,你的这些配置,
都是默认写在全局配置文件中的,他默认是从全局配置文件中获取值,如果后来我把所有的东西都配置在全局配置文件里面,
那配置文件可能就太大了,我想把一些跟Springboot无关的配置,我想提取出来,比如我想写一个person.properties,跟person
有关的配置放到这,相当于所有的配置都到这儿了,很明显我把它改成李四,如果是现在的情况下,我们全局配置文件里面,
person的值,那肯定加载不到,那我们就用这个值,@PropertySource,读取指定的配置文件,他里面有一个value值,value值还能够写
一个数组的方式,我们可以加载多个外部的配置文件
@PropertySource(value= {"classpath:person.properties"})
他的作用就是告诉springboot,来加载类路径下的person.properties内容,并把它们绑定到Person对象中,进行一个测试,发现都能
读取到
person.last-name=\u674E\u56DB
person.age=18
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=dog
person.dog.age=15
package com.learn.bean;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中的相关的配置进行绑定
* prefix="person":配置文件中哪个下面的所有属性进行映射
*
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
* 默认从全局配置文件中获取值;
*/
@PropertySource(value= {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix="person")
//@Validated
public class Person {
/**
* <bean class="person">
* <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
* </bean>
*/
// lastName必须是邮箱格式
//@Email
// @Value("${person.last-name}")
private String lastName;
// @Value("#{10*2}")
private Integer age;
@Value("true")
private Boolean boss;
private Date birth;
// @Value("${person.maps}")
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person [lastName=" + lastName + ", age=" + age + ", boss=" + boss + ",
birth=" + birth + ", maps="
+ maps + ", lists=" + lists + ", dog=" + dog + "]";
}
}
package com.learn.springboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.learn.bean.Person;
/**
* SpringBoot单元测试
*
* 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigurationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
这个注解,可以加载指定的配置文件,接下来我们来说第二个,@ImportResource,他的作用是什么呢,导入Spring的配置文件,
让配置文件里面的内容生效,比如我们要给容器中加一个组件,除了注解的方式外,我们以前写的是SpringMVC的配置文件,
我来创建一个Spring的配置文件,beans.xml,我来加一个组件,比如我来创建一个HelloService组件,我在Spring配置文件中
加入进来,然后给他一个id,这都是我们以前的配置,那现在容器中有没有这个helloService,是不是你写一个Spring的配置
文件就自动识别,那肯定不是的,我们可以来测一下,看容器中,有没有HelloService呢,我就让IOC容器注入进来
<bean id="helloService" class="com.learn.service.HelloService"></bean>
@Autowired
ApplicationContext ioc;
我们来测试容器中有没有HelloService,他有一个判断叫containsBean,是不是包含一个bean,包含哪个bean呢,我们就叫
helloService,我们在控制台打印一下有没有helloService,我们看到控制台打印false,也就是SpringBoot没有Spring的配置文件,
我们自己编写的配置文件,也不能自动识别,如果真的想让我们配置文件生效,加载进来,就需要这个注解,我们把它标注在一个
配置类上,那我就把它标注在主配置类上,@ImportResource,在这个注解上有一个locations,他也是一个数组,能让我们加载多个的
Spring配置文件,类路径下的beans.xml,当我把它加载进来以后,看容器中还有没有这个bean,我们看到现在容器中就有了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<bean id="helloService" class="com.learn.service.HelloService"></bean>
</beans>
package com.learn.service;
public class HelloService {
}
package com.learn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Sprint Boot应用
* @author Leon.Sun
*
*/
@ImportResource(locations= {"classpath:beans.xml"})
@SpringBootApplication
public class SpringBoot02ConfigApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(SpringBoot02ConfigApplication.class,args);
}
}
package com.learn.springboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import com.learn.bean.Person;
/**
* SpringBoot单元测试
*
* 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigurationTests {
@Autowired
Person person;
@Autowired
ApplicationContext ioc;
@Test
public void testHelloService() {
boolean b = ioc.containsBean("helloService");
System.out.println(b);
}
@Test
public void contextLoads() {
System.out.println(person);
}
}
所以他的功能就是导入Spring的配置文件,我们用它导入Spring的配置文件,让其生效,这样我们就能用了,
就是这两个注解,我们后来开发的时候,我们不可能给容器中加组件,我来写一个配置文件,然后将配置文件导进来,
这样太麻烦了,把@ImportResource(locations= {"classpath:beans.xml"})这个注掉,SpringBoot中推荐给容器中
添加组建的方式,是什么呢,是这样的,首先我们来写一个配置类,配置类就相当于配置文件一样,就类似于Spring的
配置文件一样,我们在Spring的配置文件里边,我们是在配置类里面添加,但是我们现在不希望这样来用了,我们不来编写
Spring的配置文件了,SpringBoot推荐使用全注解的模式,那我们要给容器中加组件,第一个我们先来写一个配置类,比如我就
来写一个配置类,当然配置类也可以是我们的主配置类,我专门来写一个配置类,所有的配置类都放在config文件夹下,我们就叫
MyAppConfig,我们项目的配置,他要称为配置类,那就要加之前讲的注解,叫@Configuration,这个注解告诉Springboot,这是一个
配置类,指明当前类是一个配置类,配置类就相当于我们之前的配置文件,就是来替代之前的配置文件,那我们在配置文件里边,
我们以前在配置文件中,是使用bean标签来添加组件的,那我们在配置类里边,我们怎么添加呢,我们在配置类里边有一个
@Bean注解,bean标签对应bean注解,Value属性对应@Value注解,这其实是一一对应的,他能够标注在方法上
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
当然也可以作为一个原注解来标注,我写一个方法他的作用是什么呢,就是将方法的返回值添加到容器中,容器中这个组件,默认的
id就是方法名,我们来return一个,自己来new一个helloService,把这个helloService添加到容器中,容器中这个组件的名字就叫
helloService,我们来可以看一下,容器中有没有这个helloService呢,注意我们已经不导这个配置文件了,我们是使用配置类的
方式加了一个组件,包括如果运行正确,这个方法也会打印,配置类@Bean给容器中添加组件了,我们可以来测试一下,容器中有没有
helloService这个组件,包括我们来看控制台,我们看到配置类给容器中添加组件了,而且容器中也有这个helloService
package com.learn.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.learn.service.HelloService;
/**
* @Configuration 指明当前类是一个配置类
*
* @author Leon.Sun
*
*/
@Configuration
public class MyAppConfig {
// 将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService() {
System.out.println("配置类@Bean给容器中添加组件了");
return new HelloService();
}
}
package com.learn.springboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import com.learn.bean.Person;
/**
* SpringBoot单元测试
*
* 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigurationTests {
@Autowired
Person person;
@Autowired
ApplicationContext ioc;
@Test
public void testHelloService() {
boolean b = ioc.containsBean("helloService");
System.out.println(b);
}
@Test
public void contextLoads() {
System.out.println(person);
}
}
而且他用的id就是我们方法的返回值,如果helloService改成helloService02,我们再看容器中有没有
helloService这个组件了,我们看helloService就没有了,而拥有的肯定是helloService02,我们推荐用
这种方式给容器中添加组件,其实@Bean注解和@Configuration注解,都是Spring注解版底层的东西