Spring注解驱动开发二组件赋值-@Value和@PropertySource及XXXXAware接口

本文详细介绍了Spring框架中@Value、@PropertySource等注解的使用方法,并解释了如何通过这些注解来读取配置文件中的属性值。同时,还探讨了@Autowired、@Resource和@Inject的区别,以及如何通过实现特定接口来注入Spring底层组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【1】@Value和@PropertySource

① @Value

该注解可以直接给bean的属性赋值(不支持JSR303校验),具体有以下几种用法:

  • 基本数值
  • 可以写SpEL; #{}
  • 可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)

Bean类如下:

public class Person {
	
	@Value("张三")
	private String name;
	
	@Value("#{20-2}")
	private Integer age;
	
	@Value("${person.nickName}")
	private String nickName;
	
	//...
}

注意到,nickName属性使用了配置文件中的值,那么如何引入配置文件呢?


② @PropertySource

该注解读取外部配置文件中的k/v保存到运行的环境变量中,加载完外部的配置文件以后使用${}取出配置文件的值。

注解接口如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {

	 // 声明资源文件名字
	String name() default "";

	 // 声明需要加在的资源文件位置,例如classpath:/com/myco/app.properties
	 // 或者 file:/path/to/file,不支持通配符,必须是确切的文件路径
	 // 可以使用${...}
	String[] value();

	 // 声明如果查找资源文件失败,是否忽略
	 // 如果资源文件是可选的,那么建议设置为true
	 // 默认是false
	boolean ignoreResourceNotFound() default false;


	 // 资源文件字符编码,如"UTF-8"
	String encoding() default "";


	 // 指定一个自定义的PropertySourceFactory
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;

}

配置类如下:

@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
	
	@Bean
	public Person person(){
		return new Person();
	}

}

测试如下:

public class IOCTest_PropertyValue {
	AnnotationConfigApplicationContext applicationContext = 
	new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
	
	@Test
	public void test01(){
		printBeans(applicationContext);
		System.out.println("=============");
		
		Person person = (Person) applicationContext.getBean("person");
		System.out.println(person);
		
		//配置文件中的值存在于环境中,可以使用如下方式获取
		ConfigurableEnvironment environment = applicationContext.getEnvironment();
		String property = environment.getProperty("person.nickName");
		System.out.println(property);
		applicationContext.close();
	}
	
	private void printBeans(AnnotationConfigApplicationContext applicationContext){
		String[] definitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : definitionNames) {
			System.out.println(name);
		}
	}

}

测试结果如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfigOfPropertyValues
person
=============
Person [name=张三, age=18, nickName=小李四]
小李四

从Properties文件中取值得三种方式:

@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
	
	@Value("${db.user}")//第一种,成员属性 @Value
	private String user;
	
	private StringValueResolver valueResolver;
	
	private String  driverClass;
	
	
	@Bean
	public Yellow yellow(){
		return new Yellow();
	}
	
	// 第二种,参数 @Value
	@Profile("test")
	@Bean("testDataSource")
	public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
		// 第二种,参数 @Value
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser(user);
		dataSource.setPassword(pwd);
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
		dataSource.setDriverClass(driverClass);
		return dataSource;
	}

// 第三种,使用值解析器,从环境中获取值。
	@Override
	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		// TODO Auto-generated method stub
		this.valueResolver = resolver;
		driverClass = valueResolver.resolveStringValue("${db.driverClass}");
	}
}

【2】@Autowired @Resource 和 @Inject

这个参考博文:Spring中Bean注入与获取几种方式详解


【3】实现XxxAware接口,将Spring底层组件注入bean

自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx)。

自定义组件实现xxxAware接口,在创建对象的时候,会调用接口规定的方法注入相关组件。

每一个xxxAware都有一个对应的xxxProcessor后置处理器来实现其功能。

ApplicationContextAware==》ApplicationContextAwareProcessor;

自定义bean类如下:

@Component
public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware {
	
	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

		System.out.println("传入的ioc:"+applicationContext);
		this.applicationContext = applicationContext;
	}

	@Override
	public void setBeanName(String name) {

		System.out.println("当前bean的名字:"+name);
	}

	@Override
	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
		System.out.println("解析的字符串:"+resolveStringValue);
	}
}

测试如下:

当前bean的名字:red
解析的字符串:你好 Windows 7 我是 360
传入的ioc:org.springframework.context.annotation.AnnotationConfigApplicationContext@11028347: 
startup date [Tue Apr 10 11:09:18 CST 2018]; root of context hierarchy

后置处理器实现源码:

ApplicationContextAwareProcessor 是一个bean后置处理器实现类,将ApplicationContext 传递给那些实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware及ApplicationContextAware接口的bean。

被实现的接口按照上述顺序得到满足。应用程序上下文将自动向其基础bean工厂注册。应用程序不直接使用它。

这个过程可以参考AbstractApplicationContext#refresh()的方法。

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;

	 // 创建一个ApplicationContextAwareProcessor 
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareInterfaces(bean);
					return null;
				}
			}, acc);
		}
		else {
		// 核心方法
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

// 判断bean的类型,然后传递applicationContext
	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值