• 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}
  • 相关阅读:
    测试运行效率
    识别字符串中的表达式(续二)
    FireScript在SharePoint中的应用
    加入了静态类的语义分析引擎
    这是我在C#中测试速度的代码
    用自定义函数来实现代理类的实例化
    IF语句多分支识别
    FireScript调用DLL和COM
    JMETER在LINUX安装和使用
    转:Big List Of 20 Common Bottlenecks
  • 原文地址:https://www.cnblogs.com/demo-alen/p/13547231.html
Copyright © 2020-2023  润新知