随笔-生活工作点滴IT@程序员猿媛

【Spring 笔记】Bean 的生命周期相关整理

2019-10-14  本文已影响0人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

1. 概述

Bean 的生命周期

2. 原理

bean 的实例化

激活 Aware

// AbstractAutowireCapableBeanFactory.java
private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        // BeanNameAware
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        // BeanClassLoaderAware
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        // BeanFactoryAware
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}
Aware 接口 说明
BeanNameAware 对该 bean 对象定义的 beanName 设置到当前对象实例中
BeanClassLoaderAware 将当前 bean 对象相应的 ClassLoader 注入到当前对象实例中
BeanFactoryAware BeanFactory 容器会将自身注入到当前对象实例中,这样当前对象就会拥有一个 BeanFactory 容器的引用。
LoadTimeWeaverAware 加载 Spring Bean 时织入第三方模块,如 AspectJ。
BootstrapContextAware 资源适配器 BootstrapContext,如 JCA,CCI。
ResourceLoaderAware 底层访问资源的加载器。
PortletConfigAware PortletConfig。
PortletContextAware PortletContext。
ServletConfigAware ServletConfig。
ServletContextAware ServletContext。
MessageSourceAware 国际化。
ApplicationEventPublisherAware 应用事件。
NotificationPublisherAware JMX 通知。

BeanPostProcessor

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

InitializingBean 和 init-method

// AbstractAutowireCapableBeanFactory.java
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    // 首先会检查是否是 InitializingBean ,如果是的话需要调用 afterPropertiesSet()
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) { // 安全模式
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    // 属性初始化的处理
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        } else {
            // 属性初始化的处理
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        // 判断是否指定了 init-method(),
        // 如果指定了 init-method(),则再调用制定的init-method
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 激活用户自定义的初始化方法
            // 利用反射机制执行
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

DisposableBean 和 destroy-method

2.1 用例验证

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="test" class="Test" init-method="initMethod" destroy-method="destroyMethdo">
        <property name="test" value="test"/>
    </bean>
</beans>
public class Test implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, BeanPostProcessor,
        InitializingBean, DisposableBean {

    private String test;

    public void setTest(String test) {
        System.out.println("setTest 属性注入....");
        this.test = test;
    }

    public Test() { // 构造方法
        System.out.println("调用构造函数...");
    }

    public void run() {
        System.out.println("run 方法调用...");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("BeanClassLoaderAware 被调用...");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware 被调用...");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("BeanNameAware 被调用...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy 被调用...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet 被调用...");
    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("BeanPostProcessor postProcessBeforeInitialization 被调用...");
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("BeanPostProcessor postProcessAfterInitialization 被调用...");
        return o;
    }

    public void initMethod() {
        System.out.println("init-method 被调用...");
    }

    public void destroyMethdo() {
        System.out.println("destroy-method 被调用...");
    }

    public static void main(String[] args) {
        ClassPathResource resource = new ClassPathResource("spring.xml");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(resource);
        factory.addBeanPostProcessor(new Test());
        Test test = (Test) factory.getBean("test");
        test.run();
        System.out.println("方法调用完成,容器开始关闭....");
        // 关闭容器
        factory.destroySingletons();
    }

}

/**
print 
调用构造函数...
调用构造函数...
setTest 属性注入....
BeanNameAware 被调用...
BeanClassLoaderAware 被调用...
BeanFactoryAware 被调用...
BeanPostProcessor postProcessBeforeInitialization 被调用...
InitializingBean afterPropertiesSet 被调用...
init-method 被调用...
BeanPostProcessor postProcessAfterInitialization 被调用...
run 方法调用...
方法调用完成,容器开始关闭....
DisposableBean destroy 被调用...
destroy-method 被调用...
**/
上一篇下一篇

猜你喜欢

热点阅读