八spring生命之器之BeanPostProcessor

Posted heliusking

tags:

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

BeanPostProcessor我们一般称为Bean的后置处理器,它与我们前面介绍的InitialingBeaninit-method等一样,都是在bean的初始化时被调用,具体的用法我们在举例中进行学习。

要使用BeanPostProcessor非常简单,只要实现这个接口即可。

在此之前,我们来先看下我们的Cat类,我们的目的是将这个Cat注册进spring的ioc容器中,并让这个BeanPostProcessor起到作用。

public class Cat implements InitializingBean,DisposableBean 
    
    public Cat()
        System.out.println("cat constructor...");
    

    @Override
    public void destroy() throws Exception 
        // TODO Auto-generated method stub
        System.out.println("cat...destroy...");
    

    @Override
    public void afterPropertiesSet() throws Exception 
        // TODO Auto-generated method stub
        System.out.println("cat...afterPropertiesSet...");
    
    
    
    //对象创建并赋值之后调用
    @PostConstruct
    public void initMethod()
        System.out.println("Cat....@PostConstruct...");
    
    
    //容器移除对象之前
    @PreDestroy
    public void detoryMethod()
        System.out.println("Cat....@PreDestroy...");
    
    
    public void initCat() 
        System.out.println("Cat.initCat()......");
    
    
    public void cleanup() 
        System.out.println("Cat.cleanup()......");
    

再来看下我们的配置类

@Configuration
public class MainConfigOfLifeCycle 
    
//  @Scope("prototype")
    @Bean(initMethod="initCat",destroyMethod="cleanup")
    public Cat cat()
        return new Cat();
    
    
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() 
        return new MyBeanPostProcessor();
    

结合之前学习过的内容, 就能知道我们为这个Cat类应用了三种初始化及销毁方法,

分别是@PostConstruct@Predestroy

还有就是实现 InitializingBean,DisposableBean这两个接口的afterPropertiesSet()destro()方法

另外就是标注在@Bean(initMethod="initCat",destroyMethod="cleanup")定义的两个方法,也存在于Cat类中,


现在我们就要加入BeanPostProcessor

/**
 * 后置处理器:初始化前后进行处理工作
 * 将后置处理器加入到容器中,只需要继承BeanPostProcessor接口并实现其两个方法即可。
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor 

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    


现在一切具备,再写一个测试方法:

    @Test
    public void test01()
        //1、创建ioc容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("容器创建完成...");
        
        //applicationContext.getBean("car");
        //关闭容器
        applicationContext.close();
    

观察控制台打印结果

cat constructor...// 创建cat对象
postProcessBeforeInitialization...cat=>com.atguigu.bean.Cat@6591f517 //在所有初始化方法之前被调用
Cat....@PostConstruct...
cat...afterPropertiesSet...
Cat.initCat()......
postProcessAfterInitialization...cat=>com.atguigu.bean.Cat@6591f517// 在所有初始化方法之后被调用
容器创建完成...
Cat....@PreDestroy...// 销毁方法不需要关注
cat...destroy...
Cat.cleanup()......

通过上面这个例子,已经很显然BeanPostProcessor的用法,它是在容器中bean初始化前后被调用。


源码调用分析:

技术图片

我们在eclipse中启用debug模式,
技术图片

看看这个方法的源码,直接在方法注释中进行分析

    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;
        if (mbd == null || !mbd.isSynthetic()) 
            // 初始化前调用BeanPostProcessor
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        

        try 
            //初始化方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        
        catch (Throwable ex) 
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        

        if (mbd == null || !mbd.isSynthetic()) 
            // 初始化后调用BeanPostProcessor
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        
        return wrappedBean;
    

就看到这里,里面内容比较多,可以进invokeInitMethods看看几个初始化方法的调用顺序,JSR-250注解@PostConstruct是如何起作用的等等 ,我们这里只是来源码中找找它在源码中的位置。


又是一个夜晚,一船的清梦。

以上是关于八spring生命之器之BeanPostProcessor的主要内容,如果未能解决你的问题,请参考以下文章

Spring任务调度器之Task的使用

形而上者谓之道,形而下者谓之器

死磕 Spring----- IOC 之 深入分析 InitializingBean 和 init-method

8 创建渲染更新销毁八个生命周期函数

python的重重之器(生成器迭代器装饰器)

生命游戏