zno2

Spring bean life cycle

 

 一、概要

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

 

posted on 2024-02-24 18:30  zno2  阅读(26)  评论(0编辑  收藏  举报

导航