Spring 生命周期

参考文章:

https://blog.csdn.net/qq_23473123/article/details/76610052

https://www.cnblogs.com/zrtqsk/p/3735273.html

https://blog.csdn.net/w_linux/article/details/80086950

Spring容器介绍

在IoC容器启动之后,Spring加载分析XML配置信息解析,并将其封装到BeanDefinition对象中保存到Map<beanid,BeanDefinition>中,但是并不会马上就实例化相应的bean。此时容器仅仅拥有所有Bean的BeanDefinition(BeanDefinition:各个Bean的配置信息对象。是容器依赖某些工具加载的XML配置信息进行解析和分析,并将分析后的信息编组为相应的BeanDefinition中)。只有当getBean()调用时或被其他要实例化的Bean依赖注入时,才是有可能触发Bean实例化阶段的活动。

为什么说有可能触发Bean实例化阶段?因为当对应某个bean定义的getBean()方法第一次被调用时,不管是显示的还是隐式的,Bean实例化阶段才会被触发,第二次被调用则会直接返回容器缓存的第一次实例化完的对象实例(因为默认是singleton单例,当然,这里的情况prototype类型的bean除外)

 

各种生命周期接口分类

Spring框架提供丰富的接口和生命周期方法,使开发者在不修改Spirng框架的基础上,对Sping进行改造,影响执行流程。满足开闭原则

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

1、Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法

2、Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

4、容器级工厂后处理器接口方法:这个包括了BeanFactoryPostProcessor、AspectJWeavingEnabler,、ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。在应用上下文装配配置文件之后立即调用。

容器级Bean:监控整个容器的其他Bean。实现此类接口的Bean在IoC容器启动BeanFactory实例化之后会立即实例化。此类型的Bean理论上来说容器中相同功能的存在一个Bean即可。

 

下图可见:Spring Bean的完整生命周期从创建Spring-IoC容器开始,直到最终Spring容器销毁Bean

红色的容器级生命周期接口的Bean会在其他Bean实例化之前实例化。因为他们的功能是监控整个容器的Bean。

绿色为Bean级生命周期接口

蓝色为Bean自身的方法

 

各个接口详细使用样例https://blog.csdn.net/qq_23473123/article/details/76610052

 

 

现在开始初始化容器
2014-5-18 15:46:20 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19a0c7c: startup date [Sun May 18 15:46:20 CST 2014]; root of context hierarchy
2014-5-18 15:46:20 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [springBeanTest/beans.xml]
【BeanFactoryPostProcessor接口】实现类实例化!
【BeanFactoryPostProcessor接口】调用postProcessBeanFactory方法
【BeanPostProcessor接口】实现类实例化!
【InstantiationAwareBeanPostProcessorAdapter】子类实例化!
2014-5-18 15:46:20 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9934d4: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,person]; root of factory hierarchy
【InstantiationAwareBeanPostProcessor接口】调用postProcessBeforeInstantiation方法
【构造器】调用bean Person 的构造器实例化
【InstantiationAwareBeanPostProcessor接口】调用postProcessPropertyValues方法
【注入属性】注入属性address (注入XML中配置bean的属性,Spring通过反射调用bean的setter())
【注入属性】注入属性name 
【注入属性】注入属性phone
【BeanNameAware接口】调用BeanNameAware.setBeanName()
【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
【BeanPostProcessor接口】方法postProcessBeforeInitialization对属性进行更改!
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
【BeanPostProcessor接口】方法postProcessAfterInitialization对属性进行更改!
【InstantiationAwareBeanPostProcessor接口】调用postProcessAfterInitialization方法
容器初始化成功
Person [address=广州, name=张三, phone=110]
现在开始关闭容器!
【DiposibleBean接口】调用DiposibleBean.destory()
【destroy-method】调用<bean>的destroy-method属性指定的初始化方法

 

容器级BeanFactoryPostProcessor接口Bean(1个方法)

BeanFactory后处理器,其作用是在BeanFactory容器构建好后,执行postProcessBeanFactory得到BeanFactory对象。通过BeanFactory对象可以得到容器各个Bean的BeanDefinition(Bean的配置信息对象)。

@Component
public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor {

    private static Log log = LogFactory.getLog(BeanFactoryPostProcessorImpl.class);

    public BeanFactoryPostProcessorImpl() {
        super();
        log.info("bean工厂后处理器实例化");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {

        log.info("取得BeanFactory容器");
        log.info("通过BeanFactory容器 ,取得 bean-id==test 的 BeanDefinition ");
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("test");

        log.info("修改beanDefinition属性值");
        beanDefinition.getPropertyValues().addPropertyValue("address", "110");//address是test的属性

    }
}

容器级InstantiationAwareBeanPostProcessor接口Bean(3个方法)

https://www.jianshu.com/p/cee031ddae72

Bean实例化后处理器,其继承BeanPostProcessor接口

监控整个容器中各个Bean对象的实例化前后初始化后。一般我们继承Spring为其提供的适配器类InstantiationAwareBeanPostProcessorAdapter来使用它。

方法postProcessPropertyValues用来操作属性,在bean实例化后执行,返回值也应该是PropertyValues对象。@Autowire就是AutowiredAnnotationBeanPostProcessor此方法注入。

 

public class MyInstantiationAwareBeanPostProcessor extends  
        InstantiationAwareBeanPostProcessorAdapter {  
  
    public MyInstantiationAwareBeanPostProcessor() {  
        super();  
        System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");  
    }  
  
    // 接口方法、实例化Bean之前调用  
    @Override  
    public Object postProcessBeforeInstantiation(Class beanClass,  
            String beanName) throws BeansException {  
       
            System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");  
            return null;  
    }  

   // 接口方法、实例化后执行
    @Override  
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,  
            PropertyDescriptor[] pds, Object bean, String beanName)  
            throws BeansException {  
        //@AutoWired依赖注入在此处实现
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法"); 
        return pvs;  
    }  
     
  
    // 接口方法、初始化Bean之后调用  
    @Override  
    public Object postProcessAfterInitialization(Object bean, String beanName)  
            throws BeansException {  
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");  
        return bean;  
    }  
  
       
}

 

容器级BeanPostProcessor接口Bean(2个方法)

Bean后处理器,监控整个容器中各个Bean对象的实例化之后在初始化前后,容器中要执行或已完成初始化的Bean实例都会被Spring传递到BeanPostProcessor处理器中。可以在此处修改Bean的属性或为Bean生成包装/代理对象。

AOP就是在postProcessAfterInitialization中生成代理对象,替换原容器的Bean。

@Component
public class BeanPostProcessorImpl implements BeanPostProcessor {

    private static Log log = LogFactory.getLog(BeanPostProcessorImpl.class);

    public  BeanPostProcessorImpl(){
        super();
        log.info("这是BeanPostProcessorImpl实现类的实例化,bean后处理器");
    }

    @Nullable
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("对初始化之前的Bean进行处理,beanName:"+beanName);
        //容器中每一个Bean对象初始化前,都会传递进入此方法

        //拿到bean的对象引用可以直接修改其属性
        Student stu = null;
	    if("student".equals(beanname) || bean instanceof Student) {
		    stu = (Student) bean;
		    stu.setName("Jack");
	    }

        //若只是修改bean的属性则,即使return null也生效。因为直接对bean的引用对象进行修改
        return bean;
    }

    @Nullable
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("对初始化之后的Bean进行处理,beanName:"+beanName);
        //容器中每一个Bean对象初始化后,都会传递进入此方法

        if("student".equals(beanname) || bean instanceof Student) {         
          //生成bean的包装类/代理类对象后,必须把其新引用返回才能替换容器中的Bean
          //注意:1 必须把其新引用返回才生效; 2 此时Bean的类型变为StudentProxy
          return  new StudentProxy(bean);
        }
 
	return bean;
    }
}

源码中执行逻辑

传入当前bean引用existingBean,遍历BeanPostProcessor.postProcessBeforeInitialization若返回值不为null则替换Bean引用继续执行,若为null则终止遍历返回result。返回的result会替换Bean引用。

//bean初始化执行BeanPostProcessor
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
//postProcessAfterInitialization同理
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
                                //立即返回当前引用
				return result;
			}
                        //bean引用被替换
			result = current;
		}
		return result;
	}

 

简单用例: 

下面的代码我们做的一个事情就是:数据库配置文件我们经常写的是用户名和密码,但是这样并不安全,所以我们在配置文件中使用加密带加盐的密码
利用下面的类进行解密,当然目前开源的项目中有这样的一个组件技术:jasypt-spring-boot-starter大家可以去了解一下
@Component
@Slf4j
public class PwdDecodeExtension implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        /**
         * 注意这里我们对bean做了修改之后要把这个bean返回回去,这样的话我们修改的bean才会被重新的添加到ioc
         * 的容器当中,我们做的修改才会生效
         */
        System.err.println(beanName);

        if (bean instanceof DruidDataSource){
            DruidDataSource dataSource = (DruidDataSource) bean;
            String password = dataSource.getPassword();
            // 在这里我们可以对这个密码进行一系列的操作,这个怎么去做,相信你自有办法
            log.info("数据库的密码=====>{}",password);
        }
        return bean;
    }
}

 

在BeanFactory后处理器执行postProcessBeanFactory方法后,Spring开始实例化BeanPostProcessor。若查看ClassPathXmlApplicationContext的源码会发现其refresh方法。

public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            //创建BeanFactory容器,解析XML封装到BeanDefinition,此时Bean不实例化
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                //BeanFactoryPostProcessor执行postProcessBeanFactory()
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //注册BeanPostProcessors,监控Bean初始化
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

 

普通Bean生命周期


一个bean的生命周期可以简述为以下几步

  • 实例化前,Spring容器会先实例化其需要依赖注入的,但是不再缓存中的Bean
  • 实例化bean对象(通过构造方法或者工厂方法)。
  • 设置bean对象属性(setter()等 包含:配置的属性+@AutoWired)
  • 检查Aware接口(BeanNameAware、BeanFactoryAware、ApplicationContextAware)
  • 如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
  • 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory(BeanFactory beanFactory)方法,传入工厂自身
  • 如果Bean实现了ApplicationContextAware接口,工厂调用setApplicationContext(ApplicationContext applicationContext)方法传入Spring应用上下文
  • 将Bean实例传递给BeanPostProcessor处理器(实现了此容器级接口的Bean)的postProcessBeforeInitialization(Object bean, String beanname)方法
  • 初始化Bean对象 调用的初始化方法 afterPropertiesSet+init-method  (@RequestMapping注册在此完成https://blog.csdn.net/shanchahua123456/article/details/89816167
  • 将Bean实例传递给BeanPostProcessor处理器(实现了此容器级接口的Bean))的postProcessAfterInitialization(Object bean, String beanname)方法
  • 使用Bean
  • 容器关闭之前,调用Bean的销毁方法
     


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值