上面兩篇文章分別介紹了spring生命週期中初始化和銷燬的幾種方式以及統一後置BeanPostProcessor接口的使用,可以點擊以下鏈接查看:
今天我們就來一起看看spring底層是如何實現這些的,在看它的實現原理之前,我們再來把之前幾種方式結合放一個例子中演示下
新建一個User1對象如下:
/**
* 定義一個實現InitializingBean DisposableBean的bean
*
* @author zhangqh
* @date 2018年5月4日
*/
public class User1 implements InitializingBean,DisposableBean{
public User1(){
System.out.println("實例化User1的構造方法......");
}
public void destroy() throws Exception {
System.out.println("調用實現DisposableBean的destroy方法....");
}
public void afterPropertiesSet() throws Exception {
System.out.println("調用實現InitializingBean的afterPropertiesSet方法......");
}
public void initUser(){
System.out.println("執行initMethod方法.....");
}
public void destroyUser(){
System.out.println("執行destroyMethod方法......");
}
}
新建一個MyBeanPostProcessor實現BeanPostProcessor如下:
/**
* 定義一個前置後置處理器
*
* @author zhangqh
* @date 2018年5月6日
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// 這邊只做簡單打印 原樣返回bean
System.out.println("postProcessBeforeInitialization===="+beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
// 這邊只做簡單打印 原樣返回bean
System.out.println("postProcessAfterInitialization===="+beanName);
return bean;
}
}
主配置文件如下:
/**
* 定義一個註解配置文件 必須要加上@Configuration註解
*
* @author zhangqh
* @date 2018年4月30日
*/
@Configuration
public class MainConfig {
@Bean(initMethod="initUser",destroyMethod="destroyUser")
public User1 getUser1(){
return new User1();
}
@Bean
public MyBeanPostProcessor getMyBeanPostProcessor(){
return new MyBeanPostProcessor();
}
}
測試代碼如下:
public static void main(String[] args) {
// 使用AnnotationConfigApplicationContext獲取spring容器ApplicationContext2
AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);
applicationContext2.close();
}
運行結果如下:
實例化User1的構造方法......
postProcessBeforeInitialization====getUser1
調用實現InitializingBean的afterPropertiesSet方法......
執行initMethod方法.....
postProcessAfterInitialization====getUser1
調用實現DisposableBean的destroy方法....
執行destroyMethod方法......
從結果中可以看出他們之前執行的順序如下:注意其中的位置序號下邊文章會用到
1,首先執行bean的構造方法,
2,BeanPostProcessor的postProcessBeforeInitialization方法
3,InitializingBean的afterPropertiesSet方法
4,@Bean註解的initMethod方法
5,BeanPostProcessor的postProcessAfterInitialization方法
6,DisposableBean的destroy方法
7,@Bean註解的destroyMethod方法
接下來我們再來看看spring底層的實現,首先進入程序的啓動類AnnotationConfigApplicationContext方法如下:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
裏邊有兩個方法一個是register註冊對應的java配置類和另一個是refresh方法,我們重點來看這個refresh方法如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 省略大部分代碼
// 實例化所有的不是延遲加載(延遲加載的只有在使用的時候纔會實例化)的bean實例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}catch (BeansException ex) {
// 省略部分代碼
}finally {
resetCommonCaches();
}
}
}
接下來我們重點來看下finishBeanFactoryInitialization實例化bean的方法,進去之後我們發現最後有一個preInstantiateSingletons方法如下:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 省略大部分代碼
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
繼續查看preInstantiateSingletons對應實現如下:
@Override
public void preInstantiateSingletons() throws BeansException {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 循環所有的bean實例化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 獲取bean方法
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
// 省略部分代碼
}
我們發現裏邊的關鍵方法getBean如下:
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
繼續跟進去如下:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 檢查緩存中是否已經存在了bean實例.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {
// 省略部分代碼。。。。。
try {
// 省略部分代碼。。。。。
// 判斷bean是否配置的是單實例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}// bean配置的是多實例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {// 既不是單實例也不是多實例的邏輯
// 省略部分代碼。。。。。
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 省略部分代碼。。。。。
return (T) bean;
}
接下來重點看一下其中創建bean的方法createBean如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 省略部分代碼
// 重點注意doCreateBean方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
繼續跟進可以看到doCreateBean方法如下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// 省略部分代碼
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 省略部分代碼......
// Register bean as disposable.
// 注意這個地方 下面講銷燬的時候說講到
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
可以發現其中有一個initializeBean方法如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 省略部分代碼。。。。
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 重點來了BeanPostProcessor的postProcessBeforeInitialization方法執行的地方
// 這也是爲什麼他執行所有的初始化之前的原因了
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 初始化bean
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor的PostProcessorsAfterInitialization方法執行的地方
// 初始化完成之後執行BeanPostProcessor的postProcessorsAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
到這BeanPostProcessor的實現已經很清晰了吧,BeanPostProcessor的postProcessBeforeInitialization(方法位置2)和BeanPostProcessor的postProcessAfterInitialization(方法位置5)的執行位置我們搞清楚了,那上面的位置3和位置4又是怎麼執行的呢,讓我們繼續到invokeInitMethods裏邊看看如下:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 位置3的 InitializingBean的afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
// 位置4的 @Bean註解的initMethod方法
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
聰明的你應該一眼就能看到位置3,以及位置4的執行順序了吧
好了初始化的邏輯部分搞清楚了,接下來我們一起來看看銷燬的流程,銷燬開始於applicationContext.close();方法,點進去看如下:
@Override
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
看到其中有一個doClose繼續跟進去看會發現有一個destroyBeans方法,再進去直到找到destroySingletons方法如下:
public void destroySingletons() {
// 省略部分代碼
// 循環所有的disposableBean執行對應的destroy方法
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
// 省略部分代碼
}
在繼續從destroySingleton方法進去可以找到destroyBean方法如下:
protected void destroyBean(String beanName, DisposableBean bean) {
// 省略部分代碼
// 重點的地方到了 執行DisposableBean 中的destroy 也就是位置6 中對應的打印
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
}
}
// 省略部分代碼
}
到這裏我們已經完成了90%的原理分析了,這個時候細心的你一定會發現那位置7中的@Bean註解中配置的destroyMethod是在什麼時候調用的呢,好像上面都沒有講到,要想知道destroyMethod的調用讓我們回到上面講bean初始化中的doCreateBean方法中其中有一個registerDisposableBeanIfNecessary方法進去看如下:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
// 關鍵代碼
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
繼續進去到DisposableBeanAdapter類如下:
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List<BeanPostProcessor> postProcessors, AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean =
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
this.destroyMethod = determineDestroyMethod();
if (this.destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
else {
Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
}
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
怎麼樣,到現在是不是就很清晰了,位置7的打印其實也是DisposableBean方法中打印出來的,@bean註解的destroyMethod其實是在初始化的時候轉換成DisposableBean的實現放入到了disposableBeans中
到此今天所有內容就到此結束了,最後以一張流程圖總結下如下:
以上是今天文章的所有內容,歡迎大家吐槽
推薦閱讀
更多優質文章請關注以下公衆號查閱: