首页 > 其他分享 >Spring bean life cycle

Spring bean life cycle

时间:2024-02-24 18:33:18浏览次数:23  
标签:life Spring springframework bean loadOrder import org Foo public

 

 一、概要

org.springframework.beans.factory.BeanFactory

Bean factory implementations should support the standard bean lifecycle interfacesas far as possible. The full set of initialization methods and their standard order is:
1. BeanNameAware's setBeanName
2. BeanClassLoaderAware's setBeanClassLoader
3. BeanFactoryAware's setBeanFactory
4. ResourceLoaderAware's setResourceLoader(only applicable when running in an application context)
5. ApplicationEventPublisherAware's setApplicationEventPublisher(only applicable when running in an application context)
6. MessageSourceAware's setMessageSource(only applicable when running in an application context)
7. ApplicationContextAware's setApplicationContext(only applicable when running in an application context)
8. ServletContextAware's setServletContext(only applicable when running in a web application context)
9. postProcessBeforeInitialization methods of BeanPostProcessors
10. InitializingBean's afterPropertiesSet
11. a custom init-method definition
12. postProcessAfterInitialization methods of BeanPostProcessors 

On shutdown of a bean factory, the following lifecycle methods apply:
1. DisposableBean's destroy
2. a custom destroy-method definition

 

 二、实测结果

1. 提前抛出结果

BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry#1
BeanFactoryPostProcessor#postProcessBeanFactory#2
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation#3
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation#4
InstantiationAwareBeanPostProcessor#postProcessPropertyValues#5
Foo#setName#6
BeanNameAware#setBeanName#7
BeanClassLoaderAware#setBeanClassLoader#8
BeanFactoryAware#setBeanFactory#9
ResourceLoaderAware#setResourceLoader#10
ApplicationEventPublisherAware#setApplicationEventPublisher#11
MessageSourceAware#setMessageSource#12
ApplicationContextAware#setApplicationContext#13
BeanPostProcessor#postProcessBeforeInitialization#14
InitializingBean#afterPropertiesSet#15
Foo#customInit#16
BeanPostProcessor#postProcessBeforeInitialization#17
Foo#getName#19
FooTest#test#18It is a foo !
DisposableBean#destroy#20
Foo#customDestroy#21

 

2. 顺序由谁决定的

org.springframework.context.support.AbstractApplicationContext#refresh()

三、具体示例

pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.1.9.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.1.9.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

 

bean configuration:

    <bean class="cn.zno.bean.OneBeanDefinitionRegistryPostProcessor"></bean>
    <bean class="cn.zno.bean.OneInstantiationAwareBeanPostProcessor"></bean>
    

    <bean id="foo" class="cn.zno.bean.Foo" init-method="customInit" destroy-method="customDestroy">
        <property name="name" value="It is a foo !"></property>
    </bean>

 

java bean:

package cn.zno.bean;

import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
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 org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;

public class Foo implements 
    
     BeanNameAware, // 获取<bean id=.. /> 其中id对应的值,如果不存在id,取name属性值,均不存在 cn.zno.bean.Foo#0
     BeanClassLoaderAware, // 获取该bean 的 ClassLoader
     BeanFactoryAware, // 获取 BeanFactory
     ResourceLoaderAware, // 获取 ResourceLoader
     ApplicationEventPublisherAware, // 获取 ApplicationEventPublisher
     MessageSourceAware, // 获取 MessageSource
     ApplicationContextAware, // 获取 ApplicationContext
     InitializingBean, // setter 执行完毕后执行
     DisposableBean // 工厂销毁时执行
     
    {

    public static AtomicInteger loadOrder = new AtomicInteger();

    private String name;

    public String getName() {
        System.out.println("Foo#getName#" + Foo.loadOrder.incrementAndGet());
        return name;
    }

    public void setName(String name) {
        System.out.println("Foo#setName#" + Foo.loadOrder.incrementAndGet());
        this.name = name;
    }

    public void customInit() {
        System.out.println("Foo#customInit#" + Foo.loadOrder.incrementAndGet());
    }

    public void customDestroy() {
        System.out.println("Foo#customDestroy#" + Foo.loadOrder.incrementAndGet());
    }


    @Override
    public void setBeanName(String name) {
        System.out.println("BeanNameAware#setBeanName#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware#setApplicationContext#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        System.out.println("MessageSourceAware#setMessageSource#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("ApplicationEventPublisherAware#setApplicationEventPublisher#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("ResourceLoaderAware#setResourceLoader#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware#setBeanFactory#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("BeanClassLoaderAware#setBeanClassLoader#" + Foo.loadOrder.incrementAndGet());
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean#afterPropertiesSet#" + Foo.loadOrder.incrementAndGet());
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean#destroy#" + Foo.loadOrder.incrementAndGet());
    }
    
}
package cn.zno.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

public class OneBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor#postProcessBeanFactory#" + Foo.loadOrder.incrementAndGet());

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry#" + Foo.loadOrder.incrementAndGet());

    }

}

 

package cn.zno.bean;

import java.beans.PropertyDescriptor;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

public class OneInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("foo"))
        System.out.println("BeanPostProcessor#postProcessBeforeInitialization#" + Foo.loadOrder.incrementAndGet());
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("foo"))
            System.out.println("BeanPostProcessor#postProcessBeforeInitialization#" + Foo.loadOrder.incrementAndGet());
        return bean;
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("foo"))
            System.out.println("InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation#" + Foo.loadOrder.incrementAndGet());
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("foo"))
            System.out.println("InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation#" + Foo.loadOrder.incrementAndGet());
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
            String beanName) throws BeansException {
        if(beanName.equals("foo"))
            System.out.println("InstantiationAwareBeanPostProcessor#postProcessPropertyValues#" + Foo.loadOrder.incrementAndGet());
        return pvs;
    }


}

 

package cn.zno.bean;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/root/private-root.xml" })
public class FooTest {

    @Autowired
    private Foo foo;

    @Test
    public void test() {
        System.out.println("FooTest#test#" + Foo.loadOrder.incrementAndGet() + foo.getName());
    }

}

 

 

 

aware 

/ə'weə/  having or showing knowledge or understanding or realization or perception

你需要啥,只需要实现对应的接口,你就可以使用了

 

post

/pəʊst/ any particular collection of letters or packages that is delivered

 为什么叫postProcess ,就是参数中的引用对象交给该方法来修改

你想改啥,通过啥做啥,只需要实现对应的接口就可以了

 

 

 

四、实际应用

1. mabatis 自动配置所有 mapper 的 BeanDefinition

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { ...

这个Processor的威力有多大,获取不到env ,需要使用字符串而非引用指定sqlSessionFactory ,描述如下

mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");

弃用了一个方法

 @Deprecated
  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
  }

 

Specifies which SqlSessionFactory to use in the case that there is more than one in the spring context. Usually this is only needed when you have more than one datasource. 

Note bean names are used, not bean references. This is because the scanner loads early during the start process and it is too early to build mybatis object instances.

 

 

 

2. 

五、FactoryBean

稍作修改

<?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 class="cn.zno.bean.OneBeanDefinitionRegistryPostProcessor"></bean>
    <bean class="cn.zno.bean.OneBeanPostProcessor"></bean>
    

    <bean id="foo" class="cn.zno.bean.FooFactoryBean" >
        <property name="attr1" value="It is a foo !"></property>
    </bean>
</beans>
package cn.zno.bean;

import org.springframework.beans.factory.FactoryBean;

public class FooFactoryBean implements FactoryBean<Foo>{
    
    private String attr1;
    
    public String getAttr1() {
        return attr1;
    }

    public void setAttr1(String attr1) {
        this.attr1 = attr1;
    }

    @Override
    public Foo getObject() throws Exception {
        System.out.println("FooFactoryBean#getObject#" + Foo.loadOrder.incrementAndGet());
        Foo foo = new Foo();
        foo.setName(attr1);
        return foo;
    }

    @Override
    public Class<?> getObjectType() {
        System.out.println("FooFactoryBean#getObjectType#" + Foo.loadOrder.incrementAndGet());
        return Foo.class;
    }

    @Override
    public boolean isSingleton() {
        System.out.println("FooFactoryBean#isSingleton#" + Foo.loadOrder.incrementAndGet());
        return true;
    }

}

其余文件保持原样,包括测试类

    @Autowired
    private Foo foo;

    @Test
    public void test() {
        System.out.println("FooTest#test#" + Foo.loadOrder.incrementAndGet() + foo.getName());
    }

结果:

 

 

Foo 实现的接口全部失效!

不过可以让FooFactoryBean 实现其需要的接口

结论:

FactoryBean 是对普通bean的构造函数做了抽象,可以传入特殊参数,比如资源文件等(在工厂中解析加工等复杂操作),最终得到目标对象

补充:

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

 

    @PostConstruct
    public void postConstruct() {
        System.out.println("Foo#postConstruct#" + Foo.loadOrder.incrementAndGet());
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("Foo#preDestroy#" + Foo.loadOrder.incrementAndGet());
    }

 

BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry#1
BeanFactoryPostProcessor#postProcessBeanFactory#2
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation#3
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation#4
InstantiationAwareBeanPostProcessor#postProcessPropertyValues#5
Foo#setName#6
BeanNameAware#setBeanName#7
BeanClassLoaderAware#setBeanClassLoader#8
BeanFactoryAware#setBeanFactory#9
ResourceLoaderAware#setResourceLoader#10
ApplicationEventPublisherAware#setApplicationEventPublisher#11
MessageSourceAware#setMessageSource#12
ApplicationContextAware#setApplicationContext#13
BeanPostProcessor#postProcessBeforeInitialization#14
Foo#postConstruct#15
InitializingBean#afterPropertiesSet#16
Foo#customInit#17
BeanPostProcessor#postProcessBeforeInitialization#18
Foo#getName#20
FooTest#test#19It is a foo !
Foo#preDestroy#21
DisposableBean#destroy#22
Foo#customDestroy#23

 

标签:life,Spring,springframework,bean,loadOrder,import,org,Foo,public
From: https://www.cnblogs.com/zno2/p/10341983.html

相关文章

  • Kafka 集成SpringBoot
    1.环境准备1.Kafka集群环境准备1.准备一个Kafka集群环境并启动Kafka3.6.1集群安装与部署2.创建firstTopic/usr/kafka/kafka_2.13-3.6.1/bin/kafka-topics.sh--bootstrap-server192.168.58.130:9092--create--partitions1--replication-factor3--topicfirst2.Sp......
  • 【Spring】spring事件监听异步处理
    在Spring框架中,ApplicationEventMulticaster接口是用于发布事件的核心组件。要支持异步处理事件,可以通过配置一个能够执行异步任务的TaskExecutor与SimpleApplicationEventMulticaster配合使用。以下是一个配置示例:importorg.springframework.context.annotation.Bean;importo......
  • 【spring】spring事件监听机制
    Spring框架的事件监听机制是基于观察者模式设计的,它允许应用程序的不同组件之间通过发布和订阅事件进行松散耦合的通信。以下是对Spring事件监听机制的基本流程和技术要点:ApplicationEvent:Spring中的所有事件都必须继承自org.springframework.context.ApplicationEvent类,这个......
  • SpringBoot + Redis 的配置及使用
    一、SpringBoot配置Redis1.1pom引入spring-boot-starter-data-redis包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></......
  • Spring Boot 入门
    1、基本介绍简化Spring应用开发的一个框架、整个Spring技术栈的一个大整合;J2EE开发的一站式解决方案;优点:快速创建独立运行的Spring项目以及与主流框架集成;使用嵌入式的Servlet容器,应用无需打成WAR包;starters自动依赖与版本控制;大量的自动配置,简化开发,也可修改默认值;无......
  • SpringMVC学习
    SpringMVC是Spring提供的用于简化web开发的框架。 1.5 Servlet能够响应请求的对象。接收请求,返回响应SpringMVC可以认为是Servlet的封装。  1.6SpringMVC开发流程回顾各种配置。Controller,DispatchServlet, 1.7......
  • VMware Aria Suite Lifecycle 8.16 - 应用生命周期管理
    VMwareAriaSuiteLifecycle8.16-应用生命周期管理请访问原文链接:https://sysin.org/blog/vmware-aria-suite-lifecycle/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org应用生命周期管理VMwareAriaSuiteLifecycle(以前称为vRealizeSuiteLifecycleManage......
  • Spring集成Nacos配置中心
    spring版本4.2.8  nacos:1.1.0 jdk1.8引入依赖<dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-spring-context</artifactId><version>1.1.1</version>......
  • 玩转SpringBoot:动态排除Starter配置,轻松部署
    引言在软件开发中,进行本地单元测试是一项常规且必要的任务。然而,在进行单元测试时,有时需要启动一些中间件服务,如Kafka、Elasticjob等。举例来说,我曾经遇到过一个问题:项目中使用了Redisson锁,但由于Redisson版本较低,在Mac环境下偶尔会报错#RedisConnectionException:Unabletoin......
  • shiro 整合 spring 实战及源码详解
    序言前面我们学习了如下内容:5分钟入门shiro安全框架实战笔记shiro整合spring实战及源码详解相信大家对于shiro已经有了最基本的认识,这一节我们一起来学习写如何将shiro与spring进行整合。spring整合maven依赖<dependencies><dependency><group......