新建一个配置类,如下:
@Configuration
@ComponentScan(value = "com.practice.bean")
public class MainConfig {
@Bean
public Person person() {
return new Person();
}
}
一,@Value赋值
1、基本数值,2、SpEL表达式#{},3、${}从Environment中获取
为Person类的属性加上以下值:
@Value("Alen")
private String name;
@Value("#{30-25}")
private Integer age;
执行测试类,
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean.toString());
}
打印出组件,结果如下:
Person{name='Alen', age=5}
二,@PropertySource加载外部配置文件
创建配置文件person.properties,内容如下:
name=Alen
age=19
在配置类中引入该properties文件:
@PropertySource("classpath:/person.properties")
在Person组件的属性上用${}取值:
@Value("${name}")
private String name;
@Value("${age}")
private Integer age;
执行测试类,打印结果如下:
Person{name='Alen', age=19}
Tips:尝试从Environment中获取配置文件中的属性值,在测试类的代码中加上如下:
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String name = environment.getProperty("name");
System.out.println(name);
打印出name的值为Alen,成功取到配置文件中name属性的值。
三,@ Autowired,@Qualifier,@Primary进行自动装配
- 自动装配:Spring利用DI(依赖注入)完成对容器中各个组件的依赖关系的赋值。
1.默认按照类型去容器中找相应的组件
新建一个ThickHair类,并加上@Component注解。
在Person类中加上如下代码,为Person注入ThickHair:
@Autowired
private ThickHair thickHair;
public void printHair(){
System.out.println(thickHair);
}
执行测试类:
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
person.printHair();
ThickHair hair = applicationContext.getBean(ThickHair.class);
System.out.println(hair);
}
打印结果如下:
com.practice.bean.ThickHair@33afa13b
com.practice.bean.ThickHair@33afa13b
可以看出在容器中注册的和为Person注入的为同一个thickHair组件。
2.如果找到多个相同的组件,则根据属性的名称作为ID去查找
在ThickHair类中加上属性flag,并赋默认值为 component。
private String flag="component";
在配置类中以@Bean方式再为容器注册一个ThickHair组件,代码如下:
@Bean("beanThickHair")
public ThickHair thickHair() {
ThickHair thickHair = new ThickHair();
thickHair.setFlag("bean");
return thickHair;
}
执行测试类:
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
person.printHair();
ThickHair hair = (ThickHair) applicationContext.getBean("beanThickHair");
System.out.println(hair);
}
结果如下:
ThickHair{flag='component'}
ThickHair{flag='bean'}
将Person类中注入ThickHair的名称改为beanThickHair;
@Autowired
private ThickHair beanThickHair;
public void printHair(){
System.out.println(beanThickHair);
}
在执行测试类,结果如下:
ThickHair{flag='bean'}
ThickHair{flag='bean'}
3@Primary可以在相同组件多个的时候指定优先级
将Person类中属性名改回thickHair,
@Autowired
private ThickHair thickHair;
public void printHair(){
System.out.println(thickHair);
}
在配置类@Bean上加上@Primary注解
@Bean("beanThickHair")
@Primary
public ThickHair thickHair() {
ThickHair thickHair = new ThickHair();
thickHair.setFlag("bean");
return thickHair;
}
执行测试类,
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
person.printHair();
ThickHair hair = (ThickHair) applicationContext.getBean("beanThickHair");
System.out.println(hair);
}
结果如下:
ThickHair{flag='bean'}
ThickHair{flag='bean'}
4.@Qualifier可以直接指定要装配的组件的ID
将@Qualifier("thickHair")加在Person注入的属性上:
@Autowired
@Qualifier("thickHair")
private ThickHair beanThickHair;
执行测试类:
ThickHair{flag='component'}
ThickHair{flag='bean'}
Tips.
1.将ThickHair组件从容器中移除(去除@Bean和@Component注解)
Person类的属性ThickHair被划红线-->Could not autowire.No beans of thickHair found;
我们在Person类ThickHair属性上的@Autowired注解上加上:
@Autowired(required = false)
报错消失,执行测试类打印为null;
2.@Resource(JSR250)和@Inject(JSR330)注解也能为容器注入组件
- @ReSource可以和@Autowired一样实现自动装配功能,默认按照组件名称进行装配,不支持@Primary和@Autowired的required=false;
- @Inject和@Autowired功能一样,不支持@Autowired的required=false,但支持@Primary
3.@Autowired还可以在构造器,参数、属性、方法上标注--->都是从容器中获取参数组件的值
4.Aware注入Spring底层组件&原理
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx)可以让自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的set方法注入相关组件,把Spring底层一些组件注入到自定义的Bean中。
原理在上一篇Spring注解开发(二)中的BeanPostProcessor在Spring底层的应用中已有说明(通过BeanPostProcesors为容器注入组件)。
四,@Profile环境搭建根据环境注册
Profile是Spring为我们提供的可以根据当前环境动态的注册组件的功能。
@Profile:指定组件在哪个环境的情况下才能被注册到容器中
- 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境。
- 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效。
- 没有标注环境标识的bean在任何环境下都是加载的。
创建Person接口:
public interface Person {
void speak();
}
并新建两个实现类:
@Profile("dev")
@Component
public class Alen implements Person {
@Override
public void speak() {
System.out.println("I am Alen");
}
}
@Profile("test")
@Component
public class ZhaZhaHui implements Person {
@Override
public void speak() {
System.out.println("我是渣渣辉,是兄弟就来砍我");
}
}
新建业务类:
@Component
public class Meeting {
@Autowired
private Person person;
public void speak(){
person.speak();
}
}
新建配置类,只做包扫描
@Configuration
@ComponentScan(value = "com.practice.bean")
public class MainConfig {
}
测试类如下:
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.getEnvironment().setActiveProfiles("dev");
applicationContext.register(MainConfig.class);
applicationContext.refresh();
Meeting bean = applicationContext.getBean(Meeting.class);
bean.speak();
}
执行结果为:
I am Alen
我们将ActiveProfiles属性改为test,执行结果为:
我是渣渣辉,是兄弟就来砍我
tips:测试类也可以这样,导入Spring-test包:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(classes = MainConfig.class)
public class BeanLifeCycleTest {
@Autowired
public Person person;
@Test
public void testProfiles(){
person.speak();
}
}
结果为:
我是渣渣辉,是兄弟就来砍我
Tips:
新建Person类属性name,age
配置文件如下:
####dev
dev.name=Alen
dev.age=18
####test
test.name=zhaZhaHui
test.age=151
配置类如下,运用@Value赋值,实现EmbeddedValueResolverAware 解析${},实现EnvironmentAware 从环境变量中获取:
@Configuration
@ComponentScan(value = "com.practice.bean")
@PropertySource("classpath:/person.properties")
public class MainConfig implements EmbeddedValueResolverAware , EnvironmentAware {
@Value("${dev.age}")
private Integer age;
private String name;
private Environment environment;
@Bean
@Profile("test")
public Person alen(@Value("${test.age}") Integer testAge) {
String name = environment.getProperty("test.name");
return new Person(name, testAge);
}
@Bean
@Profile("dev")
public Person zhaZhaHui() {
return new Person(name, age);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.name = resolver.resolveStringValue("${dev.name}");
}
@Override
public void setEnvironment(Environment environment) {
this.environment=environment;
}
}
测试类还和上面一样,
当为dev时,测试结果为:
Person{name='Alen', age=18}
当为test时,测试结果为:
Person{name='zhaZhaHui', age=151}