spring ref标签property标签中的 ref属性和ref 标签有什么不同

1167人阅读
Spring(29)
1:javaBean
package com.study.
public class Car {
private int maxS
public Car() {
public String getBrand() {
public void setBrand(String brand) {
this.brand =
public String getCorp() {
public void setCorp(String corp) {
this.corp =
public double getPrice() {
public void setPrice(double price) {
this.price =
public int getMaxSpeed() {
return maxS
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxS
public Car(String brand, String corp, int maxSpeed) {
this.brand =
this.corp =
this.maxSpeed = maxS
public Car(String brand, String corp, double price) {
this.brand =
this.corp =
this.price =
public String toString() {
return &Car [brand=& + brand + &, corp=& + corp + &, price=& + price
+ &, maxSpeed=& + maxSpeed + &]&;
2:javabean
package com.study.
public class Person {
& &private S
& &private C
public Person() {
public String getName() {
public void setName(String name) {
this.name =
public int getAge() {
public void setAge(int age) {
this.age =
public Car getCar() {
public void setCar(Car car) {
this.car =
public String toString() {
return &Person [name=& + name + &, age=& + age + &, car=& + car + &]&;
& 3:application.xml
&?xml version=&1.0& encoding=&UTF-8&?&
&beans xmlns=&http://www.springframework.org/schema/beans&
&xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&
&xmlns:context=&http://www.springframework.org/schema/context&
&xsi:schemaLocation=&http://www.springframework.org/schema/beans&
& & & & & & & & & & http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&&
& & & & & & & & & &&
& &!-- 配置bean class:bean的全类名,通过反射的方式在IOC容器实例化对象,中id是唯一的--&
& &&bean id=&helloWorld& class=&com.study.bean.HelloWorld&&
& &&property name=&name& value=&Spring& /&
& &&/bean&
& & &!--通过构造方法配置属性 --&
& &bean id=&car& class=&com.study.bean.Car&&
& & &constructor-arg value=&奔驰& type=&java.lang.String&&&/constructor-arg&
& & &constructor-arg type=&java.lang.String&&
& & &!-- 如果字面值包含特殊字符可以使用&![CDATA[]]&包裹起来 --&
& & & &value&&![CDATA[&Shanghai^&]]&&/value&
& & &/constructor-arg&
& & &constructor-arg value=&300000& type=&double&&&/constructor-arg&
& & &property name=&maxSpeed& value=&100& /&
& &&bean id=&car2& class=&com.study.bean.Car&&
& & &constructor-arg value=&奔驰& type=&java.lang.String&&&/constructor-arg&
& & &constructor-arg value=&上海& type=&java.lang.String&&&/constructor-arg&
& & &constructor-arg value=&100& type=&int&&&/constructor-arg&
& & &property name=&price& value=&5000000& /&
& &bean id=&person& class=&com.study.bean.Person&&
& & &property name=&name& value=&Tom&&&/property&
& & &property name=&age& value=&24&&&/property&
& & &!--可以使用property的ref属性建立bean之间的引用关系 --&
& & &property name=&car& ref=&car2&&&/property&
& 4:main()方法测试
package com.study.
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
public class TestMain {
public static void main(String[] args) {
// HelloWorld helloworld=new HelloWorld();
// helloworld.setName(&Spring&);
// & & & &helloworld.hello();
//1:创建Spring的IOC容器对象 ApplicationContext是IOC容器的接口,
//ClassPathXmlApplicationContext是ApplicationContext接口的实现类,从类路径下加载
ApplicationContext ctx=new ClassPathXmlApplicationContext(&applicationContext.xml&);
& & &//2:从IOC容器中获取Bean实例 &通过id获取,
HelloWorld helloWorld=(HelloWorld)ctx.getBean(&helloWorld&);
//通过类名从IOC容器中获取Bean实例,要求一个类只能有一个Bean实例
//HelloWorld helloWorld2=(HelloWorld) ctx.getBean(HelloWorld.class);
&//3:调用hello方法
helloWorld.hello();
Car car=(Car) ctx.getBean(&car&);
System.out.println(car);
Car car2=(Car) ctx.getBean(&car2&);
System.out.println(car2);
Person person=(Person) ctx.getBean(&person&);
System.out.println(person.toString());
//helloWorld2.hello();
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:155628次
积分:6703
积分:6703
排名:第3133名
原创:527篇
评论:11条
(44)(21)(34)(4)(16)(162)(140)(59)(55)(4)Spring中property-placeholder的使用与解析
我们在基于spring开发应用的时候,一般都会将数据库的配置放置在properties文件中.
代码分析的时候,涉及的知识点概要:
NamespaceHandler 解析xml配置文件中的自定义命名空间
ContextNamespaceHandler 上下文相关的解析器,这边定义了具体如何解析property-placeholder的解析器
BeanDefinitionParser 解析bean definition的接口
BeanFactoryPostProcessor 加载好bean definition后可以对其进行修改
PropertySourcesPlaceholderConfigurer 处理bean definition 中的占位符
我们先来看看具体的使用吧
property的使用
在xml文件中配置properties文件
&?xml version=&1.0& encoding=&UTF-8&?&
&beans xmlns=&http://www.springframework.org/schema/beans&
xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&
xmlns:context=&http://www.springframework.org/schema/context&
xsi:schemaLocation=&
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd&&
&context:property-placeholder location=&classpath:foo.properties& /&
这样/src/main/resources/foo.properties文件就会被spring加载
如果想使用多个配置文件,可以添加order字段来进行排序
使用PropertySource注解配置
,方便添加property文件到环境.
@Configuration
@PropertySource(&classpath:foo.properties&)
public class PropertiesWithJavaConfig {
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
properties的注入与使用
@Value( &${jdbc.url}& )
private String jdbcU
还可以添加一个默认值
@Value( &${jdbc.url:aDefaultUrl}& )
private String jdbcU
在Spring的xml配置文件中获取
&bean id=&dataSource&&
&property name=&url& value=&${jdbc.url}& /&
properties配置信息的加载
Spring在启动时会通过AbstractApplicationContext#refresh启动容器初始化工作,期间会委托loadBeanDefinitions解析xml配置文件.
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanF
catch (IOException ex) {
throw new ApplicationContextException(&I/O error parsing bean definition source for & + getDisplayName(), ex);
loadBeanDefinitions通过层层委托,找到DefaultBeanDefinitionDocumentReader#parseBeanDefinition解析具体的bean
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i & nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
delegate.parseCustomElement(ele);
delegate.parseCustomElement(root);
这边由于不是标准类定义,所以委托BeanDefinitionParserDelegate解析
通过NamespaceHandler查找到对应的处理器是ContextNamespaceHandler,再通过id找到PropertyPlaceholderBeanDefinitionParser解析器解析
public void init() {
// 这就是我们要找的解析器
registerBeanDefinitionParser(&property-placeholder&, new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser(&property-override&, new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser(&annotation-config&, new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser(&component-scan&, new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser(&load-time-weaver&, new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser(&spring-configured&, new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser(&mbean-export&, new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser(&mbean-server&, new MBeanServerBeanDefinitionParser());
PropertyPlaceholderBeanDefinitionParser是这一轮代码分析的重点.
我们来看看它的父类吧.
BeanDefinitionParser
被DefaultBeanDefinitionDocumentReader用于解析个性化的标签
这边只定义了一个解析Element的parse api
public interface BeanDefinitionParser {
BeanDefinition parse(Element element, ParserContext parserContext);
AbstractBeanDefinitionParser
BeanDefinitionParser接口的默认抽象实现.spring的拿手好戏,这边提供了很多方便使用的api,并使用模板方法设计模式给子类提供自定义实现的钩子
我们来看看parse时具体的处理逻辑把:
调用钩子parseInternal解析
生成bean id,使用BeanNameGenerator生成,或者直接读取id属性
处理name 与别名aliases
往容器中注册bean
进行事件触发
AbstractSingleBeanDefinitionParser
解析,定义单个BeanDefinition的抽象父类
在parseInternal中,解析出parentName,beanClass,并使用BeanDefinitionBuilder进行封装
AbstractPropertyLoadingBeanDefinitionParser
解析property相关的属性,如location,properties-ref,file-encoding,order等
PropertyPlaceholderBeanDefinitionParser
这边处理的事情不多,就是设置ingore-unresolvable和system-properties-mode
properties文件的加载,bean的实例化
接下来,我们再看看这个bean是在什么时候实例化的,一般类的实例化有2种,一种是单例系统启动就实例化;一种是非单例(或者单例懒加载)在getBean时实例化.
这边的触发却是通过BeanFcatoryPostProcessor.
BeanFactoryPostProcessor是在bean实例化前,修改bean definition的,比如bean definition中的占位符就是这边解决的,而我们现在使用的properties也是这边解决的.
这个是通过PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors实现的.
扫描容器中的BeanFactoryPostProcessor,找到了这边需要的PropertySourcesPlaceholderConfigurer,并通过容器的getBean实例化
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
PropertySourcesPlaceholderConfigurer实例化完成后,就直接进行触发,并加载信息
OrderComparator.sort(priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
我们再来看看PropertySourcesPlaceholderConfigurer的继承体系把
BeanFactoryPostProcessor
定义一个用于修改容器中bean definition的属性的接口.其实现类在一般类使用前先实例化,并对其他类的属性进行修改.
这跟BeanPostProcessor有明显的区别,BeanPostProcessor是修改bean实例的.
PropertiesLoaderSupport
加载properties文件的抽象类.
这边具体的加载逻辑是委托PropertiesLoaderUtils#fillProperties实现
PropertyResourceConfigurer
bean definition中占位符的替换就是这个抽象类实现的.
实现BeanFactoryPostProcessor#postProcessBeanFactory,迭代容器的中的类定义,进行修改
具体如何修改就通过钩子processProperties交由子类实现
PlaceholderConfigurerSupport
使用visitor设计模式,通过BeanDefinitionVisitor和StringValueResolver更新属性
StringValueResolver是一个转化String类型数据的接口,真正更新属性的api实现竟然是在PropertyPlaceholderHelper#parseStringValue
PropertySourcesPlaceholderConfigurer
覆写postProcessorBeanFactory api定义解析流程
阅读(...) 评论()

我要回帖

更多关于 spring ref属性 的文章

 

随机推荐