Spring注解开发(三)属性赋值与自动装配

  新建一个配置类,如下:

@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}
原文地址:https://www.cnblogs.com/demo-alen/p/13547231.html