我们知道,在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. webpack中loader和plugin的概念理解

    对于 loader ,它就是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将 A.scss 或 A.less 转变成 B.css,单纯的文件转换过程: 对于 plugin,它就是一个扩 ...

  2. Python3学习之路~6.2 实例演示面向对象编程的好处

    首先建一个dog类,实例化为3个dog对象,并让它们都叫. class Dog: def bulk(self): print("xiaohuang:wang wang wang !" ...

  3. js将字符串转换成json的三种方式

    1,js自带的eval函数,其中需要添加小括号eval('('+str+')'); function strToJson(str){ var json = eval('(' + str + ')'); ...

  4. 发现Boost官方文档的一处错误(numpy的ndarray)

    文档位置:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/numpy/tutorial/ndarray.html shape在这里 ...

  5. python-->(set /dict)交集 差集 并集 补集(功能用来做交差并补的)

    # ### 集合 作用:交集 差集 并集 补集(功能用来做交差并补的) '''特征:自动去重 无序''' #定义一个空集合 setvar = set() #set()强制转换成一个空集合的数据类型 p ...

  6. 微信小程序:wx.navigateBack页面返回传参

    场景(比如:商城选地址,选优惠券): 在[页面A]中调用wx.navigateTo方法跳转到[页面B] 然后从[页面B]返回[页面A], 并将[页面B]中的一些数据传回[页面A] wx.navigat ...

  7. Struct2中自定义的Filter无效

    解决办法,把自定义的Filter配置放在struct2前 <?xml version="1.0" encoding="UTF-8"?> <we ...

  8. python Rpyc简单使用

    客户端可以直接调用服务端代码. rpycserver #!/usr/bin/env python #coding:utf-8 from rpyc.core.service import SlaveSe ...

  9. React对比Vue(06 路由的对比)

    其实差不多, 都需要先安装路由 React  先安装 cnpm install react-router-dom --save 在再根组件引入 import { BrowserRouter as Ro ...

  10. cocos2d JS 本地缓存存储登陆记住账号密码->相当于C++中的UserDefault

    在cocos-js 3.0以上的版本中,当我们用到本地存储的时候,发现以前用到的UserDefault在JS中并没有导出,而是换成了LocalStorage. 在LocalStorage.h文件中我们 ...