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;
}
}