我们知道,在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. C#图解:第七章

    C#图解第七章:类和继承 1.类继承 通过继承我们可以定义一个新类,新类纳入一个已经声明的类并进行扩展. 1.可以使用- 一个已经存在的类作为新类的基础..已存在的类称为基类(baseclass),新 ...

  2. 20171129 ASP.NET中使用Skin文件

    在Web.config里加入<pages styleSheetTheme="DefSkin"/>再在App_Themes文件夹里建个DefSkin文件夹把css和Ski ...

  3. 【CART与GBDT】

    一.CART(分类回归树)    1.思想:     一种采用基尼信息增益作为划分属性的二叉决策树.基尼指数越小,表示纯度越高.  2.回归: 每个节点都有一个预测值,预测值等于属于该节点的所有样例的 ...

  4. Cglib动态代理实现原理

    Cglib动态代理实现方式 我们先通过一个demo看一下Cglib是如何实现动态代理的. 首先定义个服务类,有两个方法并且其中一个方法用final来修饰. public class PersonSer ...

  5. nginx 部署web页面问题

    nginx 部署web页面的时候,路径都是对的,但是css文件就是不起作用,控制台提示如下,原来是格式的问题,截图如下: css 被转成了application/octet-stream,这个是ngi ...

  6. [py]数据结构和算法-冒泡排序

    用Python实现的数据结构与算法 数据结构和算法可以培养一个人的逻辑思维(推荐几本书) 逻辑思维培养 严蔚敏的数据结构(排序 查找 列表 堆栈 队列 树的简单部分) 大话数据结构 数据结构与算法分析 ...

  7. 【UML】NO.49.EBook.5.UML.1.009-【UML 大战需求分析】- 包图(Package Diagram)

    1.0.0 Summary Tittle:[UML]NO.49.EBook.1.UML.1.009-[UML 大战需求分析]- 包图(Package Diagram) Style:DesignPatt ...

  8. 【LeetCode每天一题】Divide Two Integers(两整数相除)

    Given two integers dividend and divisor, divide two integers without using multiplication, division ...

  9. 解决异地服务器接口访问跨域,node构建反向代理

    跨域对于前端来说是一个老大难的问题,许多方法如jsonp.document.domain + iframe...都有或多或少的问题,一个最佳实践就是通过服务器nginx做反向代理,但奈何不懂相关知识, ...

  10. mysql 增加列,修改列名、列属性,删除列语句

    mysql增加列,修改列名.列属性,删除列语句 mysql修改表名,列名,列类型,添加表列,删除表列     alter table test rename test1; --修改表名 alter t ...