zoukankan      html  css  js  c++  java
  • spring 注解学习 二spring bean的生命周期

    1、Spring中bean的初始化与销毁方法

    spring的bean的生命周期大致可以分为以下部分:

    1、对象的创建:单实例的Bean在容器初始化时创建,多实例Bean在每次获取的时候

    2、属性的填充 populateBean

    3、Aware接口的调用

    4、BeanPostProcessor接口的postProcessBeforeInitialization调用

    5、生命周期初始化方法:对象创建完成,并填充完属性之后

    6、BeanPostProcessor接口的postProcessAfterInitialization调用

    7、使用bean

    8、生命周期销毁方法:单实例Bean在容器关闭时执行销毁方法,多实例的Bean是不放入容器中的,因此容器无法管理

    在XML文件中的bean标签中可以配置生命周期初始化方法与生命周期销毁方法

     <bean id="person" class="com.caopeng.bean.Person" destroy-method="init" init-method="destory"></bean>
    

    那么在注解版本中,也可以通过@Bean注解中的一些属性来配置

    1.1、类的定义

    public class Car {
    
        public Car() {
            System.out.println("constructor");
        }
    
        public void init(){
            System.out.println("init 方法");
        }
    
        public void destory(){
            System.out.println("destory 方法");
        }
    }
    

    1.2、java配置文件中注入Bean

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AppConfigOfLifeCycle {
    	//通过initMethod与destroyMethod方法来指定初始化与销毁方法
        @Bean(initMethod = "init",destroyMethod = "destory")
        public Car car(){
            return  new Car();
        }
    }
    

    1.3、测试

    public class DemoLifeCycle {
    
        @Test
        public void fun01(){
            AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(AppConfigOfLifeCycle.class);
            Object car = applicationContext.getBean("car");
           // 关闭容器
            applicationContext.close();
    
        }
    }
    

    1.4、运行结果

    constructor
    init 方法
    destory 方法
    

    如果把Car变成多实例Bean

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

    这样在容器关闭时就不会调用destory方法

    2、通过实现InitializingBean接口与DisposableBean接口

    2.1、InitializingBean

    package org.springframework.beans.factory;
    
    
    public interface InitializingBean {
    
    	void afterPropertiesSet() throws Exception;
    
    }
    

    2.2、DisposableBean

    package org.springframework.beans.factory;
    
    
    public interface DisposableBean {
    
    
    	void destroy() throws Exception;
    
    }
    

    2.3、示例

    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.stereotype.Component;
    
    @Component
    public class Cat implements InitializingBean, DisposableBean {
        @Override
        public void destroy() throws Exception {
            System.out.println("destroy");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("afterPropertiesSet");
        }
    }
    

    3、JSR250中的@PostConstruct与@PreDestroy注解

    @Component
    public class Dog {
    
        @PostConstruct
        public void init(){
            System.out.println("dog:init");
        }
    
        @PreDestroy
        public void destroy(){
            System.out.println("dog:destroy");
        }
    }
    

    4、BeanPostProcessor接口

    在bean填充完属性之后,还有一个方式可以初始化bean与销毁bean,就是定义一个实现BeanPostProcessor类。

    4.1、BeanPostProcessor接口说明

    package org.springframework.beans.factory.config;
    
    import org.springframework.beans.BeansException;
    import org.springframework.lang.Nullable;
    
    /**
     允许自定义修改新bean实例的工厂回调方法,例如,检查标记接口或用代理包装bean。
    
     ApplicationContext可以在其bean定义中自动检测出哪些是BeanPostProcessor类型的bean,并将这些后处理器应用于随后创建的任何bean。普通BeanFactory允许对后置处理器进行注册,将后置处理器应用于通过BeanFactory创建的所有bean。
    */
    public interface BeanPostProcessor {
    /*
    1、在新的Bean实例的任何的初始化回调方法(例如:InitializingBean接口的afterPropertiesSet方法 或者自定义的init-method)调用之前,调用postProcessBeforeInitialization方法。
    2、返回的实例可以是原来的对象 ,也可以是被包裹后的对象
    3、默认实现按原样返回给定bean。
    @param bean the new bean instance
    @param beanName the name of the bean
    @return the bean instance to use, either the original or a wrapped one;
    	 */
    	@Nullable
    	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    
    	/**
    1、在初始化方法调用之后调用postProcessAfterInitialization,在InitializingBean接口的afterPropertiesSet方法 或者自定义的init-method调用之后工作
    2、返回的实例可以是原来的对象 ,也可以是被包裹后的对象
    3、默认实现按原样返回给定bean。
     @param bean the new bean instance
     @param beanName the name of the bean
     @return the bean instance to use, either the original or a wrapped one;
    	
    	 */
    	@Nullable
    	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    
    }
    

    4.2、实例

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println(beanName+">>>BeanPostProcessor::postProcessBeforeInitialization");
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println(beanName+">>>BeanPostProcessor::postProcessAfterInitialization");
            return bean;
        }
    }
    

    4.3、运行结果

    appConfigOfLifeCycle>>>BeanPostProcessor::postProcessBeforeInitialization
    appConfigOfLifeCycle>>>BeanPostProcessor::postProcessAfterInitialization
    cat>>>BeanPostProcessor::postProcessBeforeInitialization
    Cat>>InitializingBean::afterPropertiesSet
    cat>>>BeanPostProcessor::postProcessAfterInitialization
    dog>>>BeanPostProcessor::postProcessBeforeInitialization
    dog:init
    dog>>>BeanPostProcessor::postProcessAfterInitialization
    Car::constructor
    car>>>BeanPostProcessor::postProcessBeforeInitialization
    Car::init 方法
    car>>>BeanPostProcessor::postProcessAfterInitialization
    Car::destory 方法
    dog:destroy
    Cat>>>DisposableBean::destroy
    

    BeanPostProcessor接口中的方法在spring中用户定义的所有bean都会起作用,而之前的三种配置方式只是针对特定的bean起作用

    5、初始化方法的调用顺序原理

    AbstractAutowireCapableBeanFactory类的createBean ->doCreateBean->populateBean以及initializeBean

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		}
    		else {
                //调用Aware接口
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
                //调用接口的前置方法postProcessBeforeInitialization
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
                //调用生命周期的初始化方法
    			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()) {
                 //调用接口的后置方法postProcessAfterInitialization
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    
    		return wrappedBean;
    	}
  • 相关阅读:
    R语言:常用统计检验
    用R语言的quantreg包进行分位数回归
    使用adagio包解决背包问题
    手机上的微型传感器
    JS常用字符串、数组的方法(备查)
    Threejs 纹理贴图2--凹凸贴图、法线贴图
    Three.js 纹理贴图1--旋转的地球
    Three.js 帧动画
    Three.js光源、相机知识梳理
    Three.js 点、线、网络模型及材质知识梳理
  • 原文地址:https://www.cnblogs.com/cplinux/p/14530462.html
Copyright © 2011-2022 走看看