编写bean(Hello.java)、配置文件(beans.xml)、调用端(TestSpring.java),项目中导入spring.jar、common-logging.jar包
1.Hello.java
public class Hello {
private String name;
public Hello(){}
public Hello(String args){
name = args;
}
public void setName(String name){
this.name = name;
}
public void println(){
System.out.println("Hello " + name);
}
}
2.beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="hello" class="Hello">
<constructor-arg>
<value>World</value>
</constructor-arg>
<!--
<property name="name">
<value>Spring</value>
</property>
-->
</bean>
</beans>
3.TestSpring.java
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class TestSpring {
public static void main(String[] args){
AbstractApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");
Hello hello = (Hello)context.getBean("hello");
hello.println();
}
}
运行TestSpring,输出结果:Hello World
如果取消注释的部分则输出:Hello Spring
Spring根据配置文件中的参数,使用构造方法注入将World注入到Hello中,使用属性注入将Spring注入到Hello中。
那Spring源码中是什么时候创建hello实例,什么时候、怎么注入的?
1.先将beans.xml中的配置信息,保存到BeanDefinition的实例中。再将这些BeanDefinition放到DefaultListableBeanFactory的属性beanDefinitionMap中。发生在这一步:
AbstractApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");
2.getBean("hello");的时候就开始创建实例了。
使用Java反射机制创建bean实例,在SimpleInstantiationStrategy.instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner)或者CglibSubclassingInstantiationStrategy.instantiate(Constructor ctor, Object[] args)方法中。
3.在BeanWrapperImpl.setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv)中也是用java反射调用相关的方法进行设置return readMethod.invoke(object);而这个readMethod是从PropertyDescriptor.getReadMethod()取得的(里边有一行readMethodName = "get" + getBaseName();这里就明白了setter、getter方法要遵守规范了)。