[Spring] Bean lifecycle and application scenarios (annotated edition)

Foreword

Clarify Bean Spring container management process will help us to better develop a more rational design based on needs, improve system scalability and efficiency.

Bean Lifecycle

Below to sort Bean Spring container life cycle by a simple example.

We from the whole to the details, first of all is to start a container loaded Bean, it's a whole process.

/**
 * 测试 Spring Bean 生命周期
 * @author zyj
 */
public class LifeCycleTest {
    @Test
    public void testLifeCycle() {
        // 通过注解开启容器,并加载Bean
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(GlobalConfig.class);
        // 关闭容器
        context.close();
    }
}

@Configuration
public class GlobalConfig {
    @Bean
    public Calculator calculator() {
        return new Calculator();
    }
    /**
     * @Order:加载到容器的优先级,越小代表优先级越高
     * @return
     */
    @Order(0)
    @Bean
    public FullyBeanPostProcessor fullyBeanPostProcessor() {
        return new FullyBeanPostProcessor();
    }
}

Then take a look at when the container is loaded Bean have done what treatment.

We need to join Bean Spring-specific interface, these interfaces can be seen as intervention in the process of loading to the developers Bean's entrance.

public class Calculator implements BeanNameAware, ApplicationContextAware {

    public Calculator() {
        System.out.println("<<<构造器执行>>>");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("<<<BeanNameAware.setBeanName执行>>>");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("<<<ApplicationContextAware.setApplicationContext执行>>>");
    }

    @PostConstruct
    public void init() {
        System.out.println("<<<@PostConstruct执行>>>");
    }

	@PreDestroy
    public void destroy() {
        System.out.println("<<<@PreDestroy执行>>>");
    }
}

From here you can see the code has the following interfaces and notes:

  • BeanNameAware: Get the current name in the container Bean
  • ApplicationContextAware: The current injected into the container Bean
  • @PostConstruct: Initialization method (corresponding to the init-method Spring configuration file, the interface InitializingBean)
  • @PreDestroy: Destruction method (corresponding to destroy-method Spring configuration file, the interface DisposableBean)

Execution order

三月 06, 2020 3:09:52 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4f47d241: startup date [Fri Mar 06 15:09:52 CST 2020]; root of context hierarchy
三月 06, 2020 3:09:52 下午 org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker postProcessAfterInitialization
信息: Bean 'globalConfig' of type [class com.zyj.spring.config.GlobalConfig$$EnhancerBySpringCGLIB$$5aa1013d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

<<<构造器执行>>>
<<<BeanNameAware.setBeanName执行>>>
<<<ApplicationContextAware.setApplicationContext执行>>>
<<<BeanPostProcessor.postProcessBeforeInitialization执行>>>
<<<@PostConstruct执行>>>
<<<BeanPostProcessor.postProcessAfterInitialization执行>>>

三月 06, 2020 3:09:52 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@4f47d241: startup date [Fri Mar 06 15:09:52 CST 2020]; root of context hierarchy

<<<@PreDestroy执行>>>

Process finished with exit code 0

Careful small partner must have noticed BeanPostProcessorthe execution, I Calculatordid not realize this interface, why when loaded will print it?

At first I thought deserved to be implemented by each Bean BeanPostProcessor, so that you can @PostConstructbe treated before and after execution.

But I was wrong, the result is validated when loading the current Bean did not do what it achieved BeanPostProcessor.

After looking for some information, did not know BeanPostProcessorthe usage.

Look at the above configuration class, you may not have been GlobalConfigin FullyBeanPostProcessor.

public class FullyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Calculator) {
            System.out.println("<<<BeanPostProcessor.postProcessBeforeInitialization执行>>>");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Calculator) {
            System.out.println("<<<BeanPostProcessor.postProcessAfterInitialization执行>>>");
        }
        return bean;
    }
}

BeanPostProcessorBe performed by a separate class, class unified by the process performed to determine which of which Bean.

Scenarios

ApplicationContextAware

Action: by which the container can be obtained Spring

Scenario: When the instance and not to Spring management, we can not use automatic injected. For example Utils use Dao, this time can be obtained by Dao assembly held a Spring container.

@Component
public class SpringJobBeanFactory implements ApplicationContextAware {

    private static ApplicationContext applicationContext;
        
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringJobBeanFactory.applicationContext=applicationContext;    
    }
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
    }
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
		if (applicationContext == null){
			return null;
		}
		return (T)applicationContext.getBean(name);
	}
}

使用:

TypeDao typeDao = SpringJobBeanFactory.getBean("typeDao");
Published 107 original articles · won praise 88 · views 260 000 +

Guess you like

Origin blog.csdn.net/Code_shadow/article/details/104696923