spring给属性赋值(非从容器中取)

spring怎么直接给属性赋值

1、使用@Value注解直接给属性赋值

  我们要给属性赋基本数据类型或者String类型的值时,可以使用@value注解来给属性赋值,一般来说这种用法比较少用。

/**
 * 给属性赋值
 *    @Value注解可以给属性赋值,给属性赋值的方式
 *      1、value=字符串,直接将字符串赋值给属性,基本数据类型也可以
 *      2、value="#{}",大括号里可以写表达式
 *      3、value="${}",大括号里可以取环境变量中的值
 *      要想向将配置文件中的值赋给属性,我们要先将配置文件的值加到环境变量中。这里需要用到@PropertySource注解,它的value属性指定配置文件的类路径例如:@PropertySource(value ={"classpath:/myconfig.properties"}),@PropertySource注解一般加在配置类类名上
 */
public class Disaster {
    @Value("祸殃")
    private String name;
    @Value("#{1+89}")
    private int age;
    @Value("${disaster.state}")
    private String state;//姿态

    @Override
    public String toString() {
        return "Disaster{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", state='" + state + '\'' +
                '}';
    }
}

2、使用@Value注解将配置文件的值赋给属性

  我们之前如果想将配置文件的值赋给属性,要先读取配置文件的值,然后在通过一系列操作才能将配置文件的值与属性绑定。使用@value注解我们可以轻松的将类的属性与配置文件进行绑定。
  首先我们要明确一点,@value获取到的是环境变量的值,它是无法直接获取配置文件的值的。所以我们要将配置文件的值加到环境变量中(使用@PropertySource注解)。

/**
 * 给属性赋值。给属性赋基本数据类型和String类型的值
 */
@Configuration
@Slf4j
@PropertySource(value ={"classpath:/myconfig.properties"})//会将配置文件的值加到环境变量中,然后使用SPEL表达式从环境变量中获取值
public class AttributeAssignmentConfig {

    @Bean
    public Disaster disaster(){
        return new Disaster();
    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(AttributeAssignmentConfig.class);
        String property = applicationContext.getEnvironment().getProperty("os.name");
        log.info(property);
        Disaster bean = applicationContext.getBean(Disaster.class);
        log.info(bean+"");
    }
}

 class Disaster {
    @Value("祸殃")
    private String name;
    @Value("#{1+89}")
    private int age;
    @Value("${disaster.state}")//使用SPEL表达式从环境变量中获取值
    private String state;//姿态
    @Override
    public String toString() {
        return "Disaster{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", state='" + state + '\'' +
                '}';
    }
}

3、原理解析

  我们之前在看bean的生命周期源码时间,在创建好bean实例以后,会调用populateBean()方法,将来自bean定义的属性值填充给定BeanWrapper中的bean实例。下面是部分源码

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		// Instantiate the bean.//创建bean实例
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
		// Initialize the bean instance.
		  Object exposedObject = bean;
			populateBean(beanName, mbd, instanceWrapper);//用来自bean定义的属性值填充给定BeanWrapper中的bean实例。
			exposedObject = initializeBean(beanName, exposedObject, mbd);//bean进行初始化
	}

  我们进入到populateBean()方法,下面是部分源码截取。通过源码我们可以知道,spring是通过前置处理器将解析@Value注解的值,并赋给属性。【处理@Value的处理器是AutowiredAnnotationBeanPostProcessor】,处理细节查看AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,这里就不赘述了。

/**
* beanName:bean的名字
* mbd:bean的定义信息
* bw:带有bean实例的BeanWrapper
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {//见下图
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值