1. 程式人生 > >【Spring註解】2、Bean生命週期

【Spring註解】2、Bean生命週期

1、初始化和銷燬

  • 通過@Bean註解的initMethoddestroyMethod屬性

  • InitializingBean介面、DisposableBean介面

  • 可以使用JSR250:

    • @PostConstruct:在Bean建立完成並且屬性值完成後,執行初始化。

    • @PreDestroy:在容器銷燬Bean之前,通知進行清理工作。

  • 使用Spring的BeanPostProcessor介面

 

1.1、通過@Bean註解的initMethod和destroyMethod屬性

//bean類
public class Car {

	public Car(){
		System.out.println("car constructor...");
	}
	
	public void init(){
		System.out.println("car init...");
	}
	
	public void destroy(){
		System.out.println("car destroy...");
	}
}

通過@Bean註解的initMethoddestroyMethod屬性

/**
 * bean的生命週期:
 * 	bean建立---初始化---銷燬的過程
 * 
 * 容器管理bean的生命週期
 * 我們可以自定義初始化和銷燬方法:容器在bean進行到生命週期的時候來呼叫我們自定義的初始化和銷燬方法
 * 
 * 構造:
 * 		單例項:在容器啟動的時候建立物件
 * 		多例項:在每次獲取的時候建立物件
 * 初始化:
 * 		物件建立完成後,呼叫初始化方法
 * 銷燬:
 * 		單例項:容器關閉的時候
 * 		多例項:容器不會管理這個bean,所以容器不會呼叫銷燬方法
 * 
 * 1)、指定初始化和銷燬方法:
 * 		通過@Bean指定init-method和destroy-method
 * 
 * @author Cay
 * @date 2018年8月25日 下午5:18:43
 */
@Configuration
public class MyConfigOfLifeCycle {

	@Bean(initMethod="init", destroyMethod="destroy")
	public Car car(){
		return new Car();
	}
}

測試:

public class TestLifeCycle {

	@Test
	public void test1(){
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfLifeCycle.class);
		System.out.println("容器建立完成...");
		
		applicationContext.close();
	}
}

單例項bean的初始化和銷燬測試結果:

@Bean(initMethod="init", destroyMethod="destroy")
public Car car(){
    return new Car();
}


@Scope("prototype")
@Bean(initMethod="init", destroyMethod="destroy")
public Car car(){
    return new Car();
}

 多例項bean的初始化和銷燬測試結果:

 對比兩圖可以看出,單例項bean和多例項bean在初始化和銷燬時的不同。

 

1.2、InitializingBean介面、DisposableBean介面

通過讓Bean實現InitializingBean介面實現初始化邏輯,實現DisposableBean介面實現銷燬邏輯。

public class Cat implements InitializingBean, DisposableBean{

	public Cat(){
		System.out.println("cat constructor...");
	}

	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("cat destroy...");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("cat init...");
	}
}

1.3、@PostConstruct、@PreDestroy

  • @PostConstruct:在Bean建立完成並且屬性值完成後,執行初始化。

  • @PreDestroy:在容器銷燬Bean之前,通知進行清理工作。

public class Dog {

	public Dog(){
		System.out.println("dog constructor...");
	}
	
	//物件建立並賦值之後呼叫
	@PostConstruct
	public void init(){
		System.out.println("dog init...");
	}
	
	@PreDestroy
	public void destroy(){
		System.out.println("dog destroy...");
	}
}

 

1.4、Spring的BeanPostProcessor介面

BeanPostProcessor是bean的後置處理器:

  • 在bean初始化前後進行一些處理工作:

  • postProcessBeforeInitialization:在初始化之前

  • postProcessAfterInitialization:在初始化之後

@Component
public class MyBeanPostProcessor implements BeanPostProcessor{

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeforeInitialization..." + beanName + "=>" + bean);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessAfterInitialization..." + beanName + "=>" + bean);
		return bean;
	}

}

BeanPostProcessor原理:

  • AbstractAutowireCapableBeanFactory#configureBean
public Object configureBean(Object existingBean, String beanName) throws BeansException {
    markBeanAsCreated(beanName);
    BeanDefinition mbd = getMergedBeanDefinition(beanName);
    RootBeanDefinition bd = null;
    if (mbd instanceof RootBeanDefinition) {
        RootBeanDefinition rbd = (RootBeanDefinition) mbd;
        bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());
    }
    if (!mbd.isPrototype()) {
        if (bd == null) {
            bd = new RootBeanDefinition(mbd);
        }
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader());
    }
    //生成bean的包裝物件,並初始化包裝類
    BeanWrapper bw = new BeanWrapperImpl(existingBean);
    initBeanWrapper(bw);
    //給bean進行賦值
    populateBean(beanName, bd, bw);
    //初始化bean
    return initializeBean(beanName, existingBean, bd);
}
  • AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    //other...

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //呼叫applyBeanPostProcessorsBeforeInitialization方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //呼叫init方法
        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()) {
        //呼叫applyBeanPostProcessorsAfterInitialization方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
  • AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        //呼叫每個BeanPostProcessor實現類的postProcessBeforeInitialization方法
        result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}
  • AbstractAutowireCapableBeanFactory#invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
		throws Throwable {

    //判斷bean是否實現了InitializingBean介面
    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實現類的afterPropertiesSet方法
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            //呼叫InitializingBean實現類的afterPropertiesSet方法
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}
  • AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    //呼叫每個BeanPostProcessor實現類的postProcessAfterInitialization方法
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

 

====================打個廣告,歡迎關注====================

QQ:

412425870

微信公眾號:Cay課堂

csdn部落格:

http://blog.csdn.net/caychen

碼雲:

https://gitee.com/caychen/

github:

https://github.com/caychen

點選群號或者掃描二維碼即可加入QQ群:

328243383(1群)

 

點選群號或者掃描二維碼即可加入QQ群:
180479701(2群)

--------------------- 作者:caychen 來源:CSDN 原文:https://blog.csdn.net/caychen/article/details/83008897?utm_source=copy 版權宣告:本文為博主原創文章,轉載請附上博文連結!