我们知道,在spring bean生命周期中,我们可以在不同阶段执行处理器或者方法,比如init-method,destroy方法,BeanPostProcessor接口等。那么这些处理器或方法的执行顺序是怎样的,让我们用实际例子来观察。

package com.coshaho.learn.spring;

import java.util.HashMap;
import java.util.Map; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component; /**
*
* ASpringProcessor.java Create on 2017年10月17日 下午10:06:35
*
* 类功能说明: Spring处理器执行顺序
*
* Copyright: Copyright(c) 2013
* Company: COSHAHO
* @Version 1.0
* @Author coshaho
*/
@Component("springProcessor")
@DependsOn("dependsBean")
@ComponentScan("com.coshaho.learn.spring")
public class ASpringProcessor implements InitializingBean, DisposableBean, BeanNameAware
{
@Autowired
public BAutowiredBean autowiredBean; public ASpringProcessor()
{
System.out.println("SpringProcessor construct. x is " + x + ".");
} // BeanNameAware
public void setBeanName(String name)
{
System.out.println("Call BeanNameAware setBeanName, name is " + name + ", x is " + x + ".");
} // DisposableBean
public void destroy() throws Exception
{
System.out.println("Call DisposableBean destroy.");
} // InitializingBean
public void afterPropertiesSet() throws Exception
{
System.out.println("Call InitializingBean afterPropertiesSet.");
} @PostConstruct
public void postConstruct()
{
System.out.println("Call postConstruct method.");
} @PreDestroy
public void preDestroy()
{
System.out.println("Call preDestroy method.");
} public void initMethod()
{
System.out.println("Call manually initMethod.");
} public void destroyMethod()
{
System.out.println("Call manually destroyMethod.");
} public void sayHello()
{
System.out.println("Hello, Spring.");
} @Value("cauchy")
private String x;
public void setX(String x)
{
this.x = x;
} public static void main(String[] args) throws Exception
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");
ASpringProcessor springBean = (ASpringProcessor)context.getBean("springProcessor");
springBean.sayHello();
context.close(); System.out.println(); // 创建一个BeanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.addBeanPostProcessor(new EBeanPostProcessor()); // 构造一个BeanDefinition
AnnotatedGenericBeanDefinition beanDefinition=new AnnotatedGenericBeanDefinition(ASpringProcessor.class);
beanDefinition.setInitMethodName("initMethod");
beanDefinition.setDestroyMethodName("destroyMethod"); // 设置这个bean的属性
Map<String, Object> map = new HashMap<String, Object>();
map.put("x", "coshaho");
beanDefinition.setPropertyValues(new MutablePropertyValues(map)); // 注册BeanDefinition
factory.registerBeanDefinition("springProcessor", beanDefinition); // 执行获取和销毁bean的方法
factory.getBean("springProcessor");
factory.destroySingleton("springProcessor");
}
} package com.coshaho.learn.spring; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; class EBeanPostProcessor implements BeanPostProcessor
{
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
{
System.out.println("MyBeanPostProcessor postProcessBeforeInitialization.");
return bean;
} public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
{
System.out.println("MyBeanPostProcessor postProcessAfterInitialization.");
return bean;
}
}
package com.coshaho.learn.spring;

import org.springframework.stereotype.Service;

@Service
public class BAutowiredBean
{
public BAutowiredBean()
{
System.out.println("AutowiredBean construct.");
} } package com.coshaho.learn.spring; import org.springframework.stereotype.Service; @Service("dependsBean")
public class CDependsBean
{
public CDependsBean()
{
System.out.println("DependsBean construct.");
} }

执行结果

Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7cef4e59: startup date [Tue Oct 17 18:18:23 GMT+08:00 2017]; root of context hierarchy
Loading XML bean definitions from class path resource [spring.xml]
DependsBean construct.
SpringProcessor construct. x is null.
AutowiredBean construct.
Call BeanNameAware setBeanName, name is springProcessor, x is cauchy.
Call postConstruct method.
Call InitializingBean afterPropertiesSet.
Hello, Spring.
Closing org.springframework.context.support.ClassPathXmlApplicationContext@7cef4e59: startup date [Tue Oct 17 18:18:23 GMT+08:00 2017]; root of context hierarchy
Call preDestroy method.
Call DisposableBean destroy. SpringProcessor construct. x is null.
Call BeanNameAware setBeanName, name is springProcessor, x is coshaho.
MyBeanPostProcessor postProcessBeforeInitialization.
Call InitializingBean afterPropertiesSet.
Call manually initMethod.
MyBeanPostProcessor postProcessAfterInitialization.
Call DisposableBean destroy.
Call manually destroyMethod.

可以看出来,spring bean加载顺序如下

1. 初始化depends bean;

2. 执行bean构造方法;

3. 初始化依赖注入bean;

4. 其他属性赋值;

5. 执行BeanNameAware接口的setBeanName方法;

6. 执行BeanPostProcessor接口postProcessBeforeInitialization方法;

7. 执行@PostConstruct注解方法;

8. 执行InitializingBean接口的afterPropertiesSet方法;

9. 执行init-method方法;

10. 执行BeanPostProcessor接口postProcessAfterInitialization方法;

11. 执行@PreDestroy注解方法;

12. 执行DisposableBean接口的destroy方法;

13. 执行destroy-method方法。

Spring源码阅读(四)的更多相关文章

  1. 40 网络相关函数(八)——live555源码阅读(四)网络

    40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...

  2. 39 网络相关函数(七)——live555源码阅读(四)网络

    39 网络相关函数(七)——live555源码阅读(四)网络 39 网络相关函数(七)——live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...

  3. 38 网络相关函数(六)——live555源码阅读(四)网络

    38 网络相关函数(六)——live555源码阅读(四)网络 38 网络相关函数(六)——live555源码阅读(四)网络 简介 12)makeSocketNonBlocking和makeSocket ...

  4. 37 网络相关函数(五)——live555源码阅读(四)网络

    37 网络相关函数(五)——live555源码阅读(四)网络 37 网络相关函数(五)——live555源码阅读(四)网络 简介 10)MAKE_SOCKADDR_IN构建sockaddr_in结构体 ...

  5. 36 网络相关函数(四)——live555源码阅读(四)网络

    36 网络相关函数(四)——live555源码阅读(四)网络 36 网络相关函数(四)——live555源码阅读(四)网络 简介 7)createSocket创建socket方法 8)closeSoc ...

  6. 35 网络相关函数(三)——live555源码阅读(四)网络

    35 网络相关函数(三)——live555源码阅读(四)网络 35 网络相关函数(三)——live555源码阅读(四)网络 简介 5)NoReuse不重用地址类 6)initializeWinsock ...

  7. 34 网络相关函数(二)——live555源码阅读(四)网络

    34 网络相关函数(二)——live555源码阅读(四)网络 34 网络相关函数(二)——live555源码阅读(四)网络 2)socketErr 套接口错误 3)groupsockPriv函数 4) ...

  8. 33 网络相关函数(一)——live555源码阅读(四)网络

    33 网络相关函数(一)——live555源码阅读(四)网络 33 网络相关函数(一)——live555源码阅读(四)网络 简介 1)IsMulticastAddress多播(组播)地址判断函数 多播 ...

  9. 32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络

    32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络 32 GroupSock(AddressPortLookupTable)——live555 ...

  10. 31 GroupSock(AddressString)——live555源码阅读(四)网络

    31 GroupSock(AddressString)——live555源码阅读(四)网络 31 GroupSock(AddressString)——live555源码阅读(四)网络 简介 Addre ...

随机推荐

  1. 【Python基础】Pycharm默认快捷键

    PyCharm常用快捷键和设置 代码快速运行: Alt+Shift+F10  编辑代码的时候经常的要换下一行,但是光标没有在行末,可以用这个命令直接换行: Shift+Enter 行注释/取消行注释: ...

  2. scss是什么?在vue.cli中的安装使用步骤是?有哪几大特性?

    css的预编译: 使用步骤: 第一步:用npm下三个loader(sass-loader.css-loader.node-sass): 第二步:在build目录找到webpack.base.confi ...

  3. oracle闪回的使用

    1.闪回查询(原理:依赖于UNDO表空间)查询当前SCN号select current_scn from v$database;误删数据以后select * from table_name as of ...

  4. Verilog如何从外部更改模块内参数

    例如有一个模块 module x(a,b,c); input a,b; output c; 'd0, h=9'd3; ...... endmodule 两种解决方法: 1.使用带有参数值的模块实例语句 ...

  5. python基于django编写api+前端后端分离

    有用 https://segmentfault.com/a/1190000016049962#articleHeader2 python的前后端分离(一):django+原生js实现get请求 htt ...

  6. CentOS+Uwsgi+Nginx发布Flask开发的WebAPI

    1.WebAPI 开发工具VS 于Windows环境中开发完成后使用SFTP进行同步文件到Centos中使用 2.重点:WebAPI触发的方法是为了发送Celery异步调度任务 Celery框架使用涉 ...

  7. 火币网API文档——REST API 错误码

    错误码 行情 API 错误码 错误码 描述 bad-request 错误请求 invalid-parameter 参数错 invalid-command 指令错 code 的具体解释, 参考对应的er ...

  8. 006-Object.assign

    一.Object.assign简要使用 是ES6新添加的接口,主要的用途是用来合并多个JavaScript的对象. Object.assign()接口可以接收多个参数,第一个参数是目标对象,后面的都是 ...

  9. centOS和windows7双系统下重装windows后恢复centOS引导

    电脑原本是windows7和centOS双系统,后来重装windows系统后,发现没有centOS引导,于是重新恢复centOS引导. 1.官网下载centos系统镜像CentOS-7-x86_64- ...

  10. Flappy Bird

    在网上学习了下“65行 JavaScript 代码实现 Flappy Bird 游戏”(http://blog.jobbole.com/61842/),main.js 如下: // Initializ ...