1. 测试代码
//User类
public class User
{
private String username;
public User()
{
System.out.println("new User() 实例化...");
}
public void init()
{
System.out.println("User.init() 初始化...");
}
public void destroy()
{
System.out.println("User.destroy() 销毁...");
}
public String getUsername()
{
System.out.println("User.getUsername()");
return username;
}
public void setUsername(String username)
{
this.username = username;
System.out.println("User.setUsername(" + username + ")");
}
}
// 测试类
public class Main
{
@Test
public void test()
{
//1.加载并解析xml文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.获取User对象
User user = (User) context.getBean("user");
// 3. 使用对象
user.getUsername();
// 4. 关闭
context.close();
}
}
Spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
注意:
1. id值必须唯一,相当于new对象的引用名称
2. class:包名+类名,按【ctrl+鼠标左键】可定位到对应的class
3. init-method:指定需要进行初始化的方法名称
4. destroy-method:指定需要销毁资源的方法名称
-->
<bean id="user" class="" init-method="init" destroy-method="destroy">
<!--
property是set方法注入依赖,调用了User对象的set方法。
name: 跟set方法名称一致,首字母小写,set不用写。
value: set方法的参数。
-->
<property name="username" value="孤云"></property>
</bean>
</beans>
2. 测试结果
3. set方法为什么比init方法先执行呢?
通过debug对比调用栈发现会先解析xml的属性值然后在初始化。
-
set方法的调用栈。
-
init方法的调用栈。
-
在调用doCreateBean时, 2个调用栈发生了变化。先执行populateBean做了一些设置值的操作,执行到BeanWrapperImpl.setValue方法时,里面用了反射调用User类的set方法。
initializeBean中在执行到invokeCustomInitMethod时用反射调用的init方法。
-
invokeCustomInitMethod方法的描述信息。
/**
* Invoke the specified custom init method on the given bean.
* Called by invokeInitMethods.
* <p>Can be overridden in subclasses for custom resolution of init
* methods with arguments.
* @see #invokeInitMethods
*/
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
4. 把property
注释掉,在测试类中调用set方法。
@Test
public void test()
{
//1.加载并解析xml文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.获取User对象
User user = (User) context.getBean("user");
// 3. 使用对象
user.setUsername("孤云");
// 4. 关闭
context.close();
}
执行结果:
new User() 实例化…
User.init() 初始化…
User.setUsername(孤云)
User.destroy() 销毁…
5. 总结
- 首先会执行对象构造方法。
- 其次是配置文件中的
<property>
的内容,也就是set方法。如果没有配置这个就执行下一步。 - 接着是执行在配置文件中指定的init-method。
- 再接着是执行对象里的普通方法(get、set、toString、自定义的方法等)。
- 最后是指定的destroy-method。
6. 结语
文章内容仅为个人理解,如有错误欢迎指出。