Spring 的属性赋值与装配

一. 属性赋值

  1. 传统 xml 方式赋值,通过 property 标签, name为属性名, value为属性值
	<bean id="hh" class="com.ssm.entity.HelpCategory" lazy-init="false" >
		<property name="name" value="aaaa"/>
		<property name="url" value="bbbb"/>
	</bean>
  1. 传统方式中,xml 读取 运行环境中, .properties 文件夹中定义的变量,需要先设置要读取变量的 .properties文件加载到项目中, 然后使用 “${读取变量在文件中的名字}”,读取
    在这里插入图片描述

@Value() 注解赋值

使用 @Value 注解修饰向 向容器中注入的 bean 的属性,注解中传递该属性的数据,可以对属性赋值
@Value 注解赋值的几种方式

  • 直接在括号中输入数据 : @Value(“变量值”)
  • 在括号中输入 Spring 的 EL 表达式(EL 表达式是可以实现运算功能的) : @Value("#{11-1}")
  • 在括号中使用 : @ V a l u e ( " {} 获取配置文件中的值 : @Value(" {配置文件中需要获取的变量的变量名}");
    注意点: 在使用@Value("${}") 读取配置文件中的变量时,需要先将properties 配置文件获取到项目中

@PropertySource 注解导入配置文件到项目中

该注解可以需要一个String 数组, 数组中的每个字符串变量代表一个配置文件,可以输入类路径"classpath:/",也可以输入文件路径"file:/"

  1. 创建配置类,@PropertySource 配置导入项目的配置文件,编写向容器中注入 Person 的方法
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

//通过 @PropertySource 配置 resources 文件夹中的 properties文件夹中
//下的"jdbc.properties"配置文件导入到项目
@PropertySource(value = {"classpath:/properties/jdbc.properties"})
@Configuration
public class MyConfiguration {

    //Persion 注入到容器中
    @Bean
    public Persion configMethod1(){
       return new Persion();
    }

}
  1. Person 类中,通过 @Value 注解对属性赋值
import org.springframework.beans.factory.annotation.Value;

public class Person {

    @Value("男") //直接赋值
    private String sex;
    @Value("${jdbc.username}") //读取配置文件
    private String name;
    @Value("#{20-2}") //el表达式
    private String age;

    @Override
    public String toString() {
        return "Persion{" +
                "sex='" + sex + '\'' +
                ", name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}
  1. 运行测试,当配置文件加载到项目中后,通过 Spring 容器对象,获取运行环境,也可以读取到配置文件中的数据
public static void main(String[] args) {
        //1.获取ioc容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        //2.获取运行时环境
        ConfigurableEnvironment environment = context.getEnvironment();
        //3.获取导入到环境中.properties配置文件中指定名称的变量
        String url = environment.getProperty("jdbc.url");
        System.out.println(url);
        
        //4.获取 bean
        Person p = (Person) context.getBean("configMethod1");
        System.out.println(p);

        //5.关闭容器
        context.close();

    }

二. 自动装配

什么是自动装配: Spring 利用依赖注入,完成对 IOC 容器各个组件的依赖关系,以实际开发为例,Controller 中会用到 Service, Service 中会用到对应数据库的 Dao, 进而实现对数据的增删改查,将需被使用的类声明为使用该类的属性,通过一个注解将被使用的类,在容器中获取赋值给使用者的这个属性,例如 @Autowired

@Autowired

  1. @Autowired 可以用来修饰: 属性,以属性类型去容器中获取,修饰方法以方法形参类型去容器中获取,修饰参数, 修饰构造器,提供有参构造以构造器形参类型获取注入,并且当向容器中注入一个只有有参构造器的对象,在不使用@Autowired的情况下,默认会通过构造器的形参在容器中获取对应的bean赋值给注入的bean
  2. 当使用@Autowired 在容器中获取 bean,赋值给某个属性时,首先会按照类型去容器中获取,如果容器中有多个,会将属性名做为id 去容器中查找,
  3. 在使用@Autowired,如果想指定以属性名去为id去容器中查找,在使用@Autowired的同时,添加@Qualifier(“id名称”)注解,指定id获取
  4. @Autowired 修饰的属性,默认是容器中必须存在的,如果不存在则报错,在某些特定的场景,想要容器中有则进行装配,若没有则不装配,可以通过设置@Autowired注解的required属性值为false来设置

@Primary 设置装配优先级

假设,有两个相同类型的 bean 都要装配到容器中,但是有级别要求,可以通过 @Primary 修饰注入的 bean 或注入bean 的方法,首选将这个bean注入到容器中

@Resource 与 @Inject 实现装配功能

  1. @Resource 是 java 提供的装配注解, 与 @Autowired 的不同是默认按照被该注解修饰的属性名称去容器中获取 bean, 并且不支持 @Qualifier(“id名称”) 与 @Primary
  2. @Inject 是 java 提供的需要导入依赖, 与 @Autowired 不同的是没有required属性设置
    在这里插入图片描述

自动装配注解实现原理

通过 AutowiredAnnotationBeanPostProcessor 后置处理器来设置 bean 在初始化前后对属性的赋值,具体查看 “Spring Bean 的注入方式” 中后置处理器,与初始化 bean 的操作

自定义组件实现获取 Spring 中底层提供的组件

只需要将自定义组件实现XxxxAware 接口即可 , 继承的每个XxxxAware 都有对应的后置处理器,通过初始化bean以后,自动调用后置处理器中的方法,通过后置处理器中的方法运行自定义组件继承 XxxAware 重写的方法,达到功能效果,例如 “Spring Bean 的生命周期” 中提到的获取IOC容器,ApplicationContextAware 对应 ApplicationContextAwareProcessor

三. @Profile

  1. @Profile 可以修饰类(对整个类中的所有方法生效),可以修饰向Spring注入bean的方法(只对当前被修饰的方法生效),默认的value值为"default"所有的都可以
  2. 作用: Spring 提供可以根据当前环境,动态的切换一系列bean组件的功能,例如: 在项目开发时,有开发环境,测试环境,生产环境,拿数据库连接来举例: 在开发时连接开发库,测试时连接测试库,发布生产则连接生产库,在不改动代码的情况下通过 @ProFile 实现动态的修改,指定组件在哪个环境下才可以激活将组件注册到容器中,设置激活环境的方式有两种,可以通过命令行的方式,也可通过代码的方式设置环境
  3. 示例: 创建配置类,配置向容器中注入数据源连接 bean,注入两个,一个test环境下的,一个dev环境下的,根据环境不同自动注入对应的连接 bean
@Configuration
public class MyConfiguration {

    //指定环境为"dev"时才会将这个方法返回的 bean 注入到容器中
    @Profile("dev")
    @Bean
    public DruidDataSource configMethod1(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/mysql?serverTimezone=GMT%2B8");
        druidDataSource.setName("root");
        druidDataSource.setPassword("");
        return  druidDataSource;
    }

    //指定环境为"test"时才会将这个方法返回的 bean 注入到容器中
    @Profile("test")
    @Bean
    public DruidDataSource configMethod2(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/sys?serverTimezone=GMT%2B8");
        druidDataSource.setName("root");
        druidDataSource.setPassword("");
        return  druidDataSource;
    }

}
  1. 设置激活环境
  • 命令行的方式active后面的值就是指定激活的开发环境 : -Dspring.profiles.active=test
    在这里插入图片描述

  • 代码的方式 : 通过调用无参构造器创建 IOC 容器对象 AnnotationConfigApplicationContext,通过这个对象获取运行时环境对象 ConfigurableEnvironment, 通过运行时环境对象调用setActiveProfiles() 方法设置激活环境,然后再使用 AnnotationConfigApplicationContext 对象调用 register() 方法读取 Spring 框架相关的配置一些配置,手动调用 refresh() 方法进行刷新

public static void main(String[] args) {

        //创建 Ioc 容器时,使用带参构造器,由于带参构造器,在构造器中会执行 refresh()方法,
        //刷新开发环境所以需要通过无参构造,创建IOC容器,在设置环境成功后,手动调用 refresh()
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        //2.通过容器获取运行时环境对象
        ConfigurableEnvironment environment = context.getEnvironment();


        //3.通过运行时环境对象设置激活环境,可以设置多个,使用逗号隔开
        environment.setActiveProfiles("test");

        //4.注册主配置类
        context.register(MyConfiguration.class);

        //5.手动启动刷新容器
        context.refresh();

        //2.获取 bean
        //DruidDataSource d = (DruidDataSource) context.getBean("configMethod1");
        Map<String, DruidDataSource> druidDataSourceMap = context.getBeansOfType(DruidDataSource.class);

        druidDataSourceMap.entrySet().stream().forEach(m -> System.out.println(m.getValue().getUrl()));

        //3.关闭容器
        context.close();

    }
发布了48 篇原创文章 · 获赞 0 · 访问量 582

猜你喜欢

转载自blog.csdn.net/qq_29799655/article/details/105318597