SpringSpring中BeanPostProcessor

Posted 九师兄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringSpring中BeanPostProcessor相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

1.概述

转载:Spring中BeanPostProcessor

对文章:SpringBoot : 定制化Bean的利器:BeanPostProcessor & BeanFactoryPostProcessor 的一个补充。

测试所使用的Spring版本:4.3.12.RELEASE

一、bean的生命周期:创建—>初始化—>销毁

容器管理 bean 的生命周期,我们可以自定义初始化和销毁方法,容器在 bean 进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。

1、bean的创建:

单实例:在容器启动时创建对象;
多实例:在每次获取时创建对象。

2、bean的初始化:

单实例:对象创建完成,并赋值好,调用初始化方法
多实例:获取对象时,创建对象,赋值,然后调用初始化方法

3、bean的销毁:

单实例:容器关闭时销毁
多实例:容器不会管理这个bean,容器不会调用销毁方法。

二、插手初始化/销毁过程的四种操作方式:

1、指定初始化和销毁方法:通过 @Bean 注解指定 init-method 和 destroy-method

第一步:实体类

@Component
public class Car {
 
    public Car() {
        System.out.println("car constructor...");
    }
 
    public void init() {
        System.out.println("car ... init...");
    }
 
    public void detory() {
        System.out.println("car ... detory...");
    }
 
}

第二步:配置

@Configuration
public class MainConfigOfLifeCycle {
	
	//@Scope("prototype")   //多实例
	@Bean(initMethod="init",destroyMethod="detory")
	public Car car(){
		return new Car();
	}
 
}

第三步:测试

public class IOCTest_LifeCycle {
	
	@Test
	public void test01(){
		//创建 IOC 容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
		System.out.println("容器创建完成...");
		
		//applicationContext.getBean("car");  //多实例测试用
		//关闭容器
		applicationContext.close();
	}
 
}

第四步:结果

六月 03, 2019 2:28:08 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Mon Jun 03 14:28:08 CST 2019]; root of context hierarchy
六月 03, 2019 2:28:09 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
car constructor...
car ... init...
容器创建完成...
六月 03, 2019 2:28:09 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Mon Jun 03 14:28:08 CST 2019]; root of context hierarchy
car ... detory...

由上可看出,对于单实例的 bean,容器创建时执行了构造方法和初始化方法,容器创建完成后可直接使用;容器关闭时执行销毁方法。而对于多实例来说,容器创建时不会执行bean的构造方法和初始化方法,只有在使用到bean的时候,才会去执行构造方法和初始化方法,容器关闭时,也不会执行销毁方法。(这里就不贴结果了,有兴趣自己测试就行)

2、通过让 Bean 实现 InitializingBean (定义初始化逻辑),DisposableBean(定义销毁逻辑)

第一步:实体类

@Component
public class Cat implements InitializingBean,DisposableBean {
	
	public Cat(){
		System.out.println("cat constructor...");
	}
 
	public void destroy() throws Exception {
		System.out.println("cat...destroy...");
	}
 
	public void afterPropertiesSet() throws Exception {
		System.out.println("cat...afterPropertiesSet...");		
	}
}

第二步:配置

@Configuration
public class MainConfigOfLifeCycle {
	@Bean
	public Cat cat(){
		return new Cat();
	}
}

第三步:测试

public class IOCTest_LifeCycle {
	
	@Test
	public void test01(){
		//创建 IOC 容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
		System.out.println("容器创建完成...");
		
		//applicationContext.getBean("cat");  //多实例测试用
		//关闭容器
		applicationContext.close();
	}
 
}

结果跟之前的是一样的,不再多说了。

3、使用 JSR250:@PostConstruct、@PreDestroy

  • @PostConstruct:在 bean 创建完成并且属性赋值完成后执行初始化方法;
  • @PreDestroy:在容器销毁 bean 之前通知我们进行清理工作。

实体类如下,其他的操作和上面相同。

@Component
public class Dog {
	
	public Dog(){
		System.out.println("dog constructor...");
	}
	
	@PostConstruct
	public void init(){
		System.out.println("Dog....@PostConstruct...");
	}
	
	@PreDestroy
	public void detory(){
		System.out.println("Dog....@PreDestroy...");
	}
 
}

4、BeanPostProcessor【interface】:bean 的后置处理器

在 bean 初始化前后进行一些处理工作:

  • postProcessBeforeInitialization:在初始化之前工作
  • postProcessAfterIntialization:在初始化之后工作
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
 
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
		return bean;
	}
 
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
		return bean;
	}
 
}
 
@Configuration
public class MainConfigOfLifeCycle {
 
	//@Scope("prototype")   //多实例
	@Bean
	public Dog dog(){
		return new Dog();
	}
 
	@Bean
	public MyBeanPostProcessor myBeanPostProcessor(){
		return new MyBeanPostProcessor();
	}
}

结果:

//省略
dog constructor...            //构造方法
postProcessBeforeInitialization...dog=>com.wyq.bean.Dog@1e67a849    //初始化之前
Dog....@PostConstruct...         //初始化
postProcessAfterInitialization...dog=>com.wyq.bean.Dog@1e67a849     //初始化之后
容器创建完成...
六月 03, 2019 3:32:25 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Mon Jun 03 15:32:24 CST 2019]; root of context hierarchy
Dog....@PreDestroy...

三、BeanPostProcessor原理

1、作用:在 bean 初始化前后进行其他操作。

BeanPostProcessor.postProcessBeforeInitialization
初始化...
BeanPostProcessor.postProcessAfterInitialization

2、初始化之前/之后具体是什么时间?

断点调试,慢慢看:

(1)首先是创建 IOC 容器:new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class)

(2)紧接着是执行构造方法:

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}

这里调用了 refresh() 方法,刷新容器。

(3)看一下 refresh() 方法

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);
 
            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);//注意
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }
 
                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }
 
        }
    }

(4)refresh 中 调用了 finishBeanFactoryInitialization(beanFactory)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    //省略
    beanFactory.preInstantiateSingletons();
}

(5)finishBeanFactoryInitialization 中调用 preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {
    //......
                if (this.isFactoryBean(beanName)) {
                    //省略...
                } else {
                    this.getBean(beanName);
                }
            }
        }
    }

(6)preInstantiateSingletons 调用 getBean,getBean 又调用 getSingleton

    public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }
 
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        //......
        if (sharedInstance != null && args == null) {
            //......
        } else {
            //......
            try {
                //......
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    //......
                } else {
                    //......
                }
            } catch (BeansException var23) {
                //......
            }
        }
 
        //......
    }

(7)getSingleton 中调用 getObject,由于是第一次,容器中并没有 bean,所以调用 createBean 创建 bean

    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        //......
 
        Object beanInstance;
        //......
 
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
 
        return beanInstance;
    }

(8)如何创建 bean,看一下 doCreateBean 方法,调用 initializeBean 初始化了 bean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        //......
 
        Object exposedObject = bean;
 
        try {
            //这个也要注意,后面要说
            this.populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                //初始化bean
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            }
        } catch (Throwable var18) {
            //......
        }
 
        //......
        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            //......
        }
    }

(9)initializeBean 中调用了后置处理器 BeanPostProcessor

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        //......
 
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //这里调用后置处理器
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }
        try {
            //执行初始化方法
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            //调用后置处理器
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        //......
 
        return wrappedBean;
    }
 
 
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        Iterator var4 = this.getBeanPostProcessors().iterator();
        /*
        遍历得到容器中所有的BeanPostProcessor,挨个执行beforeInitailization
        一旦返回null,跳出for循环,不会执行后面的BeanPostProcessor
        */
        do {
            if (!var4.hasNext()) {
                return result;
            }
 
            BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        } 以上是关于SpringSpring中BeanPostProcessor的主要内容,如果未能解决你的问题,请参考以下文章

SpringSpring JDBCTemplate

SpringSpring之注解

SpringSpring MVC原理及配置详解

SpringSpring MVC原理及配置详解

SpringSpring MVC原理及配置详解

SpringSpring MVC原理及配置详解