暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring注解驱动开发(二)-Bean的生命周期

rocklei123的技术点滴 2018-12-27
258

title: Spring注解驱动开发(二)-Bean的生命周期
author: rocklei123
tags:

  • Annotation

  • Spring

  • Java
    categories: Spring
    date: 2018-12-09 20:40:48


Bean的生命周期:
bean创建---初始化----销毁的过程

容器管理bean的生命周期;
我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。

1. 指定初始化和销毁方法

1.1 xml方式

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

1.2 注解方式

可通过@Bean(initMethod = "init",destroyMethod = "destroy")指定初始化及销毁方法,通过测试可以确定:

构造对象

  • 单实例:在容器启动的时候创建对象

  • 多实例:在每次获取的时候创建对象

初始化

对象创建完成,并赋值好,调用初始化方法。

销毁:

  • 单实例:容器关闭的时候

  • 多实例:容器不会管理这个bean;容器不会调用销毁方法;

1.2.1 单实例情况测试

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...");
    }
}
@Configuration
public class MainConfigLifeCycle {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }
}
@Test
public void testLifeCycle() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigLifeCycle.class);
    System.out.println("IOC 容器创建完成!");
    context.close();
}

通过以下测试结果可以确定Spring容器管理(单实例)Bean的过程为:

Bean构造方法-->Bean init()-->IOC容器创建完成-->关闭容器-->Bean销毁

十二月 09, 2018 9:25:32 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Sun Dec 09 21:25:32 CST 2018]; root of context hierarchy
Car...Constructor...
Car...init...
IOC 容器创建完成!
十二月 09, 2018 9:25:34 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Sun Dec 09 21:25:32 CST 2018]; root of context hierarchy
Car...destroy...

1.2.2多实例情况下测试

@Configuration
public class MainConfigLifeCycle {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    @Scope(value = "prototype")
    public Car car() {
        return new Car();
    }
}
@Test
public void testLifeCycle() {
    AnnotationConfigApplicationContext context = new         AnnotationConfigApplicationContext(MainConfigLifeCycle.class);
    System.out.println("IOC 容器创建完成!");
    Car car = (Car) context.getBean("car");
    System.out.println(car);
    context.close();
}

通过以下测试结果可以确定Spring容器管理(多实例)Bean的过程为(多实例注意:不会调用销毁方法):

IOC容器创建完成-->Bean构造方法-->Bean init()-->关闭容器

十二月 14, 2018 10:11:55 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 10:11:55 CST 2018]; root of context hierarchy
IOC 容器创建完成!
Car...Constructor...
十二月 14, 2018 10:11:56 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 10:11:55 CST 2018]; root of context hierarchy
Car...init...
com.rocklei123.bean.Car@77e4c80f

2. 实现InitializingBean和DisposableBean接口

Bean实现InitializingBean(定义初始化逻辑);重写afterPropertiesSet()方法,表示构造方法完成后,并且属性赋值完成后执行该方法

DisposableBean(定义销毁逻辑);容器销毁时调用

测试代码:

//实体类
package com.rocklei123.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class Cat implements InitializingBeanDisposableBean {

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

    @Override
    public void destroy() throws Exception {
        System.out.println("cat...destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat...afterPropertiesSet...");
    }
}

//配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(value = "com.rocklei123.bean")
public class MainConfigLifeCycle {

}

//测试类
@Test
public void testLifeCycleByInterface() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigLifeCycle.class);
    System.out.println("IOC 容器创建完成!");
    Cat cat = (Cat) context.getBean("cat");
    System.out.println(cat);
    context.close();
}

测试结果:

十二月 14, 2018 3:27:38 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 15:27:37 CST 2018]; root of context hierarchy
cat...constructor...
cat...afterPropertiesSet...
十二月 14, 2018 3:27:41 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 15:27:37 CST 2018]; root of context hierarchy
IOC 容器创建完成!
com.rocklei123.bean.Cat@61009542
cat...destroy...

3. JSR250 @PostConstruct 和@PreDestroy

  • @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法

  • @PreDestroy:在容器销毁bean之前通知我们进行清理工作

示例代码:

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class Dog {

    public Dog() {
        System.out.println("dog...Construct...");
    }

    @PostConstruct
    public  void init(){}{
        System.out.println("dog...init...");
    }

    @PreDestroy
    public void destory(){
        System.out.println("dog...destory...");
    }
}

测试结果:

十二月 14, 2018 3:33:03 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 15:33:03 CST 2018]; root of context hierarchy
cat...constructor...
cat...afterPropertiesSet...
dog...init...
dog...Construct...
十二月 14, 2018 3:33:07 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 15:33:03 CST 2018]; root of context hierarchy
IOC 容器创建完成!
com.rocklei123.bean.Dog@2ea6137
dog...destory...
cat...destroy...

4. 实现BeanPostProcessor接口

BeanPostProcessor【interface】:Spring 为我们提供的bean的后置处理器;在bean初始化前后进行一些处理工作;同时可以对这个bean进行包装并返回。

  • postProcessBeforeInitialization:在任何初始化方法调用之前工作

  • postProcessAfterInitialization:在任何初始化方法调用之后工作

package com.rocklei123.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @ClassName: MyBeanPostProcessor
 * @Author: rocklei123
 * @Date: 2018/12/14 15:39
 * @Description: 后置处理器:初始化前后进行处理工作,将后置处理器加入到容器中
 * @Version 1.0
 */

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..." + beanName + "=>" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..." + beanName + "=>" + bean);
        return bean;
    }
}

//测试代码
 @Test
public void testLifeCycleBeanPostProcessor() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigLifeCycle.class);
    System.out.println("IOC 容器创建完成!");
    context.close();
}

测试结果:

十二月 14, 2018 5:09:06 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 17:09:06 CST 2018]; root of context hierarchy
MyBeanPostProcessor...postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerProcessor=>org.springframework.context.event.EventListenerMethodProcessor@7ff2a664
MyBeanPostProcessor...postProcessAfterInitialization...org.springframework.context.event.internalEventListenerProcessor=>org.springframework.context.event.EventListenerMethodProcessor@7ff2a664
MyBeanPostProcessor...postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerFactory=>org.springframework.context.event.DefaultEventListenerFactory@58c1c010
MyBeanPostProcessor...postProcessAfterInitialization...org.springframework.context.event.internalEventListenerFactory=>org.springframework.context.event.DefaultEventListenerFactory@58c1c010
MyBeanPostProcessor...postProcessBeforeInitialization...mainConfigLifeCycle=>com.rocklei123.config.MainConfigLifeCycle$$EnhancerBySpringCGLIB$$a5cb492c@b7f23d9
MyBeanPostProcessor...postProcessAfterInitialization...mainConfigLifeCycle=>com.rocklei123.config.MainConfigLifeCycle$$EnhancerBySpringCGLIB$$a5cb492c@b7f23d9
cat...constructor...
MyBeanPostProcessor...postProcessBeforeInitialization...cat=>com.rocklei123.bean.Cat@3f200884
cat...afterPropertiesSet...
MyBeanPostProcessor...postProcessAfterInitialization...cat=>com.rocklei123.bean.Cat@3f200884
dog...init...
dog...Construct...
MyBeanPostProcessor...postProcessBeforeInitialization...dog=>com.rocklei123.bean.Dog@4d49af10
MyBeanPostProcessor...postProcessAfterInitialization...dog=>com.rocklei123.bean.Dog@4d49af10
十二月 14, 2018 5:09:11 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd: startup date [Fri Dec 14 17:09:06 CST 2018]; root of context hierarchy
IOC 容器创建完成!
dog...destory...
cat...destroy...

5. Bean 生命周期管理方法总结

  • 1)、指定初始化和销毁方法;通过@Bean指定init-method和destroy-method;

  • 2)、通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);

  • 3)、可以使用JSR250;

  • @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法

  • @PreDestroy:在容器销毁bean之前通知我们进行清理工作

  • 4)、BeanPostProcessor【interface】:bean的后置处理器;
    在bean初始化前后进行一些处理工作;

  • postProcessBeforeInitialization:在初始化之前工作

  • postProcessAfterInitialization:在初始化之后工作

6. BeanPostProcessor介绍与原理

BeanPostProcessor 源码:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory
    //给bean进行属性赋值
     protected Object doCreateBean(final String beanNamefinal RootBeanDefinition mbdObject[] argsthrows BeanCreationException 
{
     //
        this.populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        }
    }

    //初始化bean
     protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
                        return null;
                    }
                }, this.getAccessControlContext());
            } else {
                this.invokeAwareMethods(beanName, bean);
            }

            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                //执行初始化前的方法
                wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
            }

            try {
                //执行自定义初始化
                this.invokeInitMethods(beanName, wrappedBean, mbd);
            } catch (Throwable var6) {
                throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
            }

            if (mbd == null || !mbd.isSynthetic()) {
            //执行初始化之后的方法
                wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }

            return wrappedBean;
        }

BeanPostProcessor核心原理总结

populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
initializeBean
{
    applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
    applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

Spring底层大量 BeanPostProcessor 的使用;比如bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor;

6.1 ApplicationContextAwareProcessor 后置处理器

ApplicationContextAwareProcessor 接口,是Spring容器提供获取IOC容器接口,其内部实现也是后置处理器原理。示例代码:

public class Dog implements ApplicationContextAware {
    private ApplicationContext context;

    @Override //业务代码注入IOC容器
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}

7. Bean生命周期总结

  1. 构造(对象创建)

* 单实例:在容器启动的时候创建对象
* 多实例:在每次获取的时候创建对象

  1. BeanPostProcessor.postProcessBeforeInitialization

  2. 初始化:

* 对象创建完成,并赋值好,调用初始化方法。。。

  1. BeanPostProcessor.postProcessAfterInitialization

  2. 销毁:

* 单实例:容器关闭的时候
* 多实例:容器不会管理这个bean;容器不会调用销毁方法;

其实Spring容器整个生命周期还有其他几个步骤,下图给出整个Spring容器管理bean的生命周期。

8.欢迎关注米宝窝,持续更新中,谢谢!

米宝窝 https://rocklei123.github.io/ 


文章转载自rocklei123的技术点滴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论