Spring源码阅读(四)
我们知道,在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源码阅读(四)的更多相关文章
- 40 网络相关函数(八)——live555源码阅读(四)网络
40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...
- 39 网络相关函数(七)——live555源码阅读(四)网络
39 网络相关函数(七)——live555源码阅读(四)网络 39 网络相关函数(七)——live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...
- 38 网络相关函数(六)——live555源码阅读(四)网络
38 网络相关函数(六)——live555源码阅读(四)网络 38 网络相关函数(六)——live555源码阅读(四)网络 简介 12)makeSocketNonBlocking和makeSocket ...
- 37 网络相关函数(五)——live555源码阅读(四)网络
37 网络相关函数(五)——live555源码阅读(四)网络 37 网络相关函数(五)——live555源码阅读(四)网络 简介 10)MAKE_SOCKADDR_IN构建sockaddr_in结构体 ...
- 36 网络相关函数(四)——live555源码阅读(四)网络
36 网络相关函数(四)——live555源码阅读(四)网络 36 网络相关函数(四)——live555源码阅读(四)网络 简介 7)createSocket创建socket方法 8)closeSoc ...
- 35 网络相关函数(三)——live555源码阅读(四)网络
35 网络相关函数(三)——live555源码阅读(四)网络 35 网络相关函数(三)——live555源码阅读(四)网络 简介 5)NoReuse不重用地址类 6)initializeWinsock ...
- 34 网络相关函数(二)——live555源码阅读(四)网络
34 网络相关函数(二)——live555源码阅读(四)网络 34 网络相关函数(二)——live555源码阅读(四)网络 2)socketErr 套接口错误 3)groupsockPriv函数 4) ...
- 33 网络相关函数(一)——live555源码阅读(四)网络
33 网络相关函数(一)——live555源码阅读(四)网络 33 网络相关函数(一)——live555源码阅读(四)网络 简介 1)IsMulticastAddress多播(组播)地址判断函数 多播 ...
- 32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络
32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络 32 GroupSock(AddressPortLookupTable)——live555 ...
- 31 GroupSock(AddressString)——live555源码阅读(四)网络
31 GroupSock(AddressString)——live555源码阅读(四)网络 31 GroupSock(AddressString)——live555源码阅读(四)网络 简介 Addre ...
随机推荐
- webpack中loader和plugin的概念理解
对于 loader ,它就是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将 A.scss 或 A.less 转变成 B.css,单纯的文件转换过程: 对于 plugin,它就是一个扩 ...
- Python3学习之路~6.2 实例演示面向对象编程的好处
首先建一个dog类,实例化为3个dog对象,并让它们都叫. class Dog: def bulk(self): print("xiaohuang:wang wang wang !" ...
- js将字符串转换成json的三种方式
1,js自带的eval函数,其中需要添加小括号eval('('+str+')'); function strToJson(str){ var json = eval('(' + str + ')'); ...
- 发现Boost官方文档的一处错误(numpy的ndarray)
文档位置:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/numpy/tutorial/ndarray.html shape在这里 ...
- python-->(set /dict)交集 差集 并集 补集(功能用来做交差并补的)
# ### 集合 作用:交集 差集 并集 补集(功能用来做交差并补的) '''特征:自动去重 无序''' #定义一个空集合 setvar = set() #set()强制转换成一个空集合的数据类型 p ...
- 微信小程序:wx.navigateBack页面返回传参
场景(比如:商城选地址,选优惠券): 在[页面A]中调用wx.navigateTo方法跳转到[页面B] 然后从[页面B]返回[页面A], 并将[页面B]中的一些数据传回[页面A] wx.navigat ...
- Struct2中自定义的Filter无效
解决办法,把自定义的Filter配置放在struct2前 <?xml version="1.0" encoding="UTF-8"?> <we ...
- python Rpyc简单使用
客户端可以直接调用服务端代码. rpycserver #!/usr/bin/env python #coding:utf-8 from rpyc.core.service import SlaveSe ...
- React对比Vue(06 路由的对比)
其实差不多, 都需要先安装路由 React 先安装 cnpm install react-router-dom --save 在再根组件引入 import { BrowserRouter as Ro ...
- cocos2d JS 本地缓存存储登陆记住账号密码->相当于C++中的UserDefault
在cocos-js 3.0以上的版本中,当我们用到本地存储的时候,发现以前用到的UserDefault在JS中并没有导出,而是换成了LocalStorage. 在LocalStorage.h文件中我们 ...