• 八、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是如何起作用的等等 ,我们这里只是来源码中找找它在源码中的位置。


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

    你所看得到的天才不过是在你看不到的时候还在努力罢了!
  • 相关阅读:
    windows7通过Dns.GetHostAddresses(Dns.GetHostName())获得ipv6地址转换到ipv4
    题解 P3829 【[SHOI2012]信用卡凸包】
    点积与叉积
    点分治
    珂朵莉树
    NOIP2020模拟赛(二十五)7.26 结题报告
    树连剖分
    NOIP2020模拟赛(拾)解题报告
    题解 P2538 【[SCOI2008]城堡】
    模拟退火
  • 原文地址:https://www.cnblogs.com/heliusKing/p/11391271.html
Copyright © 2020-2023  润新知