Spring中bean的创建和生命周期

标签:

本文出自jvm123.com-java技术分享站:http://jvm123.com/2020/03/spring-zhong-bean.html

Bean的创建

从spring源码 AbstractAutowireCapableBeanFactory#doCreateBean 可以看出,spring容器中bean的创建分为三个步骤:

  1. 实例化(createBeanInstance)
  2. 填充属性(populateBean)
  3. 初始化(initializeBean)
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// Allow post-processors to modify the merged bean definition.
		// ...
		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// ...
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}

		// ...

		// Register bean as disposable.
		// ...
		return exposedObject;
        }

实例化阶段,调用了bean的构造方法;初始化时,调用bean的init-method和XxxAware接口方法。如下:

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

		Object wrappedBean = bean;
		
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		// ...
		return wrappedBean;
	}

Bean的生命周期

此外,bean还可以实现InitializingBean、DisposableBean等生命周期接口。如下示例:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

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

/**
 * @author yawn http://jvm123.com
 * 2020/3/23 14:28
 */
public class TestService implements BeanNameAware,
        ApplicationContextAware, InitializingBean, DisposableBean {

    public TestService() {
        System.out.println("-- construct");
    }

    public String test() {
        System.out.println("-- test service method");
        return "index";
    }

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

    public void destroyMethod() {
        System.out.println("-- destroy method");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("-- @PostConstruct method");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("-- @PreDestroy method");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("-- BeanNameAware#setBeanName(), params:s=" + s);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("-- ApplicationContextAware#setApplicationContext(), params:ctx=" + applicationContext);
    }


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

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

输出的执行顺序为:

-- construct
-- BeanNameAware#setBeanName(), params:s=testService
-- ApplicationContextAware#setApplicationContext(), params:ctx=org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@16b2bb0c, started on Mon Mar 23 16:41:55 CST 2020
-- @PostConstruct method
-- InitializingBean#afterPropertiesSet()
-- init method
: Netty started on port(s): 8080
: Started DemoWebfluxApplication in 3.289 seconds (JVM running for 3.962)
-- test service method
Disconnected from the target VM, address: '127.0.0.1:58130', transport: 'socket'
-- @PreDestroy method
-- DisposableBean#destroy()
-- destroy method

Post processor(后处理器)

Post processor(后处理器)是容器级别在bean的创建过程中对bean进行操作的处理器。具体在实例化Instantiation和初始化Initialization时,分别有如下处理器:

  • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
  • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()
  • BeanPostProcessor#postProcessBeforeInitialization()
  • BeanPostProcessor#postProcessAfterInitialization()

示例如下:

package com.jvm123.demo.lifecycle;

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

/**
 * @author yawn http://jvm123.com
 * 2020/3/23 15:23
 */
@Component
public class ContainerLifeCycle
        implements InstantiationAwareBeanPostProcessor, BeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("--- InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(), params:beanName=" + beanName);
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("--- InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(), params:beanName=" + beanName);
        return false;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--- BeanPostProcessor#postProcessBeforeInitialization(), params:beanName=" + beanName);
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--- BeanPostProcessor#postProcessAfterInitialization(), params:beanName=" + beanName);
        return null;
    }
}

输出顺序如下:

--- InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(), params:beanName=indexController
--- InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(), params:beanName=indexController
--- BeanPostProcessor#postProcessBeforeInitialization(), params:beanName=indexController
--- BeanPostProcessor#postProcessAfterInitialization(), params:beanName=indexController

--- InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(), params:beanName=testService
-- construct
--- InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(), params:beanName=testService
-- BeanNameAware#setBeanName(), params:s=testService
-- ApplicationContextAware#setApplicationContext(), params:ctx=org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@3f57bcad, started on Mon Mar 23 16:51:01 CST 2020
--- BeanPostProcessor#postProcessBeforeInitialization(), params:beanName=testService
-- InitializingBean#afterPropertiesSet()
-- init method
--- BeanPostProcessor#postProcessAfterInitialization(), params:beanName=testService

Disconnected from the target VM, address: '127.0.0.1:58375', transport: 'socket'
-- @PreDestroy method
-- DisposableBean#destroy()
-- destroy method

发表评论