在spring开发中,我们定义bean
经常会需要用到beanFactory对象,这就需要实现BeanFactoryAware这种类型的接口,它有一个setBeanFactory方法
 
在xml中配置bean 的时候,我们也可以指定initMethod方法
 
在bean类定义的时候可以实现InitializingBean,提供一个afterPropertiesSet方法的实现
 
 
以上者3中情况我们经常用到,下面来分析一下spring是如何处理这3种情况的,他们的调用时机是怎么样的?
 
 
在AbstractAutowireCapableBeanFactory类中
  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
  2. // Instantiate the bean.
  3. BeanWrapper instanceWrapper = null;
  4. if (mbd.isSingleton()) {
  5. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  6. }
  7. if (instanceWrapper == null) {
  8. instanceWrapper = createBeanInstance(beanName, mbd, args);
  9. }
  10. //...省略很多代码 下面开始初始化 关键就是两个步骤
  11. // Initialize the bean instance.
  12. Object exposedObject = bean;
  13. try {
  14. populateBean(beanName, mbd, instanceWrapper); //这里执行了注入属性和依赖的操作
  15. if (exposedObject != null) {
  16. exposedObject = initializeBean(beanName, exposedObject, mbd);//这里执行了initMethod 和 afterPropertiesSet
  17. }
  18. }
  19. //...省略很多代码
  20. return exposedObject;
  21. }

 重点看initializeBean(beanName, exposedObject, mbd)

  1. protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
  2. if (System.getSecurityManager() != null) {
  3. AccessController.doPrivileged(new PrivilegedAction<Object>() {
  4. public Object run() {
  5. invokeAwareMethods(beanName, bean);
  6.  
  7. return null;
  8. }
  9. }, getAccessControlContext());
  10. }
  11. else {
  12. //这里判断是BeanFactoryAware, ServletContextAware之类的aware类型,如果是的话就执行对于的Aware方法
  13. //把beanFactory啊 servletContext啊之类的依赖set进去
  14. invokeAwareMethods(beanName, bean);
  15. }
  16.  
  17. Object wrappedBean = bean;
  18. if (mbd == null || !mbd.isSynthetic()) {
  19. //如果实现了BeanPostProcessor接口 这里会执行postProcessBeforeInitialization方法
  20. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  21. }
  22. try {
  23. //这里就开始执行initMethod 和 afterPropertiesSet方法
  24. invokeInitMethods(beanName, wrappedBean, mbd);
  25. }
  26. catch (Throwable ex) {
  27. throw new BeanCreationException(
  28. (mbd != null ? mbd.getResourceDescription() : null),
  29. beanName, "Invocation of init method failed", ex);
  30. }
  31. if (mbd == null || !mbd.isSynthetic()) {
  32. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  33. }
  34. return wrappedBean;
  35. }

进入invokeInitMethods(beanName, wrappedBean, mbd);

  1. protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
  2. throws Throwable {
  3. boolean isInitializingBean = (bean instanceof InitializingBean);//先判断是否实现了InitializingBean接口
  4. if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
  5. //.....省略很多代码
  6. else {
  7. //执行afterPropertiesSet()方法
  8. ((InitializingBean) bean).afterPropertiesSet();
  9. }
  10. }
  11. if (mbd != null) {
  12. String initMethodName = mbd.getInitMethodName();
  13. if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
  14. !mbd.isExternallyManagedInitMethod(initMethodName)) {
  15. //如果配置了initMethod 就执行initMethod方法 这里只是取到了方法名,显然是要通过反射调用了
  16. invokeCustomInitMethod(beanName, bean, mbd);
  17. }
  18. }
  19. }
经过这些源码的分析 可以得出结论
首先这些过程都在很重要的抽象类AbstractAutowireCapableBeanFactory抽象类中 这个类就是常用的DefaultListableBeanFactory的父类
1.spring先根据beanDefinition创建出了bean 的实例
 
2.执行了populateBean方法 把属性和依赖都注入了  
 
3.执行了 initializeBean(beanName, exposedObject, mbd);方法 这里面才进行了Aware相关方法,afterPropertiesSet 和 initMethod 方法的调用
可见这3种方法调用又都是在bean实例已经创建好,且属性值和依赖的其他bean实例都已经注入以后 才得到调用的
 
4.后面的代码可以看出 Aware相关方法最先执行,afterPropertiesSet 第二执行  ,initMethod 方法最后执行
 
另外多说一句 afterPropertiesSet方法是很有用的,比如 AOP事务管理用到的类,TransactionProxyFactoryBean 就是利用afterPropertiesSet方法事先把事务管理器
TransactionManager的代理类对象给生成好了,后面调用FactoryBean对象的getObject方法的时候,就直接把这个代理对象返回出去了。

initMethod 和 afterPropertiesSet 以及 AwareMethod方法的执行时机的更多相关文章

  1. Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机

    1.今天在做数据库升级的时候,遇到一个问题,就是onCreate方法和onUpgrade方法的执行时机的问题,这个当时在操作的时候,没有弄清楚,很是迷糊,后来看了相关的博客由于转发受限所以copy了一 ...

  2. Android中的Sqlite中的onCreate方法和onUpgrade方法的执行时机--(转)

    原文:http://blog.csdn.net/jiangwei0910410003/article/details/46536329 今天在做数据库升级的时候,遇到一个问题,就是onCreate方法 ...

  3. MVC源码分析 - Action/Result 过滤器执行时机

    前面 的篇章, 解析了Action方法的查找, 以及 Authorize, Action, Result, Error 过滤器的加载时机. 也花了两篇去看授权和错误过滤器的使用. 但是对于 Actio ...

  4. 简单比较init-method,afterPropertiesSet和BeanPostProcessor

    一.简单介绍 1.init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置.init-method需要在applicationContext.xml配置文档中bean的 ...

  5. 在Spring Bean的生命周期中各方法的执行顺序

    Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下十种: 通过实现 InitializingBe ...

  6. 【hibernate 执行方法未插入数据库】hibernate的save方法成功执行,但是未插入到数据库

    今天做项目,碰上这个问题: hibernate的save方法成功执行,但是未插入到数据库. Dao层代码: @Override public void save(T t) { this.getSess ...

  7. C# 给某个方法设定执行超时时间 C#如何控制方法的执行时间,超时则强制退出方法执行 C#函数运行超时则终止执行(任意参数类型及参数个数通用版)

    我自己写的 /// <summary> /// 函数运行超时则终止执行(超时则返回true,否则返回false) /// </summary> /// <typepara ...

  8. 转 C# 给某个方法设定执行超时时间

    在某些情况下(例如通过网络访问数据),常常不希望程序卡住而占用太多时间以至于造成界面假死. 在这时.我们可以通过Thread.Thread + Invoke(UI)或者是 delegate.Begin ...

  9. -tableView: cellForRowAtIndexPath:方法不执行问题

    今天在学习UItableView 的时候,定义了一个属性 @property (weak, nonatomic) NSMutableArray *dataList: 在ViewDidLoad方法方法中 ...

随机推荐

  1. c# process 输入输出

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  2. 处理Selection对象和Range对象——Word VBA中重要的两个对象

    处理Selection对象和Range对象——Word VBA中重要的两个对象 Word 开发人员参考Selection 对象代表窗口或窗格中的当前所选内容.所选内容代表文档中选定(或突出显示)的区域 ...

  3. MongoDB之三(高级操作 聚合、游标)

    一: 聚合 常见的聚合操作跟sql server一样,有:count,distinct,group,mapReduce. <1> count count是最简单,最容易,也是最常用的聚合工 ...

  4. Android批量插入数据到SQLite数据库

    Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式 ...

  5. MySQL运行原理与基础架构

    1.MySQL基础 MySQL是一个开放源代码的关系数据库管理系统.原开发者为瑞典的MySQL AB公司,最早是在2001年MySQL3.23进入到管理员的视野并在之后获得广泛的应用. 2008年My ...

  6. c++ 11 key note

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  7. SharePoint服务器将连接配置数据库的连接字符串保存在什么地方?

    经常有人问我这个问题,SharePoint服务器将连接配置数据库的连接字符串保存在什么地方?虽然其他SharePoint服务器场设置都是保存到了配置数据库里面,但连接配置数据库本身的连接字符串,肯定是 ...

  8. Win7 64位 安装E10后 打不开的解决方案 -摘自网络

    但是后来发现点击IE图标没有任何反应,因此从网络上寻求帮助!将经验分享大家!进入注册表(运行regedit),找到 HKEY_CURRENT_USER\Software\Microsoft\Inter ...

  9. HDU 3392 Pie(DP)

    题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对.要求求出一种配对方法,使每一对的高度差的和最小. 思路:(我是真的笨笨笨!!)设人少的一组人数为n,b[],人多的一组人数为m,g ...

  10. JavaScript- The Good Parts Chapter 6

    Thee(你) I’ll chase(追逐:追捕) hence(因此:今后), thou(你:尔,汝) wolf in sheep’s array.—William Shakespeare, The ...